1. Introduction
In this tutorial, we’ll be discussing Hibernate and the Java Persistence API (JPA) – with a focus on the differences between them.
We’ll start by exploring what JPA is, how it’s used, and the core concepts behind it.
Then, we’ll take a look at how Hibernate and EclipseLink fit into the picture.
2. Object-Relational Mapping
Before we dive into JPA, it’s important to understand the concept of Object-Relational Mapping – also known as ORM.
Object-relational mapping is simply the process of persisting any Java object directly to a database table. Usually, the name of the object being persisted becomes the name of the table, and each field within that object becomes a column. With the table set up, each row corresponds to a record in the application.
3. An Introduction to JPA
The Java Persistence API, or JPA, is a specification that defines the management of relational data in a Java application. The API maps out a set of concepts that defines which objects within the application should be persisted, and how it should persist them.
It’s important to note here that JPA is only a specification and that it needs an implementation to work – but more on that later.
Now, let’s discuss some of the core JPA concepts that an implementation must cover.
3.1. Entity
The javax.persistence.Entity class defines which objects should be persisted to the database. For each persisted entity, JPA creates a new table within the chosen database.
In addition, all chosen entities should define a primary key denoted by the @Id annotation. Together with the @GeneratedValue annotation, we define that the primary key should be automatically generated when the record is persisted to the database.
Let’s take a look a quick example of an entity described by JPA.
@Entity
public class Car {
@GeneratedValue
@Id
public long id;
// getters and setters
}
Remember, this will currently have no effect on the application – JPA doesn’t provide any implementation code.
3.2. Field Persistence
Another core concept of JPA is field persistence. When an object in Java is defined as an entity, all fields within it are automatically persisted as different columns within the entity table.
If there’s a field within a persisted object that we don’t want to persist to the database, we can declare the field transient with the @Transient annotation.
3.3. Relationships
Next, JPA specifies how we should manage relationships between different database tables within our application. As we’ve seen, JPA handles this with annotations. There are four relationship annotations that we need to keep in mind:
- @OneToOne
- @OneToMany
- @ManyToOne
- @ManyToMany
Let’s take a look at how this works:
@Entity
public class SteeringWheel {
@OneToOne
private Car car
// getters and setters
}
In our example above, the SteeringWheel class describes a one to one relationship with our Car class from earlier.
3.4. Entity Manager
Finally, the javax.persistence.EntityManager class specifies operations to and from the database. The EntityManager contains common Create, Read, Update and Delete (CRUD) operations that are persisted to the database.
4. JPA Implementations
With JPA specification defining how and what we should persist, we now need to choose an implementation provider to supply the necessary code. Without such a provider, we would need to implement all of the relevant classes to conform with JPA, and that’s a lot of work!
There are plenty of providers to choose from, with each displaying its own pros and cons. When making a decision on which to use, we should consider a few of the following points:
- Project maturity – how long has the provider been around, and how well documented is it?
- Subprojects – does the provider have any useful subprojects for our new application?
- Community support – is there anyone to help us out when we end up with a critical bug?
- Benchmarking – how performant is the implementation?
While we won’t be going into depth on the benchmarking of different JPA providers, JPA Performance Benchmark (JPAB) contains valuable insight into this.
With that out of the way, let’s take a brief look at some of the top providers of JPA.
5. Hibernate
At its core, Hibernate is an object-relational mapping tool that provides an implementation of JPA. Hibernate is one of the most mature JPA implementations around, with a huge community backing the project.
It implements all of the javax.persistence classes we looked at earlier in the article as well as providing functionality beyond JPA – Hibernate tools, validation, and search. Although these Hibernate-specific APIs may be useful, they are not needed in applications that only require the base JPA functionality.
Let’s take a quick look at what Hibernate offers with the @Entity annotation.
Whilst fulfilling JPA contract, @org.hibernate.annotations.Entity adds additional metadata that goes beyond JPA specification. Doing so allows fine-tuning entity persistence. For example, let’s look at a few annotations offered by Hibernate that extends the functionality of @Entity:
- @Table – allows us to specify the name of the table created for the entity
- @BatchSize – *specifies the batch size when retrieving entities from the table*
It’s also worth noting a few of the extra features that the JPA does not specify, that may prove useful in larger applications:
- Customizable CRUD statements with the @SQLInsert, @SQLUpate and @SQLDelete annotations
- Support for soft deleting
- Immutable entities with the @Immutable annotation
For a deeper dive into Hibernate and Java persistence – head over to our Spring persistence tutorial series.
6. EclipseLink
EclipseLink, built by the Eclipse Foundation, provides an open-sourced JPA implementation. Additionally, EclipseLink supports a number of other persistence standards such as Java Architecture for XML Binding (JAXB).
Simply put, rather than persisting an object to a database row, JAXB maps it to an XML representation.
Next, by comparing the same @Entity annotation implementation, we see that EclipseLink offers again different extensions. Whilst there is no annotation for @BatchSize as we saw earlier, EclipseLink offers other options that Hibernate doesn’t.
For example:
- @ReadOnly – specifies the entity to be persisted is read-only
- @Struct – defines the class to map to a database ‘struct’ type
To read more about what EclipseLink has to offer, head over to our guide on EclipseLink with Spring.
7. Conclusion
In this article, we’ve looked at the Java Persistence API, or JPA.
Finally, we explored how it differs from Hibernate and EclipseLink.