转载

获取EntityManager避免IllegalStateException: EnityManager is closed

在使用springboot进行一些非封装的JPA操作时,我们可能需要 EntityManager 的支持。比如笔者近期启用了 hibernate envers 来记录某个数据表的数据变更情况,在进行数据查询时参阅了官方文档的以下代码:

AuditReader reader = AuditReaderFactory.get(entityManager); ➊

Person person2/_rev1 = reader.find(Person.class, person2.getId(), 1);
assert person2/_rev1.getAddress().equals(new Address("Grimmauld Place", 12));

Address address1/_rev1 = reader.find(Address.class, address1.getId(), 1);
assert address1/_rev1.getPersons().getSize() == 1;
  • ➊ 这里需要一个entityManager。

以前看hibernate的官方文档时总感觉其不太友好,很多代码都只给了一部分,并没有给出整个的上下文。比如这里的 entityManager 。后来才明白原来用户在使用hibernate时都会有自己特定的环境,而每个特定环境都有着获取 entityManager 的不同方式,官方在这里是想告诉我们:这里需要一个 entityManager ,至于该 entityManager 你如何获取,取决于用户当前的特定环境。

spring boot中获取entityManager

spring boot 中可以非常简单的获取 entityManager :

@Autowired  
private EntityManager entityManager;

但如果直接将此对象放到 AuditReaderFactory.get(entityManager); ➊ 中使用,则会面临以下问题:

  • 第一次使用时正常。
  • 第二次使用时报以下错误:IllegalStateException: EnityManager is closed

这时由于:每个 entityManager 只能够用一次,用完以后该 entityManager 便会自动关闭,所以当第二次再用的时候便发生了EnityManager is closed的错误。

正确的方法如下:

@Autowired  
private EntityManager entityManager;
...
   EntityManager tempEntityManager = this.entityManager.getEntityManagerFactory().createEntityManager();  
   AuditReaderFactory.get(tempEntityManager);

这样以来,在第一次需要 entityManager 时,我们从工厂中创建一个临时的 tempEntityManager ,在查询完毕后系统自动关闭了这个临时的 tempEntityManager ;下次查询时,我们再获取一个全新临时 tempEntityManager ,从而保障了多次调用该方法,也不会出现EnityManager is closed的异常。

原文  https://segmentfault.com/a/1190000021371838
正文到此结束
Loading...