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支持以下一组方法。为了更好地可读性,我没有提及方法参数。

  1. 持久化 – 使实例被管理并持久化。
  2. 合并 – 合并给定实体的状态到当前持久化上下文中。
  3. 移除 – 移除实体实例。
  4. 查找 – 通过主键查找。搜索指定类和主键的实体。如果实体实例包含在持久化上下文中,则从那里返回。
  5. getReference – 返回一个懒加载的实例,在第一次访问实例时抛出EntityNotFoundException异常。
  6. 刷新 – 将持久化上下文与数据库同步。
  7. setFlushMode – 设置持久化上下文中所有对象的刷新模式。
  8. getFlushMode – 获取持久化上下文中所有对象的刷新模式。
  9. 锁定 – 使用指定的锁定模式锁定包含在持久化上下文中的实体实例。
  10. 刷新 – 从数据库刷新实例的状态,同时会覆盖对实体的更改。
  11. 清除 – 清除持久化上下文,使所有受管理的实体变为游离状态。未刷新到数据库的实体的更改将不会持久化。
  12. 分离 – 这类似于clear方法,只是之前引用游离对象的实体将继续引用它。
  13. 包含 – 检查受管理的实体是否属于当前持久化上下文。
  14. 获取锁定模式 – 获取实体实例的当前锁定模式。
  15. 设置属性 – 设置实体管理器的属性或提示。
  16. 获取属性 – 获取与实体管理器相关联的属性和提示。
  17. 创建查询 – 创建一个执行Java持久化查询语言语句的Query实例。
  18. 创建命名查询 – 创建一个执行Java持久化命名查询语句的Query实例。
  19. 创建本地查询 – 创建一个执行本地SQL语句的Query实例。
  20. 创建命名存储过程查询 – 创建一个执行存储过程查询的StoredProcedureQuery实例。
  21. 创建存储过程查询 – 创建一个执行存储过程查询的StoredProcedureQuery实例。
  22. 加入事务 – 告知实体管理器当前存在一个JTA事务。此方法应该在一个JTA应用程序管理的实体管理器上调用,该实体管理器在活动事务范围之外创建,以将其与当前JTA事务关联起来。
  23. 是否加入事务 – 判断实体管理器是否链接到当前事务。
  24. 解开 – 返回指定类型的对象,以允许访问特定于提供程序的API。
  25. 获取代理对象 – 返回实体管理器的提供程序对象。
  26. 关闭 – 关闭应用程序管理的实体管理器。
  27. 是否打开 – 判断实体管理器是否打开。
  28. 获取事务 – 返回资源级别的EntityTransaction对象。
  29. 获取实体管理器工厂 – 为实体管理器提供实体管理器工厂。
  30. 获取CriteriaBuilder – 返回一个CriteriaBuilder实例,用于创建CriteriaQuery对象。
  31. 获取元模型 – 返回一个Metamodel接口实例,用于访问持久单元的元模型。
  32. 创建EntityGraph – 返回一个可变的EntityGraph,用于动态创建EntityGraph。
  33. 获取EntityGraph – 返回一个命名的EntityGraph实例。

让我们通过EntityManager示例项目来看一些方法。

Hibernate EntityManager 示例

JPA 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();

	}
}
  1. Persistence.createEntityManagerFactory将使用我们在persistence.xml文件中提供的持久性单元,提供EntityManagerFactory实例。
  2. entityManagerFactory.createEntityManager()将为我们创建一个EntityManager实例供我们使用。每次调用createEntityManager()方法,它都会返回一个新的EntityManager实例。
  3. entityManager.getTransaction().begin()方法首先从当前持久化上下文中获取事务,然后使用begin()方法开始事务。
  4. entityManager.persist(employee)用于将employee对象持久化到数据库中。
  5. entityManager.getTransaction().commit()方法用于获取事务,然后提交相同的事务。这将提交所有对数据库的更改。
  6. entityManager.find()用于使用主键在数据库中查找实体。
  7. 如果要编写自定义查询,我们可以使用entityManager.createQuery()方法。这里需要注意的重要一点是,createQuery()方法将使用实体类中给定的名称,而不是实际的表名。
  8. entityManager.remove()只有在需要从数据库中删除实体时才应该使用。
  9. 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文档

bannerAds