如何在jersey / hk2应用程序中正确配置EntityManager?

我有一个使用JPA持久性的jersey-2 / hk2应用程序。 EntityManager在启动时就像这样绑定

 public MyApplication() { // ... register(new AbstractBinder() { @Override public void configure() { bindFactory(EmFactory.class) .to(EntityManager.class) .in(RequestScoped.class); } }); } 

与工厂类一样

 public class EmFactory implements Factory { 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: 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的正确方法是什么?

一种选择是,不是在EMFactory中创建新的EntityManagerFactory (在请求范围内),您可以为EntityManagerFactory创建一个单独的工厂,然后将EntityManagerFactory注入EMFactory

 public class EMFFactory implements Factory { private final EntityManagerFactory emf; public EMFFactory (){ emf = Persistence.createEntityManagerFactory(persistenceUnit); } public EntityManagerFactory provide() { return emf; } ... } public class EMFactory implements Factory { private final EntityManager em; @Inject public EMFactory (EntityManagerFactory emf){ em = emf.createEntityManager(); } public EntityManager provide() { return em; } ... } 

没有测试过这个确切的实现,但它看起来应该是这样的。 我以前用过这种模式。

 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

关于上述示例需要注意的一点是它不会清理资源,即EntityManager应该关闭; 它不会自行关闭。 我们需要覆盖Factory类中的dispose方法,但根据我的经验,Jersey从不调用它。

我们可以做的是将EntityManager添加到[ CloseableService ] [1]

 public class EMFactory implements Factory { 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