一、为什么要抽取 JpaUtil 工具类
前面我们已经学习了:一篇文章带你搞定 JPA 中的 API 对象
知道由于EntityManagerFactory
是一个线程安全的对象(即多个线程访问同一个EntityManagerFactory
对象不会有线程安全问题),并且EntityManagerFactory
的创建极其浪费资源,所以在使用JPA编程时,我们可以对EntityManagerFactory
的创建进行优化,只需要做到一个工程只存在一个EntityManagerFactory
即可
解决思路是通过静态代码的形式创建 EntityManagerFactory
对于静态代码块的学习:一篇文章带你搞定 Java 中代码块的学习(普通代码块/构造代码块/静态代码块)
二、JpaUtil 工具类
/**
* 解决实体管理器工厂的浪费资源和耗时问题
* 通过静态代码块的形式,当程序第一次访问此工具类时,创建一个公共的实体管理器工厂对象
*
* 第一次访问getEntityManager方法:经过静态代码块创建一个factory对象,再调用方法创建一个EntityManager对象
* 第二次方法getEntityManager方法:直接通过一个已经创建好的factory对象,创建EntityManager对象
*/
public class JpaUtils {
private static EntityManagerFactory factory;
static {
//1.加载配置文件,创建entityManagerFactory
factory = Persistence.createEntityManagerFactory("myJpa");
}
/**
* 获取EntityManager对象
*/
public static EntityManager getEntityManager() {
return factory.createEntityManager();
}
}
三、测试工具类
public class JpaTest {
@Test
public void testSave() {
//1.通过工具类获取实体类管理器
EntityManager em = JpaUtils.getEntityManager();
//2.获取事务对象,开启事务
EntityTransaction tx = em.getTransaction(); //获取事务对象
tx.begin();//开启事务
//3.完成增删改查操作:保存一个客户到数据库中
Customer customer = new Customer();
customer.setCustName("Yolo");
customer.setCustAddress("BeiJing");
customer.setCustIndustry("Student");
//保存操作
em.persist(customer);
//4.提交事务
tx.commit();
//5.释放资源
em.close();
//因为工厂是公共的,不能关闭,不然其他线程将无法获取
//factory.close();
}
}