Ioa*_*oan 19 java hibernate jpa java-ee cdi
我正在开发一个应用程序,我已经开始使用CDI沿JSF和JPA.Web容器是Tomcat.
我EntityManager对我的CDI豆子里的生命周期非常困惑,我需要一个很好的建议来清除我心中的一些东西.一般来说,我读过的是EntityManager主要应该在Java EE容器中使用,使用PersistenceContext注释注入它.因此,容器会照顾它的生命.但是,如果你不使用Java EE容器(as Tomcat),那么我需要管理我EntityManager的生活.
使用哪个是我最好的选择Tomcat, CDI, JSF and JPA?我现在正在做的是以下内容:
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;
Run Code Online (Sandbox Code Playgroud)
@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();
}
}
Run Code Online (Sandbox Code Playgroud)
所以基本上我只是用plain CDI来完成这个.但是,我不确定这是否是标准的做法,更重要的是,我不知道如何关闭EntityManager豆后生活已经结束.总结:我最终得到许多未闭合的连接EntityManager,因此内存泄漏.
有人可以帮我理解我该怎么办?非常感谢你.
Yur*_*uri 19
这不是关于CDI.EntityManager的生命周期取决于其类型,可以是:
前两个仅在完整的应用程序服务器中可用.因此,如果您要坚持使用servlet容器,那么您将缩小到第3个选项.
您必须在应用程序中明确打开和关闭EM.它很简单:创建一个应用程序范围的EntityManagerFactory实例,将其注入所有bean.当你需要EM时只需创建它,使用然后立即关闭而不等待bean的上下文结束.因为在此配置中,打开的EntityManager将保留连接,并且对于长寿命的bean,您将耗尽连接.您可以在ObjectDB手册的" 获取JPA数据库连接"部分中找到简单而全面的说明.
Asi*_*tto 12
您可以使用CDI Scopes维护CDI bean状态.实际上EntityManagerProducer#create()错过了范围.无论你在其Weld或OpenWebBean中配置/安装CDI的RI,你都可以将你的cdi bean状态定义为belwo.
@Produces @RequestScoped
public EntityManager create() {
return emf.createEntityManager();
}
Run Code Online (Sandbox Code Playgroud)
你的问题是
1. CDI, JSF and JPA2.
2. Managing EntityManager lifecycle when using JPA in a non enterprise environment (e.g. Tomcat)
Run Code Online (Sandbox Code Playgroud)
1. CDI,JSF和JPA2.
Tomcat容器不支持CDI开箱,甚至不支持JSF,你知道开发人员必须提供JSF jars他们自己的.JSF 2.2有新的CDI兼容scops @ViewScoped这里是CDI-only @FlowScoped没有相同的对于@ManagedBean.
(1)真的如果你最感兴趣的话就是使用CDI或CDI + JSF + JPA,那么将tomcat升级到TomEE或者使用TomEE.Tomcat + Java EE = TomEE.Tomcat的Java企业版,使用TomEE,您可以使用JPA获得Tomcat.
(2)如果您无法控制升级tomcat服务器,那么您必须执行i.提供CDI和其他一些jar和配置文件以及我们自己的应用程序.II.在tomcat中安装CDI(Weld或OpenWebBeans这些都是主要的CDI实现)
(3)Tomcat 8. Tomcat 8与Java EE 7对齐.
2)管理EntityManager生命周期
在非企业环境(例如Tomcat)或Java SE中使用JPA时管理EntityManager生命周期是一项自定义任务.在这种情况下,您应该考虑使用EntityManager的正确范围,并且在使用资源时,确保在不再需要时关闭它们始终很重要.
There are three main types of EntityManagers defined in JPA.
Container Managed and Transaction Scoped Entity Managers
Container Managed and Extended Scope Entity Managers
Application Managed Entity Managers
Run Code Online (Sandbox Code Playgroud)
使用JPA有两种我们可以处理的资源:EntityManager和事务.在这种情况下,您应该考虑使用EntityManager的正确范围.
1. An EntityManager is not a heavyload object.
There is no need to use the same EntityManger longer than needed,
You can't use an EntityManager instance for the whole application lifecycle (application scope) for the EntityManager is not Thread-safe)
2. It's not safe to traverse lazy-loaded relationships once the EntityManager is closed (This situation will change as of JPA 2.0).
i.)Method scope (i.e. instantiate/destroy one EntityManager in each business method).
The method scope is not enough for every situation. There could be some scenarios where you'll need a wide scope, such as the following situations:
i. When transactions spread multiple business methods.
ii. Need to traverse lazy-loaded relationships outside a method (e.g. in a JSF page).
In method scope be careful to ensure the EntityManger is always closed
ii.)Request scope (on-demand creation of the EntityManager instance to use within the request service)
EntityManager per HTTP request strategy with the following features:
i. Creation on demand of the EntityManager.
ii. Lazy closing of the EntityManager.
The main benefit of this scope is derived from the delayed closing of the EntityManager (it will last as long as a HTTP request is in process).
Every queried entity will be managed till the end of the request and therefore during the presentation phase (the render phase in JSF for instance).
Run Code Online (Sandbox Code Playgroud)
在您的情况下,您正在使用应用程序实体管理器和应用程序管理事务,这意味着它应该处理事务的代码.简而言之,它意味着:
你打电话:
entityManager.getTransaction().begin(); //to start a transaction
Run Code Online (Sandbox Code Playgroud)
如果成功,你将确保打电话
entityManager.getTranasaction().commit(); //to commit changes to database
Run Code Online (Sandbox Code Playgroud)
如果失败,您将确保致电:
entityManager.getTransaction().rollBack();
Run Code Online (Sandbox Code Playgroud)
现在假设你有一个容器,它知道何时调用begin(), commit() or rollback(),这就是容器管理的事务.
主要问题是您的实体经理生产者没有范围.因此,它永远不会被清理.您应该为您的实体经理提供范围.
另一件事是Apache DeltaSpike已经解决了这个问题.为什么不使用DeltaSpike? https://deltaspike.apache.org/documentation/jpa.html
| 归档时间: |
|
| 查看次数: |
20643 次 |
| 最近记录: |