I am encountering some problems with a web app that uses Spring, Hibernate and JPA. The problems are very high memory consumption which increases over time and never seems to decrease. They most likely stem from an incorrect usage of the EntityManager. I have searched around but I haven't found something for sure yet.
We are using DAOs which all extend the following GenericDAO where our ONLY EntityManager is injected:
public abstract class GenericDAOImpl<E extends AbstractEntity<P>, P> implements
GenericDAO<E, P> {
@PersistenceContext
@Autowired
private EntityManager entityManager;
[...]
The generic DAO is used because it has methods to get entities by ID and so on which would be a pain to implement in all ~40 DAOs.
The EntityManager is configured as a Spring bean in the following way:
<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" />
The biggest problem I think is using this shared EntityManager for everything. In the services classes, we are using the @Transactional annotation for methods which require a transaction. This flushes the EntityManager automatically from what I read, but does is different from clearing, so I guess the objects are still in memory.
We noticed an increase in memory after each automatic import of data in the DB which happens every day (~7 files of 25k lines each, where a lot of linked objects are created). But also during normal functioning, when retrieving lots of data (let's say 100-200 objects at a time for a request).
Anyone has any idea how I could improve the current situation (because it's kind of bad at this point...)?
Edit: Have run a profiler on the deployed app and this is what it found:
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".
This is probably the EntityManager is not cleared?