本文介绍了如何管理CDI环境中的EntityManager生命周期(使用Tomcat)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个应用程序,并且已经开始使用

我对 CDI 生命周期非常困惑$ c> beans和我需要一个好的建议来清除我脑海中的一些东西。
通常我读过的是 EntityManager 应该主要用在 Java EE 容器中,注入它使用 PersistenceContext 注释。那么容器就会关心它的生活。但是,如果您不使用 Java EE 容器(如 Tomcat ),那么我需要管理 EntityManager 的人生。



现在我最好的选择是使用 Tomcat,CDI,JSF和JPA ?
我现在正在做的是:
$ b $ pre $ public class EntityManagerFactoryProducer {

public static final String TEST =test;
$ b @ broduces
@ApplicationScoped
public EntityManagerFactory create(){
return Persistence.createEntityManagerFactory(TEST);


$ b $ public void destroy(@Disposes
EntityManagerFactory factory){
factory.close();



公共类EntityManagerProducer {

@Inject
私有临时记录器记录器;

@Inject
私人EntityManagerFactory emf;

@Produces
public EntityManager create(){
return emf.createEntityManager();


public void destroy(@Disposes
EntityManager em){
em.close();
logger.debug(String.format(%s Entity manager was closed,em));



@Named
@ViewScoped
@Interceptors(LoggingInterceptor.class)
public class ProductBacking implements Serializable {

@Inject
private ProductDAO productDAO;






  @ ViewScoped 
public class ProductDAOImpl实现ProductDAO,Serializable {
private static final long serialVersionUID = 4806788420578024259L;

private static final int MAX_RANDOMIZED_ELEMENTS = 3000;

@Inject
私有瞬态记录器记录器;

@Inject
私人EntityManager entityManager;

@Override
公开列表<产品> getSuggestedProducts(){
logger.debug(String.format(%s Entity manager get products,entityManager));

return entityManager.createQuery(SELECT p FROM Product p ORDER BY random(),Product.class).setMaxResults(
MAX_RANDOMIZED_ELEMENTS).getResultList();
}

@Override
public void saveProduct(Product product){
logger.debug(String.format(%s Entity manager save product,entityManager) );

entityManager.getTransaction()。begin();
entityManager.merge(product);
entityManager.getTransaction()。commit();
}

@PreDestroy
void destroy(){
entityManager.close();
}

}

所以基本上我只是使用plain CDI 来完成此操作。
但是,我不确定这是否是标准的做法,更重要的是,我不知道如何在bean生命后关闭 EntityManager 结束了。
作为总结:我最终得到了许多未关闭的连接( EntityManager s),所以内存泄漏。



解决方案

这不是关于CDI。
EntityManager的生命周期取决于它的类型,它可以是:


  1. 容器管理的事务,
  2. 容器管理的扩展,
  3. 应用程序管理。

前两个仅适用于全面的应用程序服务器。所以如果你要坚持一个servlet容器,你会被缩小到第三个选项。

您必须在您的应用程序中明确打开和关闭EM。
这很简单:创建一个EntityManagerFactory的应用程序范围的实例,将它注入到所有的bean中。当你需要一个EM创建它时,使用并立即关闭,而不用等待bean的上下文结束。
因为在这个配置中,一个开放的EntityManager将保留一个连接,并且长寿命的bean将会连接失败。
您可以在的ObjectDB手册。


I am developing one application and I have started to use CDI along with JSF and JPA. The web container is Tomcat.

I am very confused about EntityManager life-cycle in my CDI beans and I would need a good advise to clear some stuff in my mind.Generally what I've read is that EntityManager should be used mainly in a Java EE container, injecting it using PersistenceContext annotation. So then the container takes care about its life. However, if you do not use Java EE container(as Tomcat), then I need to manage my EntityManager's life.

Which are my best options now, using Tomcat, CDI, JSF and JPA?What I am currently doing now is the following :

public class EntityManagerFactoryProducer {

    public static final String TEST = "test";

    @Produces
    @ApplicationScoped
    public EntityManagerFactory create() {
        return Persistence.createEntityManagerFactory(TEST);

    }

    public void destroy(@Disposes
    EntityManagerFactory factory) {
        factory.close();
    }
}

public class EntityManagerProducer {

    @Inject
    private transient Logger logger;

    @Inject
    private EntityManagerFactory emf;

    @Produces
    public EntityManager create() {
        return emf.createEntityManager();
    }

    public void destroy(@Disposes
    EntityManager em) {
        em.close();
        logger.debug(String.format("%s Entity manager was closed", em));
    }
}

@Named
@ViewScoped
@Interceptors(LoggingInterceptor.class)
public class ProductBacking implements Serializable {

    @Inject
    private ProductDAO productDAO;


@ViewScoped
public class ProductDAOImpl implements ProductDAO, Serializable {
    private static final long serialVersionUID = 4806788420578024259L;

    private static final int MAX_RANDOMIZED_ELEMENTS = 3000;

    @Inject
    private transient Logger logger;

    @Inject
    private EntityManager entityManager;

    @Override
    public List<Product> getSuggestedProducts() {
        logger.debug(String.format("%s Entity manager get products", entityManager));

        return entityManager.createQuery("SELECT p FROM Product p ORDER BY random()", Product.class).setMaxResults(
                MAX_RANDOMIZED_ELEMENTS).getResultList();
    }

    @Override
    public void saveProduct(Product product) {
        logger.debug(String.format("%s Entity manager save product", entityManager));

        entityManager.getTransaction().begin();
        entityManager.merge(product);
        entityManager.getTransaction().commit();
    }

    @PreDestroy
    void destroy() {
        entityManager.close();
    }

}

So basically I am just using plain CDI to accomplish this.However, I am not sure if this is standard way of doing it, and what is more important, I do not know how to close the EntityManager after bean life is over.As as summary: I end up with many unclosed connections (EntityManagers), so memory leak.

Can someone help me understand how should I proceed ? Thank you very much.

解决方案

It's not about CDI.EntityManager's life cycle depends on its type, which can be:

  1. container-managed transactional,
  2. container-managed extended,
  3. application-managed.

The first two are only available in a full-blown application server. So if you're going to stick with a servlet container you're narrowed to the 3rd option.

You will have to explicitly open and close EMs in your application.It's straightforward: create an application-wide instance of EntityManagerFactory, inject it to all your beans. When you need an EM just create it, use and then immediately close without waiting for your bean's context to end. Because in this configuration an open EntityManager will retain a connection and with long-lived beans you'll run out of connections. You can find an easy and comprehensive explanation in the Obtaining a JPA Database Connection section of the ObjectDB manual.

这篇关于如何管理CDI环境中的EntityManager生命周期(使用Tomcat)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-23 21:53