Ленивая загрузка с весны и зимней спячки - PullRequest
1 голос
/ 03 марта 2012

Я пытаюсь решить мою проблему LazyLoading, которую я раньше обходил fetchType EAGER. Но это не может быть окончательным решением.

Я попытался придумать пример, который не имеет особого смысла, но демонстрирует мою проблему: У меня есть компания, и люди @ManyToOne по составу. Теперь, когда я пытаюсь получить доступ к personList с помощью калькулятора, я получаю следующее исключение:

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

Может быть, кто-то может помочь мне решить эту проблему?

tablePersons.xhtml:

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

опорные фасады:

@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
    }
}

Сырая услуга:

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

    //CRUD
}

Организация:

@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>();
}

Я также уже настроил Spring OpenEntityManager в 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>

Тем не менее, это не работает. Но я понятия не имею, почему! Может кто знает больше?

tyvm

1 Ответ

2 голосов
/ 04 марта 2012

Чтобы решить, что LazyInitializationException происходит в слое вида, у вас есть следующие опции:

  1. Использовать шаблон «Открыть EntityManager в представлении» для отложенной загрузки неинициализированных объектов в представлении. Похоже, что вы делаете это, но я понятия не имею, почему это не удалось.

  2. Прежде чем вернуться к представлению, всегда инициализируйте все объекты, которые должны отображаться ввид .

Вы можете использовать Hibernate.initialize () для принудительной инициализации Company.personList:

class Facade() {
    @Inject
    Dao dao;

    List<Company> companies;

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

Или использовать fetch join дляизвлекает personList вместе с Company.It приведет к тому, что возвращенный объект Companies будет иметь полностью инициализированный personList.

@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>();
}

Затем извлекает компанию, используя именованный запрос "Company.ALL.WithPerson"

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...