问题描述
我有一个使用JPA持久性的jersey-2 / hk2应用程序。 EntityManager
在启动时绑定如下
public MyApplication(){
// ...
注册(新的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的日志中收到警告:
HHH000436:实体管理器工厂名称(单位)已经注册。 \
如果实体管理器将被集群或钝化,请为属性hibernate.ejb.entitymanager_factory_name指定唯一的\
值
我做错了什么?在jersey-2 / hk2应用程序中初始化EntityManager的正确方法是什么?
一个选项是替代创建在 EMFactory
(在请求范围内)的新的 EntityManagerFactory
,您可以创建一个单例工厂, code> EntityManagerFactory ,然后将 EntityManagerFactory
注入到 EMFactory
中。 / p>
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;
}
...
}
尚未测试这个确切的实现,但它应该看起来像这样。我以前使用过这种模式。
注册(新的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
类中有一个处理
方法,但从我的经验来看,这不是
我们可以做的是将
EntityManager
添加到[] [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提供(){
final EntityManager em = emf.createEntityManager();
this.closeService.add(new Closeable(){
@Override
public void close(){
em.close();
}
});
return em;
}
...
}
code> EntityManager 确保在请求结束时关闭。
I have a jersey-2 / hk2 application which uses JPA persistence. The
EntityManager
is bound at startup like thispublic MyApplication() { // ... register(new AbstractBinder() { @Override public void configure() { bindFactory(EmFactory.class) .to(EntityManager.class) .in(RequestScoped.class); } }); }
with the factory class being
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(); } } }
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'
What am I doing wrong? What is the proper way to initialize an EntityManager in a jersey-2 / hk2 application?
解决方案One option is to instead of creating a new
EntityManagerFactory
in theEMFactory
(which is in a request scope), you could create a singleton factory for theEntityManagerFactory
, then just inject theEntityManagerFactory
into theEMFactory
.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); } });
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 adispose
method in theFactory
class that we need to override, but from my experience, this is never called by Jersey.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; } ... }
This way the
EntityManager
is ensured to be closed at the end of the request.这篇关于如何在运动衫/ hk2应用程序中正确配置EntityManager?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!