开发者

LazyInitializationException in @RequestScoped Bean after explicit EntityManager.find

开发者 https://www.devze.com 2023-03-10 23:20 出处:网络
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-java

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);

0

精彩评论

暂无评论...
验证码 换一张
取 消