LazyInitializationException в @RequestScoped Bean после явного EntityManager.find - PullRequest
3 голосов
/ 06 июня 2011

В настоящее время мы мигрируем с JavaEE5 на JavaEE6 и используем JBoss 6.0.0 и JSF2. Для простоты этот пример построен на основе архетипа Maven: org.jboss.weld.archetypes:jboss-javaee6-webapp:1.0.1.CR2

Я добавил простые ленивые отношения к User:

@NotNull @ManyToMany(fetch=FetchType.LAZY)
private List<Address> addresses;

Этот бин является частью архетипа maven, и я добавил несколько строк к 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
    }}

Как видите, List<Member> извлекается CriteriaQuery, затем Member m1 берется из списка, а Member m2 явно загружается из того же EntityManager em. Теперь интересная часть: m1.getAddresses().size() работает, m2.getAddresses().size() дает

    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

Кто-нибудь может объяснить это или знает, как решить эту проблему? Спасибо, Тор

Ответы [ 3 ]

0 голосов
/ 18 июля 2011

Тор, не могли бы вы еще раз проверить? Я подумал, что это интересно, и попробовал сам, однако я получаю исключение в обоих звонках. Ни один из них не работает. Я мог сделать что-то не так, но я проверял пару раз, и оба метода дают мне это исключение. Вы получаете регистратор для регистрации размера первой коллекции?

0 голосов
/ 17 августа 2011

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

crit.setFetchMode ("address", FetchMode.JOIN);

0 голосов
/ 06 июня 2011

Это нормальное поведение для ленивой загрузки, все ваши ленивые классы являются прокси.и когда вы выбираете класс из прокси, ваш сеанс Hibernate уже закрыт.

Решение состоит в том, чтобы реализовать Open Session in View Filter, который будет поддерживать ваш сеанс Hibernate открытым до тех пор, пока ваш запрос не будет активен.

Подробнее об этом вы можете прочитать в этой статье

http://community.jboss.org/wiki/OpenSessionInView

Если вы используете Spring Framework, то вы уже выполнили эту работу OpenSessionInViewFilter класс.

Надеюсь, это поможет.

...