JPA与Hibernate EntityManager全面解析:功能、使用方法及区别详解
这是文章《JPA的EntityManager – Hibernate的EntityManager》的第1部分(共3部分)。
内容片段: JPA实体管理器是Java持久化API的核心。Hibernate是最广泛使用的JPA实现。
JPA实体管理器
- 程序中最重要的一个方面是与数据库的连接。数据库连接和与数据库的事务被视为最昂贵的操作。在这方面,ORM是一个非常重要的工具。ORM有助于用Java对象来表示数据库的关系。
- ORM包含两个概念:面向对象编程和关系型编程。
- Hibernate是一个ORM框架,程序员可以在其中描述对象在数据库中的表示方式。Hibernate会自动处理转换过程。
- Hibernate提供了JPA接口EntityManagerFactory和EntityManager的实现。
- EntityManagerFactory为连接到同一数据库提供EntityManager实例。所有实例都被配置为使用默认实现所定义的相同设置。可以准备多个实体管理器工厂来连接到不同的数据存储。
- JPA EntityManager用于在特定应用程序中访问数据库。它用于管理持久化实体实例,通过主键标识查找实体,以及对所有实体进行查询。
JPA EntityManager 方法的释义
JPA EntityManager支持以下一组方法。为了更好地可读性,我没有提及方法参数。
- 持久化 – 使实例被管理并持久化。
- 合并 – 合并给定实体的状态到当前持久化上下文中。
- 移除 – 移除实体实例。
- 查找 – 通过主键查找。搜索指定类和主键的实体。如果实体实例包含在持久化上下文中,则从那里返回。
- getReference – 返回一个懒加载的实例,在第一次访问实例时抛出EntityNotFoundException异常。
- 刷新 – 将持久化上下文与数据库同步。
- setFlushMode – 设置持久化上下文中所有对象的刷新模式。
- getFlushMode – 获取持久化上下文中所有对象的刷新模式。
- 锁定 – 使用指定的锁定模式锁定包含在持久化上下文中的实体实例。
- 刷新 – 从数据库刷新实例的状态,同时会覆盖对实体的更改。
- 清除 – 清除持久化上下文,使所有受管理的实体变为游离状态。未刷新到数据库的实体的更改将不会持久化。
- 分离 – 这类似于clear方法,只是之前引用游离对象的实体将继续引用它。
- 包含 – 检查受管理的实体是否属于当前持久化上下文。
- 获取锁定模式 – 获取实体实例的当前锁定模式。
- 设置属性 – 设置实体管理器的属性或提示。
- 获取属性 – 获取与实体管理器相关联的属性和提示。
- 创建查询 – 创建一个执行Java持久化查询语言语句的Query实例。
- 创建命名查询 – 创建一个执行Java持久化命名查询语句的Query实例。
- 创建本地查询 – 创建一个执行本地SQL语句的Query实例。
- 创建命名存储过程查询 – 创建一个执行存储过程查询的StoredProcedureQuery实例。
- 创建存储过程查询 – 创建一个执行存储过程查询的StoredProcedureQuery实例。
- 加入事务 – 告知实体管理器当前存在一个JTA事务。此方法应该在一个JTA应用程序管理的实体管理器上调用,该实体管理器在活动事务范围之外创建,以将其与当前JTA事务关联起来。
- 是否加入事务 – 判断实体管理器是否链接到当前事务。
- 解开 – 返回指定类型的对象,以允许访问特定于提供程序的API。
- 获取代理对象 – 返回实体管理器的提供程序对象。
- 关闭 – 关闭应用程序管理的实体管理器。
- 是否打开 – 判断实体管理器是否打开。
- 获取事务 – 返回资源级别的EntityTransaction对象。
- 获取实体管理器工厂 – 为实体管理器提供实体管理器工厂。
- 获取CriteriaBuilder – 返回一个CriteriaBuilder实例,用于创建CriteriaQuery对象。
- 获取元模型 – 返回一个Metamodel接口实例,用于访问持久单元的元模型。
- 创建EntityGraph – 返回一个可变的EntityGraph,用于动态创建EntityGraph。
- 获取EntityGraph – 返回一个命名的EntityGraph实例。
让我们通过EntityManager示例项目来看一些方法。
Hibernate EntityManager 示例

CREATE TABLE `employee` (
`employee_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`employee_name` varchar(32) NOT NULL DEFAULT '',
PRIMARY KEY (`employee_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
这是一张非常简单的表格,但非常适合我们的示例来展示EntityManager的使用。
Hibernate的Maven依赖
我们需要在我们的pom.xml文件中添加Hibernate和MySQL java驱动的依赖项。我正在使用Hibernate 5与最新版本的mysql-connector-java jar。
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.Olivia.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>hibernate-entitymanager</name>
<url>https://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- MySQL connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version>
</dependency>
<!-- Hibernate 5.2.6 Final -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.6.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Hibernate的持久化XML文件
使用Hibernate最重要的部分就是提供一个persistence.xml文件。这个xml文件包含了连接数据库的配置。
<persistence xmlns="https://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/persistence
https://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="persistence">
<description>Hibernate实体管理器示例</description>
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/Test" />
<property name="javax.persistence.jdbc.user" value="scdev" />
<property name="javax.persistence.jdbc.password" value="scdev" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>
</persistence>
- hibernate.show_sql用于告诉hibernate将SQL查询打印到日志文件或控制台。
- 最重要的配置是提供者类,即org.hibernate.jpa.HibernatePersistenceProvider。这就是Hibernate如何被挂接到我们的应用程序中作为JPA实现使用的方式。
- 有用于连接到数据库和要使用的驱动程序的属性。
- 需要注意的是,persistence.xml应该放在META-INF目录中,正如您从项目图像中看到的那样。
隐藏式实体Bean
JPA的EntityManager – Hibernate的EntityManager(第3部分,共3部分)
我们现在将创建一个与数据库中创建的雇员表相对应的Employee.java类。使用@Entity注解将员工类声明为实体。
package com.Olivia.jpa.hibernate.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "employee")
public class Employee {
private int employeeId;
private String name;
@Id
@Column(name = "employee_id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getEmployeeId() {
return employeeId;
}
public void setEmployeeId(int employeeId) {
this.employeeId = employeeId;
}
@Column(name = "employee_name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Employee [employeeId=" + employeeId + ", name=" + name + "]";
}
}
现在是时候创建我们的主程序并使用EntityManager方法运行一些查询了。
package com.Olivia.jpa.hibernate.main;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import com.Olivia.jpa.hibernate.model.Employee;
public class App {
public static void main(String[] args) {
// 创建EntityManagerFactory实例
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("persistence");
// 创建EntityManager实例
EntityManager entityManager = entityManagerFactory.createEntityManager();
System.out.println("开始事务");
// 开始事务
entityManager.getTransaction().begin();
Employee employee = new Employee();
employee.setName("Pankaj");
System.out.println("保存员工到数据库");
// 持久化员工对象到数据库
entityManager.persist(employee);
// 提交事务
entityManager.getTransaction().commit();
System.out.println("生成的员工ID = " + employee.getEmployeeId());
// 使用主键获取对象
Employee emp = entityManager.find(Employee.class, employee.getEmployeeId());
System.out.println("获取对象 " + emp.getName() + " " + emp.getEmployeeId());
// 从Employee表中获取所有对象
@SuppressWarnings("unchecked")
List<Employee> listEmployee = entityManager.createQuery("SELECT e FROM Employee e").getResultList();
if (listEmployee == null) {
System.out.println("未找到员工");
} else {
for (Employee empl : listEmployee) {
System.out.println("员工姓名= " + empl.getName() + ", 员工ID " + empl.getEmployeeId());
}
}
// 删除实体
entityManager.getTransaction().begin();
System.out.println("删除ID为 " + emp.getEmployeeId() + " 的员工");
entityManager.remove(emp);
entityManager.getTransaction().commit();
// 关闭实体管理器
entityManager.close();
entityManagerFactory.close();
}
}
- Persistence.createEntityManagerFactory将使用我们在persistence.xml文件中提供的持久性单元,提供EntityManagerFactory实例。
- entityManagerFactory.createEntityManager()将为我们创建一个EntityManager实例供我们使用。每次调用createEntityManager()方法,它都会返回一个新的EntityManager实例。
- entityManager.getTransaction().begin()方法首先从当前持久化上下文中获取事务,然后使用begin()方法开始事务。
- entityManager.persist(employee)用于将employee对象持久化到数据库中。
- entityManager.getTransaction().commit()方法用于获取事务,然后提交相同的事务。这将提交所有对数据库的更改。
- entityManager.find()用于使用主键在数据库中查找实体。
- 如果要编写自定义查询,我们可以使用entityManager.createQuery()方法。这里需要注意的重要一点是,createQuery()方法将使用实体类中给定的名称,而不是实际的表名。
- entityManager.remove()只有在需要从数据库中删除实体时才应该使用。
- entityManager.close()用于关闭实体管理器。同样entityManagerFactory.close()用于关闭EntityManagerFactory。我们应该尽快关闭这些资源。
以下是上述程序一次样本运行产生的输出结果。
开始事务
保存员工到数据库
Hibernate: insert into employee (employee_name) values (?)
生成的员工ID = 11
获取对象 Pankaj 11
2017年12月07日 下午1:05:23 org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
信息: HHH000397: Using ASTQueryTranslatorFactory
Hibernate: select employee0_.employee_id as employee1_0_, employee0_.employee_name as employee2_0_ from employee employee0_
员工姓名= Test, 员工ID 5
员工姓名= Pankaj, 员工ID 6
员工姓名= Pankaj, 员工ID 11
删除ID为 11 的员工
Hibernate: delete from employee where employee_id=?
注意当员工ID保存到数据库并映射回对象时的生成方式。还要注意在控制台中打印的SQL查询语句。请注意,Hibernate会创建更多的日志,但我没有在这里放置它们以保持可读性。关于 JPA EntityManager 的示例以及其与 Hibernate 的实现,请参考以下链接下载最终的Hibernate EntityManager示例项目。
下载JPA Hibernate EntityManager示例项目
参考:API文档