在使用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;
以前看hibernate的官方文档时总感觉其不太友好,很多代码都只给了一部分,并没有给出整个的上下文。比如这里的 entityManager
。后来才明白原来用户在使用hibernate时都会有自己特定的环境,而每个特定环境都有着获取 entityManager
的不同方式,官方在这里是想告诉我们:这里需要一个 entityManager
,至于该 entityManager
你如何获取,取决于用户当前的特定环境。
在 spring boot
中可以非常简单的获取 entityManager
:
@Autowired private EntityManager entityManager;
但如果直接将此对象放到 AuditReaderFactory.get(entityManager);
➊ 中使用,则会面临以下问题:
这时由于:每个 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的异常。