The API includes methods to make instances of a mapped domain class persistent, to retrieve an instance of a domain class by its primary identity, to find all instances of domain class and subclasses by a query expressed in terms of the domain class values, and to delete an instance of a domain class from the database. Updates are done in the context of a transaction, by retrieving an instance of a domain class and using domain methods to modify values of the instance.
The domain classes that represent the application’s view of the data stored in the relational database are typically either written by hand or generated from a database schema using a tool. Typically declarative, the mapping relates the domain object model to the relational schema model and is defined before the application runs. Since the domain classes need not contain specific persistence behavior, the classes are often referred to as POJOs (plain old Java objects).
The absence of persistence code allows operation of the persistent classes independent of the persistence aspect. Much of the behavior of the domain classes can thus be tested without access to the database or to the persistence environment. This style of programming encourages separation of concerns and encapsulation.
Many tables map directly to domain classes, such as Employee, Department, Customer, Order, LineItem, Contract, Claim, Product, and so forth. Rows of these tables are mapped to instances of the domain classes. Columns of the tables are mapped to fields of the domain classes.
The so-called impedance mismatch between object and database schema has generated much discussion, for good reason. There are “deceptive similarities” between the two technologies, according to Scott Ambler. 3 Lack of understanding the difference between the technologies can lead to bad design choices and project failure.
The data model in object languages such as Java is not exactly the same as in relational databases, so special care must be taken to prevent problems from arising. For example, the maximum lengths of character columns must be specified in the relational schema, but Java Strings are essentially unbounded.
Floating-point numbers may cause problems, too. Java implements IEEE floating-point numbers; relational databases often have a different representation. The effect is that not all values for floating-point numbers in Java can be stored in the database, and vice versa.
Even fixed-precision decimal numbers may pose problems when mapped to relational schema. Java supports
fixed-precision decimal numbers that are self-describ-ing—that is, each value has a specific precision (number of digits) and scale (number of digits to the right of the decimal point). In the database, however, all numbers in the same column have the same precision and scale.
Mapping between the application domain classes and database schema is, by design, not isomorphic. On the domain model side, certain aspects of the object model are not mapped to the database, including behavior of the classes and class variables. On the relational database side, not all of the tables and columns in every schema in the database are represented in the domain model, nor are stored procedures. Additionally, domain models might have several valid mappings.
Representing a database schema with a domain object model is usually straightforward, especially if the schema is well normalized. With an entity-relationship model of the schema, each entity is mapped to a domain class. Each simple relationship, implemented as a foreign key in the schema, is mapped to a field of a reference type on one side and a field of a multivalued type on the other.
Many complex constructs in the entity-relationship model can be nicely mapped to object-model constructs. For example, a join table in which the columns are foreign keys to two different tables can be mapped to two classes in which each class contains a field, the type of which is a set of objects of the other class type.
On the other hand, storing an arbitrary domain object model in a relational database can be challenging. Models that represent relationships using abstract classes, deep
I nheritance
Person
-firstName : String -lastName : String -middleName : String
Employee
-employeeId : integer -hireDate : date
FullTimeEmployee
-weeklySalary : BigDecimal
PartTimeEmployee
-hourlyWage : BigDecimal
References:
Archives