[英]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);
}
});
關於上述示例需要注意的一點是它不會清理資源,即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.