QA@IT

JPQLでhibernateを使用した際にLazyInitializationExceptionがでる

5950 PV

前提
エラー内容

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: entity.Order.orderLine, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214)
    at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:155)
    at org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:278)
    at javax.faces.model.ListDataModel.isRowAvailable(ListDataModel.java:109)
    at javax.faces.model.ListDataModel.setRowIndex(ListDataModel.java:184)

src
Order.class

@NamedQueries ({
    @NamedQuery(name=Order.Order_History,   query="select c from Order c join c.custom d where d.id=:customId")
})
@Entity
@Proxy(lazy=false)
@Table(name="TEST_ORDER")
public class Order implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long            id; 
    @OneToOne
    private Custom              custom;
    private String          form_name;
    @OneToMany(mappedBy="order",cascade={CascadeType.ALL})
    private List<OrderLine> orderLine;
//以下略

OrderLine.class

@Entity
@Proxy(lazy=false)
@Table(name="TEST_ORDERLINE")
public class OrderLine implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long    id;
    @OneToOne
    private Product product;
    @ManyToOne
    private Order order;
//以下略

product.class

@Entity
@Proxy(lazy=false)
@Table(name="TEST_PRODUCT")
public class Product implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long   id;
    private String name;
//以下略

Custom.class

@Entity
@Table(name="TEST_CUSTOM")
public class Custom implements Serializable {
    @Id
    private String  customId;
//以下略

実行箇所
OrderManager.class

@Stateless
public class OrderManager {
    @PersistenceContext
    EntityManager   em;
    public  List<Order> getHistory(String id){
                TypedQuery<Order> query = em.createNamedQuery(Order.Order_History, Order.class);
        query.setParameter("customId", id);
        return  query.getResultList();
    }
//以下略

実行内容
OrderManager.classで実行したJPQLのselect c from Order c join c.custom d where d.id=:customId"ですが
query.getResultList()での戻り値のListの最初のOrderを見ると
orderLineがLazyInitializationExceptionというエラーがでます。
Orderに含まれる他のid、form_name、customなどは取れています。

原因が何かわかりましたら、教えてください。
宜しくお願いします。

回答

あまり自信ないんですけど、orderLine(コレクション)はLAZYフェッチになっているので、Order取得と同時には取得されていないと思います。Orderと一緒にorderLineをまとめて取得したいなら、

    @OneToMany(mappedBy="order",cascade={CascadeType.ALL})

を下のようにEAGERフェッチに変えてはどうでしょうか。

    @OneToMany(fetch = FetchType.EAGER, mappedBy="order",cascade={CascadeType.ALL})
編集 履歴 (1)
  • ありがとうございます!
    EAGERフェッチで動作しました。
    -
ウォッチ

この質問への回答やコメントをメールでお知らせします。