Hi. I've been using Hibernate on my web app for a while, and I decided to switch to a pure JPA approach, so I'm using EntityManagerFactory instead of SessionFactory, and persistence.xml instead of hibernate.cfg.xml.
The problem is, when I made the required changes, I started getting "LazyInitializationException - no session or session was closed" errors, on -and this is what puzzles me- class attributes and many-to-one relationships, when I tried to access them from my view. AFAIK, the JPA standard defines lazy initialization by default only for collections, and I don't have any explicit lazy initialization annotations on my entities.
I solved the problem by using Spring's OpenEntityManagerInViewFilter, but I'm still wondering why I got those errors.
This is my config, in case that matters. I'm using Spring's shared EntityManager approach, and I've got two EntityManagerFactory beans defined, each one pointing to a different persistence unit.
Spring config:Code:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml" />
<property name="persistenceUnitName" value="mainPersistenceUnit" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
</bean>
<bean id="entityManagerFactorySec" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml" />
<property name="persistenceUnitName" value="securityPersistenceUnit" />
<property name="dataSource" ref="dataSourceSec" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
</bean>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
persistence.xmlCode:
<?xml version='1.0' encoding='utf-8'?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="mainPersistenceUnit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<non-jta-data-source>dataSource</non-jta-data-source>
<!-- some class elements here -->
<exclude-unlisted-classes/>
</persistence-unit>
<persistence-unit name="securityPersistenceUnit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<non-jta-data-source>dataSourceSec</non-jta-data-source>
<!-- some class elements here -->
<exclude-unlisted-classes/>
</persistence-unit>
</persistence>
This is the transaction demarcation configuration:Code:
<bean
class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="retrieve*" read-only="true"/>
<tx:method name="search*" read-only="true"/>
<tx:method name="*" rollback-for="java.lang.Exception"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut
expression="execution(* my.service.package.*.*(..))" id="operation"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="operation"/>
</aop:config>
My DAOs have the EntityManager injected by the PersistenceExceptionTranslationPostProcessor bean defined above using PersistenceContext annotation:Code:
@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
Thanks in advance.