本文介绍了如何在运动衫/ hk2应用程序中正确配置EntityManager?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用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 this

public 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 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);
    }
});


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.

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?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 19:45