Object-relational Mapping Using JPA, Hibernate and Spring Data JPA. Persistence with JPA
PERSISTENCE WITH JPA
JPA application
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.4.17.Final</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
The persistence unit
<provider>org.hibernate.jpa.
HibernatePersistenceProvider</provider> #1
<properties>
<property name="javax.persistence.jdbc.driver"
value="com.mysql.cj.jdbc.Driver"/> #2
<property name="javax.persistence.jdbc.url"
value="jdbc:mysql://localhost:3306/CSCS"/> #3
<property name="javax.persistence.jdbc.user"
value="root"/> #4
<property name="javax.persistence.jdbc.password"
value=""/> #5
<property name="hibernate.dialect" #6
value="org.hibernate.dialect.MySQL8Dialect"/>
<property name="hibernate.hbm2ddl.auto"
value="create"/> #7
</properties>
-
As JPA is only a specification, we need to indicate the vendor-specific PersistenceProvider implementation of the API. The persistence we define will be backed by a Hibernate provider. #1
- We indicate the JDBC properties - driver #2, URL of the database #3, username #4, and password #5 to access it. The machine we are running the programs on has MySQL 8 installed and the access credentials are the ones from persistence.xml.
- The Hibernate dialect is MySQL8 #6, as the database to interact with is MySQL Release 8.0.
- Every time the program is executed, the database will be created from scratch #7. This is ideal for automated testing when we want to work with a clean database for every test run.
The persistent class
The application we implement has a persistent class, Item:
Listing 3 The Item class
public class Item {
@Id #2
@GeneratedValue #3
private Long id;
private String info; #4
}
- Persistent classes need the @Entity annotation #1, to indicate they correspond to a database table. If no table name is specified, this class will be mapped by default to a table called ITEM.
- Persistent classes need an attribute annotated with @Id #2, to correspond to the primary key of the database table. This attribute will be mapped to a column named ID.
- The @GeneratedValue annotation indicates the automatic generation of primary keys #3. Many strategies may be used here, depending on the database: identity fields, values obtained from a sequence, or a table.
- Attributes will be mapped to columns in the table. As no column name is specified, info attribute #4 will be mapped by default to a column called INFO.
Saving and retrieving items
Listing 4 The ItemJPATest class
public class ItemJPATest {
@Test
void saveRetrieveItem() {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(
"cscs"); #1
try {
EntityManager em =
emf.createEntityManager(); #2
em.getTransaction().begin(); #3
Item item = new Item(); #4
item.setInfo("Item"); #4
em.persist(item); #5
em.getTransaction().commit(); #6
em.close(); #7
} finally {
emf.close(); #8
}
}
}
- We need an EntityManagerFactory to access the database #1. This factory corresponds to the persistence unit that we have previously defined.
- Create an EntityManager and start a new database session #2.
- Get access to the standard transaction API and begin a transaction #3.
- Create a new instance of the Item class, and set its info property #4.
- The transient instance becomes persistent on the side of the persistence context #5.
- Commit the transaction #6. A new row is inserted in the ITEM table. Access to the database must be transactional, even if it is read-only.
- As we created an EntityManager, we must close it #7.
- As we created an EntityManagerFactory, we must close it #8.
- There is no SQL code and no JDBC usage in the JPA application. There are no CRUD (create, read, update, delete) operations inside the Java code, but only working object-oriented way, with classes, objects, and methods. The translation to each SQL dialect is made by the ORM which also addresses portability.