1

I'm trying to solve my LazyLoading problem, which I worked around by fetchType EAGER in the past. But that cannot be the final solution.

I tried to contruct an example, which does not make much sence the way it is, but demonstrates my problem: I have a company, and persons are @ManyToOne by composition. Now when I try to access the personList by a calculator, I get this exception:

Schwerwiegend [javax.enterprise.resource.webcontainer.jsf.context] (http--127.0.0.1-8080-4) javax.el.ELException: /tablePersons.xhtml @31,76 value=" #{calculator.getPersonCount(_var)}":
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: business.domain.Company.personList, no session or session was closed

Maybe someone can help me solving this?

tablePersons.xhtml:

<p:dataTable var="_var" value="#{facade.companies}">
<p:column>
<h:outputText value="#{calculator.getPersonCount(_var)}" />

backing facades:

@Named
@RequestScoped
class Facade() {
    @Inject
    Dao dao;

    List<Company> companies;

    @PostConstruct
    init() {
        companies = Dao.findByNamedQuery("Companies.ALL");
    }
}


@Named
@RequestScoped
class Calculator {
    int getPersonCount(Company c) {
        return c.getPersonList().size(); //EX
    }
}

Crud service:

@Stateless
@Transactional
class Dao() {
    @PersistenceContext
    private EntityManager em;

    //CRUD
}

Entity:

@Entity
@NamedQueries( {
    @NamedQuery(name = Company.ALL",
                query = "SELECT c FROM Company c")
})
class Company {
    @OneToMany(cascade = CascadeType.ALL)  // fetch=FetchType.EAGER <-ugly, but would work
    List<Person> personList = new LinkedList<Person>();
}

I also already configured the Spring OpenEntityManager in web.xml:

<filter>
    <filter-name>OpenEntityManagerInViewFilter</filter-name>
    <filter-class>
        org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
    </filter-class>
    <init-param>
        <param-name>entityManagerFactoryBeanName</param-name>
        <param-value>entityManagerFactory</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>OpenEntityManagerInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Nevertheless it does not work. But I have not more idea why! Maybe someone knows more?

tyvm

membersound
  • 66,525
  • 139
  • 452
  • 886

1 Answers1

2

To solve the LazyInitializationException occurs in the view layer , you have the following options:

  1. Use "Open EntityManager in View" pattern to lazy load the uninitialized entities in the view .It seems that you are doing this way , but I have no idea why it is failed.

  2. Before returning to the view , always initialize all the entities that are required to be displayed in the view .

You can use Hibernate.initialize() to force initializing the Company.personList :

class Facade() {
    @Inject
    Dao dao;

    List<Company> companies;

    @PostConstruct
    init() {
        companies = Dao.findByNamedQuery("Companies.ALL");
        Hibernate.initialize(companies.getPersonList()); 
    }
} 

Or use the fetch join to fetch the personList along with the Company.It will cause the returned Companies object have their personList fully initialized.

@Entity
@NamedQueries( {
    @NamedQuery(name = "Company.ALL",query = "SELECT c FROM Company c")
    @NamedQuery(name = "Company.ALL.WithPerson",query = "SELECT c FROM Company c join fetch c.personList")
})
class Company {
    @OneToMany(cascade = CascadeType.ALL)  // fetch=FetchType.EAGER <-ugly, but would work
    List<Person> personList = new LinkedList<Person>();
}

Then retrieve the company using the named query "Company.ALL.WithPerson"

Ken Chan
  • 64,456
  • 22
  • 117
  • 138
  • 1
    man thanks for your answer, I really appreciate this!! In the meantime I discovered that it would work if I use `@PersistenceContext(type=PersistenceContextType.EXTENDED)` , but I don't know if this is a good practice? Otherwise I would choose your solution with the initialize in postconstruct. – membersound Mar 04 '12 at 12:23
  • You are welcome . I have not much experience in `@PersistenceContext(type=PersistenceContextType.EXTENDED)` . so I cannot comment it. But for the "Open EntityManager in View" or "Open Session in View" pattern ,I personally not favour it .You can refer it at http://stackoverflow.com/questions/1103363/why-is-hibernate-open-session-in-view-considered-a-bad-practice – Ken Chan Mar 05 '12 at 01:41