LazyInitializationException при зареждане на дъщерни обекти с FetchType.LAZY

Получавам LazyInitializationException, когато моят JSF изглед изисква списък с деца за обект. Не използвам Hibernate директно, а JPA. Таблицата CHILD DB има FK на таблицата PARENT. Това е много стандартна връзка.

Ето как изглеждат съответните извадки от кода:

Родител

@Entity
@Table(name="PARENT")
@NamedQueries({@NamedQuery(name = "Parent.getByID", 
            query = "SELECT i FROM Parent i WHERE i.parentID = :parentID")})
public class Parent implements Serializable {

    @Id
    @SequenceGenerator(name="PARENT_SEQ_GEN", sequenceName="DB_SEQ", allocationSize = 1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PARENT_SEQ_GEN")
    @Column(name="PARENT_ID")
    private long parentID;

    /* other stuff */

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", fetch = FetchType.LAZY)
    private List<Child> childList;

    /* other stuff */

    public List<Child> getChildren() {
        return this.childList;
    }

Дете

@Entity
@Table(name="CHILD")
@NamedQueries({@NamedQuery(name = "Child.getByID", 
            query = "SELECT i FROM Child i WHERE i.childID = :childID")})

public class Child implements Serializable {

    @Id
    @SequenceGenerator(name="CHILD_SEQ_GEN", sequenceName="DB_SEQ", allocationSize = 1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="CHILD_SEQ_GEN")
    @Column(name="CHILD_ID")
    private long childID;

    @JoinColumn(name = "PARENT_ID", referencedColumnName = "PARENT_ID", insertable = true, updatable = false)
    @ManyToOne(optional = false)
    private Parent parent;

Преглед

<h:dataTable id="childTbl" value="#{parent.children}" 
        var="child" width="100%"
        styleClass="data" border="1" cellpadding="2"
        cellspacing="0">
    <h:column>
        <f:facet name="header">Child Name</f:facet>
        #{child.name}
    </h:column>
    <h:column>
        <f:facet name="header">DOB</f:facet>
        #{child.dob}
    </h:column>
</h:dataTable>

Ако променя FetchType на EAGER, не получавам изключение, но искам извличането на данни да е мързеливо, т.е. само при поискване. Какво трябва да променя, за да избегна това изключение?

Може да е свързано

В изгледа, който се изобразява успешно, когато FetchType е EAGER, имам формуляр за добавяне на дете за всеки родител и след като бъде добавено дете, се опитвам да използвам f:ajax, за да опресня автоматично списъка с деца:

<h:commandButton value="Add Child" action="#{parentBean.addChild}">
    <f:ajax execute="@form" render="childTbl"/>
</h:commandButton>

Това опресняване обаче е неуспешно, тъй като дъщерната таблица не се актуализира с нов ред, когато добавя дъщерен елемент към AJAX (което правя, за да избегна презареждането на страницата), въпреки че съответната DB транзакция е успешна. Новодобавеното дете се вижда само в таблицата, когато опресня изгледа в браузъра, като презаредя страницата.

Обърнете внимание обаче, че LazyInitializationException се появява, когато за първи път се опитам да заредя страницата с родител и техните деца, когато FetchType е LAZY. Това не е пряко свързано с неуспешното опресняване, което се случва, когато FetchType е EAGER. Но си помислих, че може да има някакъв основен пропуск в моя код, който, когато бъде коригиран, ще позволи както мързелива инициализация, така и опресняване на AJAX изгледа.


person amphibient    schedule 19.05.2015    source източник
comment
опреснявате ли родителския си обект, след като приключите с транзакцията?   -  person guilhebl    schedule 20.05.2015
comment
да, <f:ajax execute="@form" render="childTbl"/> трябва да направи това   -  person amphibient    schedule 20.05.2015
comment
Можете да видите този отговор, същия проблем, но с jsp страница [връзка] [1] [1]: stackoverflow.com/questions/19047835/   -  person Abdou Amari    schedule 20.05.2015
comment
Това е така, защото се опитвате да се обърнете към лениво инициализирана колекция тук в този EL #{parent.children}. Предполагам, че EL се отнася до private List<Child> childList, върнат от getChildren() в обекта Parent. Това няма нищо общо с JSF. Използвайте отделна заявка, за да извлечете списък с деца въз основа на неговия родителски ред в зависимост от функционалните изисквания или структурата/потока на проекта.   -  person Tiny    schedule 20.05.2015


Отговори (1)


Тъй като дефинирате FetchType.LAZY извличане за колона childList; разгледайте разликите между FetchType.LAZY и FetchType.EAGER от ТУК . Ако искате да получите ненулев обект childList, има 2 опции:

  1. Променете FetchType.LAZY на FetchType.EAGER
  2. Когато вашият Child обект постоянно извиква getChildren() в анотирания метод @Transaction.
person dogankadriye    schedule 20.05.2015