2

在使用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的异常。


潘杰
3.1k 声望238 粉丝