JPA的核心API主要包括Persistence、EntityManagerFactory、EntityManager和EntityTransaction等。
其中,JPA核心API的具体测试代码下载地址:。
1. Persistence
主要作用:通过createEntityManagerFactory()静态方法来获取EntityManagerFactory的实例。
// 1. 创建EntityManagerFactory
String persistenceUnitName = "JPA-3-EntityManager";
EntityManagerFactory entityManagerFactory = null;
entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnitName);
/* 了解
Map<String, Object> properties = new HashMap<>();
properties.put("hibernate.show_sql", false);
entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnitName, properties);
*/
2. EntityManagerFactory
主要作用:该接口主要用来创建EntityManager的实例。
主要方法 | 具体描述 |
---|---|
createEntityManager() | 用于创建实体管理器对象实例 |
createEntityManager(Map map) | 用于创建实体管理器对象实例的重载方法,Map参数用于提供EntityManager的属性 |
isOpen() | 检查EntityManagerFactory是否处于打开状态;实体管理器工厂实例创建后一直处于打开状态,除非调用close()方法将其关闭 |
close() | 关闭EntityManagerFactory;关闭后将释放所有资源,isOpen()方法测试将返回false,其它方法将不能调用,否则将导致IllegalStateException异常 |
// 2. 创建EntityManager
EntityManager entityManager = entityManagerFactory.createEntityManager();
3. EntityManager
主要作用:JPA规范中完成持久化操作的核心对象,在一组实体类与底层数据源之间进行O/R映射的管理。
在JPA规范中,实体具有如下四种状态:
实体状态 | 具体描述 |
---|---|
新建状态 | 新创建的对象,尚未拥有持久性主键 |
持久化状态 | 已经拥有持久性主键并和持久化建立了上下文环境 |
游离状态 | 拥有持久化主键,但是没有与持久化建立上下文环境 |
删除状态 | 拥有持久化主键,已经和持久化建立上下文环境,但是从数据库中删除 |
3.1 find()/getReference()/persist()/remove()
package com.qiaobc.jpa.junit;
import java.util.Date;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.qiaobc.jpa.em.Customer;
public class JPATest {
private EntityManagerFactory entityManagerFactory;
private EntityManager entityManager;
private EntityTransaction entityTransaction;
@Before
public void init() {
String persistenceUnitName = "JPA-3-EntityManager";
entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnitName);
entityManager = entityManagerFactory.createEntityManager();
entityTransaction = entityManager.getTransaction();
// 开启事务
entityTransaction.begin();
}
/**
* find()方法 : 类似于Hibernate中Session的get()方法
*/
@Test
public void testFind() {
Customer customer = entityManager.find(Customer.class, 1);
System.out.println(customer.getClass().getName()); // com.qiaobc.jpa.em.Customer
System.out.println("******");
System.out.println(customer);
}
/**
* getReference()方法 : 类似于Hibernate中Session的load()方法
*/
@Test
public void testGetReference() {
Customer customer = entityManager.getReference(Customer.class, 1);
System.out.println(customer.getClass().getName()); // com.qiaobc.jpa.em.Customer_$$_javassist_0
// org.hibernate.LazyInitializationException: could not initialize proxy - no Session
// entityTransaction.commit();
// entityManager.close();
System.out.println("******");
System.out.println(customer);
}
/**
* persist()方法 : 类似于Hibernate中Session的save()方法
*
* 不同之处:若对象有id则persist()方法不能执行INSERT操作,而会抛出异常
*/
@Test
public void testPersist() {
Customer customer = new Customer(null, "qiaob", "qiaob@163.com", 22, new Date(), new Date());
entityManager.persist(customer); // 使对象由临时状态变为持久化状态
System.out.println("id = " + customer.getId());
}
/**
* remove()方法 : 类似于Hibernate中Session的delete()方法
*
* 不同之处:只能移除持久化对象,但delete()方法实际上还可移除游离对象
*/
@Test
public void testRemove() {
Customer customer = new Customer();
customer.setId(1);
// entityManager.remove(customer); // 不能移除游离对象
customer = entityManager.find(Customer.class, 1);
entityManager.remove(customer);
}
@After
public void destory() {
entityTransaction.commit();
entityManager.close();
entityManagerFactory.close();
}
}
3.2 merge()
主要作用:用于处理Entity的同步,即数据库的插入和更新操作,类似于Hibernate中Session的saveOrUpdate()方法。
运行流程:若news1为临时对象,则创建新的news2对象,将news1对象的属性复制到news2对象中,并持久化news2对象,进而返回持久化对象news2的引用。若news1为游离对象(设OID=1),则先在EntityManager缓存中查找是否存在OID为1的持久化对象news3,若存在则将news1对象的属性复制到news3对象中,并持久化news3对象,进而返回持久化对象的引用;若不存在则在数据库中查找是否存在ID为1的记录,若存在则加载该记录对应的持久化对象news4,将news1对象的属性复制到news4对象中,并持久化news4对象,进而返回持久化对象的引用。
/**
* 临时对象的持久化过程:
* 1). 创建新的对象
* 2). 将临时对象的属性赋值到新创建的对象属性中
* 3). 持久化新创建的对象
* 4). 返回新创建的对象的引用
*/
@Test
public void testMerge1() {
// 临时对象
Customer customer1 = new Customer(null, "qiaobc", "qiaobc@163.com", 23, new Date(), new Date());
// 持久化该临时对象
Customer customer2 = entityManager.merge(customer1);
System.out.println(customer1 == customer2); // false
System.out.println("customer1#id: " + customer1.getId()); // null
System.out.println("customer2#id: " + customer2.getId()); // 不为null
}
/**
* 游离对象的持久化过程:
* 1). 若EntityManager缓存中存在与游离对象OID相同的持久化对象
* 2). 将游离对象的属性复制到持久化对象的属性中
* 3). 持久化复制后的持久化对象
* 4). 返回该持久化对象的引用
*
* 特别注意:Hibernate不允许Session在同一时刻与两个OID相同的对象进行关联,而EntityManager可以
*/
@Test
public void testMerge2() {
// 游离对象
Customer customer1 = new Customer(1, "qiaodb", "qiaodb@163.com", 22, new Date(), new Date());
// 缓存中加载OID=1的持久化对象
Customer customer2 = entityManager.find(Customer.class, 1);
// 持久化该游离对象
entityManager.merge(customer1);
System.out.println(customer1 == customer2); // false
System.out.println("customer1#id: " + customer1.getId()); // 1
System.out.println("customer2#id: " + customer2.getId()); // 1
}
/**
* 游离对象的持久化过程:
* 1). 若EntityManager缓存中不存在与游离对象OID相同的持久化对象
* 2). 若数据库中存在id=OID的记录,则从该数据库中加载id=OID的持久化对象
* 3). 将游离对象的属性复制到持久化对象的属性中
* 4). 持久化复制后的持久化对象
* 5). 返回该持久化对象的引用
*/
@Test
public void testMerge3() {
// 游离对象
Customer customer1 = new Customer(1, "qiaobb", "qiaobb@163.com", 22, new Date(), new Date());
// 持久化该游离对象
Customer customer2 = entityManager.merge(customer1);
// 通过setName()方法设置断点来查看效果
System.out.println(customer1 == customer2); // false
}
3.3 其他方法
@Test
public void testFlush() {
Customer customer = entityManager.find(Customer.class, 1);
System.out.println(customer);
customer.setName("qiaobendan");
entityManager.flush(); // 强制将修改后的实体保存到数据库中,否则只在事务提交时保存
}
@Test
public void testRefresh() {
Customer customer = entityManager.find(Customer.class, 1);
customer = entityManager.find(Customer.class, 1);
entityManager.refresh(customer); // 强制重新获取customer实体
}
4. EntityTransaction
主要作用:用来管理资源层实体管理器的事务操作,可通过调用实体管理器的getTransaction()方法来获得其实例。