gpt4 book ai didi

java - JPA EntityManager 大内存问题

转载 作者:搜寻专家 更新时间:2023-11-01 02:51:43 25 4
gpt4 key购买 nike

我在使用 Spring、Hibernate 和 JPA 的 Web 应用程序时遇到了一些问题。问题是非常高的内存消耗,它会随着时间的推移而增加,而且似乎永远不会减少。它们很可能源于 EntityManager 的不正确使用。我四处搜寻,但还没有找到确定的东西。

我们使用的 DAO 都扩展了以下 GenericDAO,其中注入(inject)了我们唯一的 EntityManager:

public abstract class GenericDAOImpl<E extends AbstractEntity<P>, P> implements
GenericDAO<E, P> {

@PersistenceContext
@Autowired
private EntityManager entityManager;
[...]

之所以使用通用 DAO,是因为它具有通过 ID 等获取实体的方法,这在所有约 40 个 DAO 中实现起来会很痛苦。

EntityManager 通过以下方式配置为 Spring bean:

<bean class="org.springframework.orm.jpa.JpaTransactionManager"
id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven mode="aspectj"
transaction-manager="transactionManager" />
<bean
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
id="entityManagerFactory">
<property name="persistenceUnitName" value="persistenceUnit" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="entityManager" factory-bean="entityManagerFactory"
factory-method="createEntityManager" scope="singleton" />

我认为最大的问题是对所有内容都使用这个共享的 EntityManager。在服务类中,我们对需要事务的方法使用@Transactional 注释。这会根据我读取的内容自动刷新 EntityManager,但它与清除不同,所以我猜这些对象仍在内存中。

我们注意到在每天自动导入数据库中的数据后内存增加(约 7 个文件,每个文件 25k 行,其中创建了大量链接对象)。而且在正常运行期间,当检索大量数据时(假设一次请求有 100-200 个对象)。

有谁知道我可以如何改善目前的情况(因为目前情况有点糟糕...)?

编辑:在部署的应用程序上运行分析器,这是它发现的:

One instance of "org.hibernate.impl.SessionFactoryImpl" loaded by "org.apache.catalina.loader.WebappClassLoader @ 0xc3217298" occupies 15,256,880 (20.57%) bytes. The memory is accumulated in one instance of "org.hibernate.impl.SessionFactoryImpl" loaded by "org.apache.catalina.loader.WebappClassLoader @ 0xc3217298".

这可能是EntityManager没有清空?

最佳答案

我倾向于同意您的评估。 EntityManagers aren't really designed to be used as singletons .刷新 EntityManager 不会从内存中清除任何内容,它只会将实体与数据库同步。

可能发生的情况是 EntityManager 保持对持久性上下文中所有对象的引用,而您永远不会关闭上下文。 (This guy 有类似的问题。)清除它确实会删除 EntityManager 对您的实体的所有引用,但是,如果您发现自己经常需要调用 clear(),您可能应该重新评估您通常如何使用 EntityManager。如果您只是想避免 LazyInitializationExceptions,请考虑 Spring* 的 OpenSessionInViewFilter。这允许您延迟加载实体,同时仍然让 Spring 管理 bean 的生命周期。 bean 的生命周期管理是 Spring Framework 的一大优势,因此您需要确保覆盖该行为确实是您想要的。

确实在某些情况下您需要一个长期存在的 EntityManager,但这些情况相对较少并且需要大量的理解才能正确实现。

*注意:OpenSessionInView 需要非常小心以避免 N+1 problem .这是一个很大的问题 some call Open Session in View an AntiPattern .谨慎使用。

编辑

此外,您也不需要使用 @Autowired 注释 @PersistenceContext 元素。 @PersistenceContext 自己进行连接。

关于java - JPA EntityManager 大内存问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10012751/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com