In JPA, the EntityManagerFactory object is an entity management object that manages the connection to the database. Using Spring to manage this object will help us a lot in developing Java applications that use JPA. In this tutorial, I will guide you on how to use JPA with the Spring framework.
First, I will create a new Maven project as an example:
Spring framework dependency:
1 2 3 4 5 |
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.0.3</version> </dependency> |
To work with JPA, we also need to add the spring-orm dependency:
1 2 3 4 5 |
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>6.0.3</version> </dependency> |
Here, I will use JPA with the implementation of Hibernate so I will add Hibernate dependency as follows:
1 2 3 4 5 |
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>6.1.6.Final</version> </dependency> |
MySQL Connector:
1 2 3 4 5 |
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.31</version> </dependency> |
For simplicity, in this example, I only define a table containing student information with two columns:
1 2 3 4 5 |
CREATE TABLE `student` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; |
The entity of student table has the following contents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
package com.huongdanjava.springjpa.entity; import java.io.Serializable; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.Table; @Table(name = "student") @Entity public class Student implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue private Long id; @Column private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + "]"; } } |
To work with JPA, we need a persistence.xml configuration file for it. Let’s create a new file called persistence.xml located in /src/main/resources/META-INF.
The contents of this file are as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="springPU" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <class>com.huongdanjava.springjpa.entity.Student</class> <exclude-unlisted-classes /> <properties> <property name="hibernate.show_sql" value="true" /> <property name="hibernate.format_sql" value="false" /> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" /> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.validation.mode" value="none" /> </properties> </persistence-unit> </persistence> |
Now, the most important part is: to declare the EntityManagerFactory object in the Spring container.
In Spring 5, we currently have two classes that support declaring the EntityManagerFactory object:
- LocalContainerEntityManagerFactoryBean
- LocalEntityManagerFactoryBean
With the LocalEntityManagerFactoryBean class, the JPA persistence.xml configuration file is usually located in the META-INF/persistence.xml folder, but with the LocalContainerEntityManagerFactoryBean class, the location of the persistence.xml file is more flexible. We can override its location and using LocalContainerEntityManagerFactoryBean will help you be more flexible on the JDBC DataSources declaration.
I will use the LocalContainerEntityManagerFactoryBean in this example to declare it in the Spring container as follows:
1 2 3 4 5 6 7 |
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="persistenceUnitName" value="springPU" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> </property> </bean> |
As you can see, there are three properties that we need to declare with the LocalContainerEntityManagerFactory class:
- dataSource: This property is used to declare the DataSource for our EntityManagerFactory. The DataSource here, we can understand, is the management of the connection to the database. We can declare many different types of DataSource as many different organizations implement the javax.sql.DataSource interface.
- persistenceUnitName: This is the name of the Persistence Unit that we have declared in the JPA configuration file, persistence.xml.
- jpaVendorAdapter: This attribute is used to declare the library we will use for the JPA implementation. In this example, I use Hibernate then I declared HibernateJpaVendorAdapter. If you use EclipseLink as a JPA implementation, just declare this property as org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter.
The dataSource section in this example, I will use DriverManagerDataSource with declarations as we do for JDBC, as follows:
1 2 3 4 5 6 |
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/muleesb_jpa" /> <property name="username" value="root" /> <property name="password" value="123456" /> </bean> |
OK, so we have completed the EntityManagerFactory declaration in the Spring container. Now use it!
My example is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.huongdanjava.springjpa.entity; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManagerFactory; public class Application { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml"); EntityManagerFactory emf = (EntityManagerFactory) ac.getBean("entityManagerFactory"); EntityManager em = emf.createEntityManager(); Student student = em.find(Student.class, Long.valueOf(1)); System.out.println(student.getName()); } } |
My database currently has the following data:
So the result would be: