The Jakarta Persistence API (JPA) is a Java specification that bridges the hole between relational databases and object-oriented programming. This two-part tutorial introduces JPA and explains how Java objects are modeled as JPA entities, how entity relationships are outlined, and use JPA’s EntityManager
with the Repository sample in your Java purposes. This provides you all of the fundamentals for saving and loading software state.
Observe that this tutorial makes use of Hibernate because the JPA supplier. Most ideas might be prolonged to different Java persistence frameworks.
Object relations in JPA
Relational databases have existed as a method for storing program knowledge because the Seventies. Whereas builders right now have many alternate options to the relational database, it’s nonetheless broadly utilized in small- and large-scale software program growth.
Java objects in a relational database context are outlined as entities. Entities are objects which can be positioned in tables the place they occupy columns and rows, thereby outliving their existence in this system. Programmers use overseas keys and be a part of tables to outline the relationships between entities—specifically one-to-one, one-to-many, and many-to-many relationships. We use SQL (Structured Question Language) to retrieve and work together with knowledge in particular person tables and throughout a number of tables.
The relational mannequin is flat, whereas object fashions are graphs. Builders can write queries to retrieve knowledge and assemble objects from relational knowledge, and vice versa, however that course of is painstaking and error susceptible. JPA is one technique to resolve that downside.
Object-relations impedance mismatch
You could be acquainted with the time period object-relations impedance mismatch, which refers to this problem of mapping knowledge objects to a relational database. This mismatch happens as a result of object-oriented design shouldn’t be restricted to one-to-one, one-to-many, and many-to-many relationships. As an alternative, in object-oriented design, we consider objects, their attributes and conduct, and the way objects relate. Two examples are encapsulation and inheritance:
- If an object comprises one other object, we outline this by encapsulation—a has-a relationship.
- If an object is a specialization of one other object, we outline this by inheritance—an is-a relationship.
Affiliation, aggregation, composition, abstraction, generalization, realization, and dependencies are all object-oriented programming ideas that may be difficult to map to a relational mannequin.
Put one other means, the easy dot notation in Java: myObject.anotherObject.aProperty
implies a substantial amount of work for a relational knowledge retailer.
ORM: Object-relational mapping
The mismatch between object-oriented design and relational database modeling has led to a category of instruments developed particularly for object-relational mapping (ORM). ORM instruments like Hibernate, EclipseLink, OpenJPA, and MyBatis translate relational database fashions, together with entities and their relationships, into object-oriented fashions. Many of those instruments existed earlier than the JPA specification, however with out a customary their options have been vendor dependent.
First launched as a part of EJB 3.0 in 2006, the Java Persistence API (JPA) was moved to the Eclipse Basis and renamed the Jakarta Persistence API in 2019. It presents a regular technique to annotate objects in order that they are often mapped and saved in a relational database. The specification additionally defines a typical assemble for interacting with databases. Having an ORM customary for Java brings consistency to vendor implementations, whereas additionally permitting for flexibility and add-ons. For example, whereas the unique JPA specification is relevant to relational databases, some vendor implementations have prolonged JPA to be used with NoSQL databases.
Getting began with JPA
The Java Persistence API is a specification, not an implementation: it defines a typical abstraction that you should utilize in your code to work together with ORM merchandise. This part critiques a few of the essential elements of the JPA specification.
You may learn to:
- Outline entities, fields, and first keys within the database.
- Create relationships between entities within the database.
- Work with the
EntityManager
and its strategies.
Defining entities
So as to outline an entity, you have to create a category that’s annotated with the @Entity
annotation. The @Entity
annotation is a marker annotation, which is used to find persistent entities. For instance, for those who needed to create a e book entity, you’d annotate it as follows:
@Entity
public class E-book {
...
}
By default, this entity can be mapped to the E-book desk, as decided by the given class identify. In case you needed to map this entity to a different desk (and, optionally, a selected schema) you could possibly use the @Desk
annotation. Here is how you’d map the E-book
class to a BOOKS
desk:
@Entity
@Desk(identify="BOOKS")
public class E-book {
...
}
If the BOOKS
desk was within the PUBLISHING
schema, you could possibly add the schema to the @Desk
annotation:
@Desk(identify="BOOKS", schema="PUBLISHING")
Mapping fields to columns
With the entity mapped to a desk, your subsequent job is to outline its fields. Fields are outlined as member variables within the class, with the identify of every discipline being mapped to a column identify within the desk. You possibly can override this default mapping by utilizing the @Column
annotation, as proven right here:
@Entity
@Desk(identify="BOOKS")
public class E-book {
personal String identify;
@Column(identify="ISBN_NUMBER")
personal String isbn;
...
}
On this instance, we have accepted the default mapping for the identify
attribute however specified a customized mapping for the isbn
attribute. The identify
attribute can be mapped to the “identify” column, however the isbn
attribute can be mapped to the ISBN_NUMBER column.
The @Column
annotation permits us to outline extra properties of the sector or column, together with size, whether or not it’s nullable, whether or not it should be distinctive, its precision and scale (if it is a decimal worth), whether or not it’s insertable and updatable, and so forth.
Specifying the first key
One of many necessities for a relational database desk is that it should comprise a major key, or a key that uniquely identifies a selected row within the database. In JPA, we use the @Id
annotation to designate a discipline to be the desk’s major key. The first key should be a Java primitive kind, a primitive wrapper resembling Integer
or Lengthy
, a String
, a Date
, a BigInteger
, or a BigDecimal
.
On this instance, we map the id
attribute, which is an Integer
, to the ID column within the BOOKS
desk:
@Entity
@Desk(identify="BOOKS")
public class E-book {
@Id
personal Integer id;
personal String identify;
@Column(identify="ISBN_NUMBER")
personal String isbn;
...
}
It is usually doable to mix the @Id
annotation with the @Column
annotation to overwrite the first key’s column-name mapping.
Entity relationships in JPA
Now that you understand how to outline an entity, let us take a look at create relationships between entities. JPA defines 4 annotations for outlining relationships between entities:
@OneToOne
@OneToMany
@ManyToOne
@ManyToMany
One-to-one relationships
The @OneToOne
annotation is used to outline a one-to-one relationship between two entities. For instance, you could have a Person
entity that comprises a person’s identify, electronic mail, and password, however it’s possible you’ll wish to preserve extra details about a person (resembling age, gender, and favourite coloration) in a separate UserProfile
entity. The @OneToOne
annotation facilitates breaking down your knowledge and entities this fashion.
The Person
class under has a single UserProfile
occasion. The UserProfile
maps to a single Person
occasion.
@Entity
public class Person {
@Id
personal Integer id;
personal String electronic mail;
personal String identify;
personal String password;
@OneToOne(mappedBy="person")
personal UserProfile profile;
...
}
@Entity
public class UserProfile {
@Id
personal Integer id;
personal int age;
personal String gender;
personal String favoriteColor;
@OneToOne
personal Person person;
...
}
The JPA supplier makes use of UserProfile
‘s person discipline to map UserProfile
to Person
. The mapping is specified within the mappedBy
attribute within the @OneToOne
annotation.
One-to-many and many-to-one relationships
The @OneToMany
and @ManyToOne
annotations facilitate totally different sides of the identical relationship. Contemplate an instance the place a e book can have just one writer, however an writer could have many books. The E-book
entity would outline a @ManyToOne
relationship with Writer
and the Writer
entity would outline a @OneToMany
relationship with E-book
:
@Entity
public class E-book {
@Id
personal Integer id;
personal String identify;
@ManyToOne
@JoinColumn(identify="AUTHOR_ID")
personal Writer writer;
...
}
@Entity
public class Writer {
@Id
@GeneratedValue
personal Integer id;
personal String identify;
@OneToMany(mappedBy = "writer")
personal Checklist<E-book> books = new ArrayList<>();
...
}
On this case, the Writer
class maintains a listing of the entire books written by that writer and the E-book
class maintains a reference to its single writer. Moreover, the @JoinColumn
specifies the identify of the column within the E-book
desk to retailer the ID of the Writer
.
Many-to-many relationships
Lastly, the @ManyToMany
annotation facilitates a many-to-many relationship between entities. Here is a case the place a E-book
entity has a number of Writer
s:
@Entity
public class E-book {
@Id
personal Integer id;
personal String identify;
@ManyToMany
@JoinTable(identify="BOOK_AUTHORS",
joinColumns=@JoinColumn(identify="BOOK_ID"),
inverseJoinColumns=@JoinColumn(identify="AUTHOR_ID"))
personal Set<Writer> authors = new HashSet<>();
...
}
@Entity
public class Writer {
@Id
@GeneratedValue
personal Integer id;
personal String identify;
@ManyToMany(mappedBy = "writer")
personal Set<E-book> books = new HashSet<>();
...
}
On this instance, we create a brand new desk, BOOK_AUTHORS
, with two columns: BOOK_ID
and AUTHOR_ID
. Utilizing the joinColumns
and inverseJoinColumns
attributes tells your JPA framework map these courses in a many-to-many relationship. The @ManyToMany
annotation within the Writer
class references the sector within the E-book
class that manages the connection, specifically the authors property.
Working with the EntityManager
EntityManager
is the category that performs database interactions in JPA. It’s initialized by a configuration file named persistence.xml
or by utilizing annotations. Every method has benefits. Annotations maintain the configuration near the category configured, which is easier, whereas the XML file retains the configuration exterior to the code and shareable throughout totally different purposes.
We’ll use persistence.xml
on this instance. The file is discovered within the META-INF
folder in your CLASSPATH
, which is often packaged in your JAR or WAR file. The persistence.xml
file comprises the next:
- The named “persistence unit,” which specifies the persistence framework you are utilizing, resembling Hibernate or EclipseLink.
- A set of properties specifying how to hook up with your database, in addition to any customizations within the persistence framework.
- An inventory of entity courses in your venture.
Let’s take a look at an instance.
Configuring the EntityManager
First, we create an EntityManager
. There are a number of methods to do that, together with utilizing the EntityManagerFactory
retrieved from the Persistence
class. In lots of eventualities, this class can be injected, with an IoC container like Spring or with Java CDI (Contexts and Dependency Injection). For simplicity in our standalone software, let’s outline the EntityManager
in a single place, after which entry it by way of the EntityManagerFactory
, like so:
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("Books");
EntityManager entityManager = entityManagerFactory.createEntityManager();
On this case, we have created an EntityManager
that’s linked to the “Books” persistence unit. You’ll see the EntityManager
in motion shortly.
The EntityManager
class defines how our software program will work together with the database by JPA entities. Listed here are a few of the strategies utilized by EntityManager
: