如何在 jersey/hk2 应用程序中正确配置 EntityManager? [英] How do I properly configure an EntityManager in a jersey / hk2 application?
问题描述
我有一个 jersey-2/hk2 应用程序,它使用 JPA 持久性.EntityManager
像这样在启动时绑定
I have a jersey-2 / hk2 application which uses JPA persistence. The EntityManager
is bound at startup like this
public MyApplication() {
// ...
register(new AbstractBinder() {
@Override
public void configure() {
bindFactory(EmFactory.class)
.to(EntityManager.class)
.in(RequestScoped.class);
}
});
}
工厂类是
public class EmFactory implements Factory<EntityManager> {
private static final String PERSISTENCE_UNIT = "unit";
private EntityManagerFactory emf;
private CloseableService closeableService;
@Inject
public EmFactory(@Named(PERSISTENCE_UNIT) String persistenceUnit,
CloseableService closeableService) {
emf = Persistence.createEntityManagerFactory(persistenceUnit);
this.closeableService = closeableService;
}
@Override
public EntityManager provide() {
final EntityManager entityManager = emf.createEntityManager();
closeableService.add(new Closeable() {
@Override
public void close() throws IOException {
if(entityManager.isOpen()) {
entityManager.close();
}
}
});
return entityManager;
}
@Override
public void dispose(EntityManager entityManager) {
if(entityManager.isOpen()) {
entityManager.close();
}
}
}
这有效,但是对于每个请求,我都会在日志中收到有关 EntityManager 已注册的警告:
this works but then for each request i get a warning in the logs about an EntityManager being already registered:
HHH000436: Entity manager factory name (unit) is already registered.
If entity manager will be clustered or passivated, specify a unique
value for property 'hibernate.ejb.entitymanager_factory_name'
我做错了什么?在 jersey-2/hk2 应用程序中初始化 EntityManager 的正确方法是什么?
What am I doing wrong? What is the proper way to initialize an EntityManager in a jersey-2 / hk2 application?
推荐答案
一种选择是在 EMFactory
(在请求中)而不是创建一个新的 EntityManagerFactory
范围),您可以为 EntityManagerFactory
创建一个单例工厂,然后只需将 EntityManagerFactory
注入 EMFactory
.
One option is to instead of creating a new EntityManagerFactory
in the EMFactory
(which is in a request scope), you could create a singleton factory for the EntityManagerFactory
, then just inject the EntityManagerFactory
into the EMFactory
.
public class EMFFactory implements Factory<EntityManagerFactory> {
private final EntityManagerFactory emf;
public EMFFactory (){
emf = Persistence.createEntityManagerFactory(persistenceUnit);
}
public EntityManagerFactory provide() {
return emf;
}
...
}
public class EMFactory implements Factory<EntityManager> {
private final EntityManager em;
@Inject
public EMFactory (EntityManagerFactory emf){
em = emf.createEntityManager();
}
public EntityManager provide() {
return em;
}
...
}
还没有测试过这个确切的实现,但它应该看起来像这样.我以前用过这种模式.
Haven't tested this exact implementation out, but it should look something like this. I've used this pattern before.
register(new AbstractBinder() {
@Override
public void configure() {
bindFactory(EMFFactory.class).to(EntityManagerFactory.class).in(Singleton.class);
bindFactory(EMFactory.class).to(EntityManager.class).in(RequestScoped.class);
}
});
<小时>
更新
关于上面的例子需要注意的一点是它不会清理资源,即 EntityManager
应该关闭;它不会自行关闭.Factory
类中有一个 dispose
方法,我们需要重写它,但根据我的经验,Jersey 永远不会调用它.
UPDATE
One thing to note about the above example is that it doesn't clean up resources, i.e. the EntityManager
should be close; it won't close itself. There is a dispose
method in the Factory
class that we need to override, but from my experience, this is never called by Jersey.
我们可以做的是将 EntityManager
添加到 [CloseableService
][1]
What we can do is add the EntityManager
to a [CloseableService
][1]
public class EMFactory implements Factory<EntityManager> {
private final EntityManagerFactory emf;
private final CloseableService closeService;
@Inject
public EMFactory (EntityManagerFactory emf, CloseableService closeService){
this.emf = emf;
this.closeService = closeService;
}
public EntityManager provide() {
final EntityManager em = emf.createEntityManager();
this.closeService.add(new Closeable(){
@Override
public void close() {
em.close();
}
});
return em;
}
...
}
这样可以确保 EntityManager
在请求结束时关闭.
This way the EntityManager
is ensured to be closed at the end of the request.
这篇关于如何在 jersey/hk2 应用程序中正确配置 EntityManager?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!