2

First of all, I use Java EE, Hibernate with EntityManager and PrimeFaces.

I have one EJB module (business logic and domain) and two WAR modules (Jersey WS and JSF PrimeFaces).

I decided to initialize lazy collections in JSF WAR module to avoid lazy initialization exception. I don't use extended entity manager.

@ManagedBean(name = "company")
@SessionScoped
public class CompanyBean {

    @EJB
    private CompanyFacade cf;

    ...

    public String showDetails(Long id) {
        company = cf.find(id);
        Hibernate.initialize(company.getCompanyTypes());
        Hibernate.initialize(company.getPrimaryUser());
        Hibernate.initialize(company.getBlocked());
        Hibernate.initialize(company.getAddresses());
        Hibernate.initialize(company.getContacts());
        return "DETAILS";
    }

    ...
}

And I get:

Caused by: org.hibernate.HibernateException: collection is not associated with any session at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:474) at org.hibernate.Hibernate.initialize(Hibernate.java:417) at minepackage.CompanyBean.showDetails(CompanyBean.java:79) ...

I don't understand it. There has to be a session when one line before the initialization it was fetched from database, doesn't it? I initialize attributes in WS module in similar way and there it's working.

Any idea what's happening?

ziri
  • 513
  • 7
  • 18

1 Answers1

6

I think the session is closed after your EJB finished, so the objects are in detached state. So Hibernate.initialize() won't work any more. You have multiple options here:

  • Open the transaction on the client side (in your JSF bean or in a servlet filter). This way the session will still be open when your are calling Hibernate.initialize().
  • Modify your EJB to load the full object and all the required collections. You could use fetch joins and/or use Hibernate.initialize() there.
  • Create a more fine grained API in your EJB. Method like CompanyFacade.getAddressesByCompany().

I would prefer a combination of the latter two. Use fetch joins to load the one-to-one and many-to-one relationships in your find method and add extra methods for loading the one-to-many collections (like addresses). This will also improve performance of your backend because it reduces the number of database queries.

chkal
  • 5,598
  • 21
  • 26