在使用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的异常。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。