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

1 Answer 1

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"

Sign up to request clarification or add additional context in comments.

2 Comments

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.
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 stackoverflow.com/questions/1103363/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.