we are currently migrating from JavaEE5 to JavaEE6 and are using JBoss 6.0.0 and JSF2. For simplicity this example is constructed and based on the Maven archetype: org.jboss.weld.archetypes:jboss-javaee6-webapp:1.0.1.CR2
I have added a simple LAZY relationship to User
:
@NotNull @ManyToMany(fetch=FetchType.LAZY)
private List<Address> addresses;
This bea开发者_StackOverflown is part of the maven archetype, and I added a few lines to retrieveAllMembersOrderedByName()
.
@RequestScoped
public class MemberListProducer {
@Inject private Logger log;
@Inject @MemberRepository
private EntityManager em;
private List<Member> members;
@Produces @Named
public List<Member> getMembers(){return members;}
@PostConstruct
public void retrieveAllMembersOrderedByName()
{
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> criteria = cb.createQuery(Member.class);
Root<Member> member = criteria.from(Member.class);
criteria.select(member).orderBy(cb.asc(member.get("name")));
members = em.createQuery(criteria).getResultList();
Member m1 = members.get(0);
log.info("Id: "+m1.getId());
Member m2 = em.find(Member.class, m1.getId());
log.info("Addr m1: "+m1.getAddresses().size()); // OK
log.info("Addr m2: "+m2.getAddresses().size()); // Error
}}
As you see, the List<Member>
is retrieved by a CriteriaQuery, then the Member m1
is taken from the List and Member m2
is explicitly loaded from the same EntityManager em
. Now the interesting part: m1.getAddresses().size()
works, m2.getAddresses().size()
gives a
15:41:32,910 ERROR [org.hibernate.LazyInitializationException]
failed to lazily initialize a collection of role: test.Member.addresses,
no session or session was closed: org.hibernate.LazyInitializationException:
failed to lazily initialize a collection of role:test.Member.addresses,
no session or session was closed
Can anybody explain this, or knows how to solve this issue? Thank you, Thor
This is normal behavior for lazy loading all your lazy classes are proxy. and when you fetching the class from proxy your Hibernate session is already closed.
The solution is to implement Open Session in View Filter which will keep your Hibernate session open until your Request is alive.
You can read more about it in this article
http://community.jboss.org/wiki/OpenSessionInView
If you are using Spring Framework then you already have this job done OpenSessionInViewFilter
class.
Hope it helps.
Thor, can you please double check? I thought this was interesting and tried it myself, however I'm getting the exception in both calls. Neither of them work. I could be doing something wrong but I've checked a couple of times and both methods give me that exception. Do you get the logger to log the size of the first collection?
You can fetch related objects dynamically through code given below which has default lazy initialization :
criteria.setFetchMode("addresses", FetchMode.JOIN);
精彩评论