如何在CDI环境中管理EntityManager生命周期(使用Tomcat) [英] How to manage EntityManager life-cycle in CDI environment (using Tomcat)

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

问题描述

我正在开发一个应用程序,并且已经开始将CDIJSFJPA一起使用. Web容器为Tomcat.

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

对于CDI豆中的EntityManager生命周期,我感到非常困惑,我需要一个很好的建议来清除一些想法. 通常,我读到的是EntityManager应该主要在Java EE容器中使用,并使用PersistenceContext注释注入它.因此,容器会照顾好其使用寿命.但是,如果您不使用Java EE容器(如Tomcat),那么我需要管理EntityManager的寿命.

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.

使用Tomcat, CDI, JSF and JPA现在是我最好的选择? 我现在正在做的事情如下:

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

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

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?

推荐答案

这与CDI无关. EntityManager的生命周期取决于其类型,可以是:

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

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

前两个仅在功能完善的应用程序服务器中可用.因此,如果您要坚持使用servlet容器,则可以选择第3个选项.

您将必须在应用程序中显式打开和关闭EM. 这很简单:创建EntityManagerFactory的应用程序范围的实例,然后将其注入到所有bean中.当您需要EM时,只需创建它,即可使用它,然后立即关闭它,而无需等待bean的上下文结束. 因为在此配置中,打开的EntityManager将保留连接,而对于寿命长的bean,您将用尽连接. 您可以在 获得JPA数据库连接 在ObjectDB手册中.

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆