On this second half of the Java persistence with JPA and Hibernate tutorial, we transfer previous ideas and begin writing code that persists knowledge to and from a relational database utilizing JPA with Hibernate. We’ll begin by configuring an instance utility to make use of Hibernate because the JPA supplier, then shortly configure the EntityManager
and write two lessons that we need to persist to the database: E book
and Writer
. Lastly, we’ll write a easy utility that pulls collectively all the appliance elements and efficiently persists our two entities to the database.
You will discover ways to:
- Configure a Java utility to make use of Hibernate as your JPA supplier.
- Configure JPA’s
EntityManager
. - Create a easy JPA area mannequin representing two lessons with a one-to-many relationship.
- Use repositories to cleanly separate persistence logic out of your utility code.
- Write, construct, and run the instance utility utilizing JPA to attach with a relational database.
You will additionally get began with JPA Question Language (JPQL) and use it to execute just a few easy database operations on the instance utility.
The entire supply code for the instance utility might be discovered right here. When you have not learn the first half of this tutorial, we suggest doing that earlier than you proceed.
Configuring Hibernate
To maintain issues easy, we’ll use the embedded H2 database for each improvement and runtime examples. You’ll be able to change the JDBC URL within the EntityManager
to level to any database you want.
Begin by reviewing the Maven POM file for the challenge, proven in Itemizing 1.
Itemizing 1. pom.xml
<challenge xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.infoworld</groupId>
<artifactId>jpa-example</artifactId>
<packaging>jar</packaging>
<model>1.0-SNAPSHOT</model>
<title>jpa-example</title>
<url>http://maven.apache.org</url>
<properties>
<java.model>21</java.model>
<hibernate.model>6.3.1.Remaining</hibernate.model>
</properties>
<construct>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<model>2.0.2</model>
<configuration>
<supply>${java.model}</supply>
<goal>${java.model}</goal>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.infoworld.jpa.JpaExample</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<section>set up</section>
<targets>
<purpose>copy-dependencies</purpose>
</targets>
<configuration>
<outputDirectory>${challenge.construct.listing}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</construct>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<model>${hibernate.model}</model>
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<model>3.1.0</model>
</dependency>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<model>9.1.0</model>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<model>2.2.224</model>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>jakarta.json.bind</groupId>
<artifactId>jakarta.json.bind-api</artifactId>
<model>3.0.0</model>
</dependency>
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>yasson</artifactId>
<model>3.0.3</model>
<scope>runtime</scope>
</dependency>
</dependencies>
</challenge>
We’ll construct this challenge utilizing Java 21 and Hibernate model 6.3, which was the most recent model as of this writing. Plugins within the construct node will set the Java compilation model, make the ensuing JAR file executable, and make sure that all dependencies are copied to a lib folder in order that the executable JAR can run. We embrace the next dependencies:
- Hibernate’s core performance:
hibernate-core
- The JPA API:
hibernate-jpa-2.1-api
- The embedded H2 database:
h2
Word that H2’s scope is ready to runtime in order that we are able to use it once we run our code.
Configuring the EntityManager
Recall that our JPA’s EntityManager
is pushed by the persistence.xml
file. Itemizing 2 exhibits the contents of this file.
Itemizing 2. /sources/persistence.xml
<persistence xmlns="http://java.solar.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.solar.com/xml/ns/persistence http://java.solar.com/xml/ns/persistence/persistence_2_0.xsd"
model="2.0">
<persistence-unit title="Books" transaction-type="RESOURCE_LOCAL">
<!-- Persistence supplier -->
<supplier>org.hibernate.jpa.HibernatePersistenceProvider</supplier>
<properties>
<property title="jakarta.persistence.jdbc.driver" worth="org.h2.Driver" />
<property title="jakarta.persistence.jdbc.url" worth="jdbc:h2:mem:bookstore" />
<property title="jakarta.persistence.jdbc.consumer" worth="sa" />
<property title="jakarta.persistence.jdbc.password" worth="" />
<property title="hibernate.dialect" worth="org.hibernate.dialect.H2Dialect"/>
<property title="hibernate.hbm2ddl.auto" worth="replace" />
<property title="show_sql" worth="true"/>
<property title="hibernate.temp.use_jdbc_metadata_defaults" worth="false"/>
<property title="hibernate.format_sql" worth="true"/>
<property title="hibernate.use_sql_comments" worth="true"/>
</properties>
</persistence-unit>
</persistence>
Though we’re utilizing persistence.xml
, you can obtain an identical configuration with an annotated EntityManager
. In that case, you’ll use the @PersistenceContext(unitName = "Books")
annotation.
The persistence.xml
file begins with a persistence node that may comprise a number of persistence models. A persistence-unit
has a reputation, which we’ll use later once we create the EntityManager
, and it defines the attributes of that unit. On this case, we configure properties on this unit to do the next:
- Specify
HibernatePersistenceProvider
, so the appliance is aware of we’re utilizing Hibernate as our JPA supplier. - Outline the database configuration through JDBC. On this case, we’re utilizing an in-memory H2 occasion.
- Configure Hibernate, together with setting the Hibernate dialect to
H2Dialect
, in order that Hibernate is aware of find out how to talk with the H2 database.
Word that JPA will routinely scan and uncover your annotated entity lessons.
The area mannequin
For this utility, we’re modeling a E book
class and an Writer
class. These entities have a one-to-many relationship, that means {that a} e-book can solely be written by a single writer, however an writer can write many books. Determine 1 exhibits this area mannequin.
Determine 1. Area mannequin for a JPA/Hibernate utility with two entities.
Once we discuss database tables, we usually discuss a “knowledge mannequin,” however once we discuss Java entities and their relationships, we usually consult with it as a “area mannequin.”
Modeling the E book class
Let’s start with our entities. Itemizing 3 exhibits the supply code for the E book
class.
Itemizing 3. E book.java
package deal com.infoworld.jpa.mannequin;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.NamedQueries;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.Desk;
@Entity
@Desk(title = "BOOK")
@NamedQueries({
@NamedQuery(title = "E book.findByName",
question = "SELECT b FROM E book b WHERE b.title = :title"),
@NamedQuery(title = "E book.findAll",
question = "SELECT b FROM E book b")
})
public class E book {
@Id
@GeneratedValue
personal Integer id;
personal String title;
@ManyToOne
@JoinColumn(title="AUTHOR_ID")
personal Writer writer;
public E book() {
}
public E book(Integer id, String title) {
this.id = id;
this.title = title;
}
public E book(String title) {
this.title = title;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return title;
}
public void setName(String title) {
this.title = title;
}
public Writer getAuthor() {
return writer;
}
public void setAuthor(Writer writer) {
this.writer = writer;
}
@Override
public String toString() {
return "E book{" +
"id=" + id +
", title="" + title + "'' +
", writer=" + writer.getName() +
'}';
}
}
This E book
is an easy POJO (plain previous Java object) that manages three properties:
id
: The first key, or identifier, of the e-book.title
: The title, or title, of the e-book.writer
: The writer who wrote the e-book.
The category itself is annotated with three annotations:
@Entity
: Identifies theE book
as a JPA entity.@Desk
: Overrides the title of the desk to which this entity can be persevered. On this case we outline the desk title as BOOK.@NamedQueries
: Means that you can outline JPA Question Language queries that may later be retrieved and executed by theEntityManager
.
About JPA Question Language (JPQL)
JPQL is much like SQL, however relatively than working on database column names, it operates on entities, their fields, and their relationships. JPA refers to those queries as operating on high of an “summary schema,” which will get translated to a correct database schema. Entities are mapped to that database schema. Here is the format for a easy JPQL question:
SELECT returnedEntity FROM entityName var WHERE whereClause
The E book.findAll
question is outlined as SELECT b FROM E book b
, during which “E book” is the title of the entity and “b” is the variable title assigned to “E book.” That is equal to the SQL SELECT * FROM BOOK
.
The E book.findByName
makes use of a named parameter, “title
,” as in:
SELECT b FROM E book b WHERE b.title = :title
Parameters might be referenced by title or by place. When referencing a parameter by title, you specify the title your question expects, akin to “title
” or “bookName
,” prefaced by a “:
“. If, as an alternative, you wished to reference the title by place, you can change “:title
” with “?1
“. When executing the question, you’ll set the parameter with place of “1”. Binding the e-book title to “MyBook
” is equal to the next SQL:
SELECT * FROM BOOK WHERE title="MyBook"
The E book
‘s id
attribute is annotated with each @Id
and @GeneratedValue
. The @Id
annotation identifies the id
as the first key of the E book
, which is able to resolve to the first key of the underlying database. The @GeneratedValue
annotation tells JPA that the database ought to generate the first key when the entity is persevered to the database. As a result of we have now not specified a @Column
annotation, the id
can be mapped to the identical column title, “id.”