What is persistence and object/relational mapping all about? You might have heard talk about the "object/relational mismatch". Never fear: Hibernate solves it.
Persistence
Hibernate ORM is concerned with helping your application to achieve persistence. So what’s persistence? Persistence simply means that we would like our program’s data to outlive the current process. For Java developers, this means we would like the state of certain objects to live beyond the scope of the JVM, so that the same state is available in a different JVM, or even in a different program written in a different programming language.
Relational databases
Specifically, Hibernate ORM helps us keep persistent state in a relational database. Relational databases are amazing! Hibernate has been around long enough to have existed through two (or perhaps even three) completely separate generations of database technology claiming to be ready to displace the relational database in enterprise systems. Strangely enough, PostgreSQL is still the king.
The object/relational mismatch
The object/relational impedance mismatch refers to differences in how entities are represented in the relational data model, compared to how they’re represented in an object-oriented programming language. The relational model represents data in a tabular format (quite similar to a spreadsheet), whereas object-oriented languages like Java represent data as an interconnected graph of objects with inheritance and polymorphism.
Writing or reading a graph of objects to or from a relational database exposes us to the following problems.
- Granularity
-
Often we find that an object model has more classes than there are tables in the database. Then we say that the object model is more granular than the relational model.
- Subtypes (inheritance)
-
Inheritance is a natural paradigm in object-oriented programming languages. The relational model doesn’t have inheritance as a first-class construct, but relational data modelling does have standard ways to represent subtyping.
- Identity
-
The relational model defines exactly one notion of "sameness": the primary key. Java, on the other hand, defines both object identity
a==b
and value equalitya.equals(b)
. In particular, it’s common to have more than one object in a given Java program representing the same row of a database table. - Associations
-
Associations are represented as unidirectional references in object-oriented languages, whereas relational databases represent associations via foreign keys. We can’t always be certain of the multiplicity of an association between Java objects just by looking at the Java code. And to represent a bidirectional relationship in Java, we must write code on both sides of the association.
- Data navigation
-
The way we access state in Java is fundamentally different to the how we retrieve data from a relational database. In Java, we navigate associations from one object to the next, walking the object network. But that’s an extremely inefficient way of retrieving relational data, where, instead, we must control latency by minimizing the number of SQL queries, loading related entity data using joins.
Where are we today?
Object/relational mapping is a difficult and subtle problem, and used to be a major source of anguish for enterprise developers. Indeed, it was once called "the Vietnam of computer science". But just as Vietnam is today a dynamic nation with a fast-growing economy, Hibernate has commodified object/relational mapping in Java. Whereas awful custom-written ORM libraries and frameworks used to be found almost everywhere, we now have a common solution which works. Of course, you’ll still meet challenges from time to time, but dealing with persistence is no longer a reason projects fail.