Object-relational impedance mismatch is the friction between an object-oriented domain model and an SQL relational model. Objects can refer to other objects and form networks; a relational database stores values in tables and columns. Persisting an object network therefore requires translating its structure into rows, keys, and SQL data types. section 1.1.3 section 1.4
Users and billing details
A Java User holds a Set<BillingDetails>, and each BillingDetails refers back to its User. In SQL, a USERNAME foreign key in BILLINGDETAILS represents that relationship. This simple case is straightforward to handle with JDBC; the mismatch becomes more apparent as the model gains entities and relationships. section 1.2
The mismatch has several practical dimensions:
- Granularity: an object network must be broken down into database columns and portable SQL values. section 1.4
- Inheritance: SQL tables do not directly provide the class-inheritance mechanism needed to persist a hierarchy, and a foreign key cannot straightforwardly target multiple subtype tables. section 1.2.2
- Identity and associations are further mapping problems, distinct from inheritance and granularity. section 1.2.5
- Data navigation: following associations can trigger one query for a user plus one for each of n billing details—the n+1 selects problem. Fetching too much through a join can instead produce a Cartesian product. section 1.2.5
ORM addresses much of the translation work, including joins and copying JDBC results into objects, but it is not the best tool for every persistence task. Plain SQL and JDBC remain useful for tabular results, reporting, and operations on large sets of data. In Java, JPA provides a persistence specification, Hibernate implements it, and Spring Data can simplify data-access code further. Fetching strategy still matters when navigating object relationships. section 1.1.3 section 1.2.5 section 1.4
Path: Ch01/e-commerce/src/com/manning/javapersistence/ch01/User.java public class User { private String username; private String address; private Set<BillingDetails> billingDetails = new HashSet<>(); // Constructor, accessor methods (getters/setters), business methods } Path: Ch01/e-commerce/src/com/manning/javapersistence/ch01 /BillingDetails.java public class BillingDetails { private String account; private String bankname; private User user; // Constructor, accessor methods (getters/setters), business methods }
Compare the collection and back-reference in the Java classes with their relational representation. section 1.2
CREATE TABLE USERS (
USERNAME VARCHAR(15) NOT NULL PRIMARY KEY,
ADDRESS VARCHAR(255) NOT NULL
);
CREATE TABLE BILLINGDETAILS (
ACCOUNT VARCHAR(15) NOT NULL PRIMARY KEY,
BANKNAME VARCHAR(255) NOT NULL,
USERNAME VARCHAR(15) NOT NULL,
FOREIGN KEY (USERNAME) REFERENCES USERS(USERNAME)
);
See how a foreign key represents the relationship between users and billing details. section 1.2
