JPA的EntityManager – Hibernate的EntityManager
JPA实体管理器是Java持久化API的核心。Hibernate是最广泛使用的JPA实现。
JPA实体管理器
- One of the most important aspect of a program is connection with database. Database connection and transaction with database is considered as most expensive transaction. ORM is a very important tool in this regard. ORM helps in representing relations of database in terms of java objects.
- ORM consists of two concepts object-oriented and relational programming.
- Hibernate is an ORM framework where programmer describes the way objects are represented in database. Hibernate handles the conversion automatically.
- Hibernate provides implementation of JPA interfaces EntityManagerFactory and EntityManager.
- EntityManagerFactory provides instances of EntityManager for connecting to same database. All the instances are configured to use the same setting as defined by the default implementation. Several entity manager factories can be prepared for connecting to different data stores.
- JPA EntityManager is used to access a database in a particular application. It is used to manage persistent entity instances, to find entities by their primary key identity, and to query over all entities.
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 Entity Manager Example</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 is used to tell hibernate to print sql queries into log files or console.
- The most important configuration is provider class i.e. org.hibernate.jpa.HibernatePersistenceProvider. This is how Hibernate is hooked into our application to be used as JPA implementation.
- There are properties to connect to your database and driver to use.
- It is important to note that persistence.xml should be placed in the META-INF directory, as you can see from the project image.
请将以下内容翻译为中文:
“隐藏式实体Bean”
我们现在将创建一个与数据库中创建的雇员表相对应的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 = Persistence.createEntityManagerFactory("persistence");
EntityManager entityManager = entityManagerFactory.createEntityManager();
System.out.println("Starting Transaction");
entityManager.getTransaction().begin();
Employee employee = new Employee();
employee.setName("Pankaj");
System.out.println("Saving Employee to Database");
entityManager.persist(employee);
entityManager.getTransaction().commit();
System.out.println("Generated Employee ID = " + employee.getEmployeeId());
// get an object using primary key.
Employee emp = entityManager.find(Employee.class, employee.getEmployeeId());
System.out.println("got object " + emp.getName() + " " + emp.getEmployeeId());
// get all the objects from Employee table
@SuppressWarnings("unchecked")
List<Employee> listEmployee = entityManager.createQuery("SELECT e FROM Employee e").getResultList();
if (listEmployee == null) {
System.out.println("No employee found . ");
} else {
for (Employee empl : listEmployee) {
System.out.println("Employee name= " + empl.getName() + ", Employee id " + empl.getEmployeeId());
}
}
// remove and entity
entityManager.getTransaction().begin();
System.out.println("Deleting Employee with ID = " + emp.getEmployeeId());
entityManager.remove(emp);
entityManager.getTransaction().commit();
// close the entity manager
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。我们应该尽快关闭这些资源。
以下是上述程序一次样本运行产生的输出结果。
Starting Transaction
Saving Employee to Database
Hibernate: insert into employee (employee_name) values (?)
Generated Employee ID = 11
got object Pankaj 11
Dec 07, 2017 1:05:23 PM org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
INFO: HHH000397: Using ASTQueryTranslatorFactory
Hibernate: select employee0_.employee_id as employee1_0_, employee0_.employee_name as employee2_0_ from employee employee0_
Employee name= Test, Employee id 5
Employee name= Pankaj, Employee id 6
Employee name= Pankaj, Employee id 11
Deleting Employee with ID = 11
Hibernate: delete from employee where employee_id=?
注意当员工ID保存到数据库并映射回对象时的生成方式。还要注意在控制台中打印的SQL查询语句。请注意,Hibernate会创建更多的日志,但我没有在这里放置它们以保持可读性。关于 JPA EntityManager 的示例以及其与 Hibernate 的实现,请参考以下链接下载最终的Hibernate EntityManager示例项目。
下载JPA Hibernate EntityManager示例项目。
参考:API文档