Hello.
I'm using JPA DAO's managed by Spring container for fetching entities that will be serialized to remote Swing clients. That means there is no web here (no conventional MVC web framework, no web controllers, no JPS's, etc... ), so I guess this is not an Open Session in View case, but I may be wrong.
In order to force the fetching of the 'n' part in the '1-n' relationship which fetching type is 'LAZY', the code throwing the exception calls a method (size()) on the lazy fetched member (a List) of the entity. Both method call and entity retrieval are performed inside the same DAO method:
Code:
public class SistemaJPA implements SistemaDAO {
@PersistenceContext
private EntityManager em;
@Override
public Servicio getRootAndChildren() {
//'root' is expected to be an entity instance managed by 'em'
Servicio root = em.createNamedQuery("Servicio.raiz", Servicio.class).getSingleResult();
em.isOpen(); //returns true
em.contains(root)); //returns false!
//call list.size() for retrieving lazy 1-n relationship
root.getChildren().size(); //<<===== EXCEPTION HERE
return raiz;
}
}
Exception thrown:
Code:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.yomismamente.miapl.entidades.Servicio.children, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:122)
at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
at com.yomismamente.miapl.servicios.datos.SistemaISD.darRaizConHijos(SistemaJPA.java:16)
at com.yomismamente.miapl.servicios.logica.SistemaISL.cargarServicios(SistemaISL.java:15)
... 21 more
The entity has a recursive 1-n relationship. I think this is not relevant to the problem except in that it excludes using 'eager' fetch type as a workaround:
Code:
@Entity
@NamedQueries({
@NamedQuery(name = "Servicio.raiz", query = "SELECT s FROM Servicio s WHERE s.categ is null")
})
public class Servicio implements Serializable {
@Id
@Column(name = "ID")
private Integer id;
@OneToMany(mappedBy = "categ")
private List<Servicio> children;
@JoinColumn(name = "CATEG", referencedColumnName = "ID")
@ManyToOne
private Servicio categ;
//... more ...
}
And finally the Spring configuration:
Code:
<bean id="jedEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="jedDataSource"/>
<property name="persistenceUnitName" value="jed"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="H2" />
<property name="showSql" value="true" />
</bean>
</property>
</bean>
<bean id="JpaTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="jedEmf"/>
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="sistemaJPA" class="com.yomismamente.miapl.servicios.datos.SistemaJPA"/>
I thought that all this DAO method code would be running inside the same transaction and the same EntityManager (Hibernate Session) would be used for any operation on managed entities.
So:
- How is it possible that there is 'no session (entity manager) or session was closed'?
- Why the entity just retrieved by the entity manager is not managed by that EM?
- What am I doing wrong?
- Is there any fix or workaround?
- Does this anything to to with SPR-7752 Shared EntityManager proxy does not expose JPA Provider EntityManager interface if not configured explicitly
Please help.
Thank you!