簡體   English   中英

如何在jersey / hk2應用程序中正確配置EntityManager?

[英]How do I properly configure an EntityManager in a jersey / hk2 application?

我有一個使用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<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: 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<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;
    }
    ...
}

沒有測試過這個確切的實現,但它看起來應該是這樣的。 我以前用過這種模式。

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<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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM