2017-01-17 2 views
0

私のアプリケーションでJPAにこの問題があります。私はすべてが怠惰にフェッチされるように設定されている他のエンティティと1対1 /多くのエッチ関係を持つ親エンティティアーティストを持っています。私は結合クエリを使用してこれらのエンティティを取得します。これはすべて正常に動作するようですが、時々私はLazyInitializationExceptionを取得します。私はステートレスEJBをバックエンドにJPA、Web層にSpring MVCを使用しています。ここで方法は次のとおりです。JPAでフェッチを結合するとLazyInitializationExceptionが発生することがあります

public Artist getArtistWithChildren(long id, boolean isFetchReviews, boolean isFetchRequests, boolean isFetchGigs, boolean isFetchVenues) { 
    StringBuilder sql = new StringBuilder(); 
    sql.append("select a from Artist a join fetch a.members mrs"); 
    if(isFetchReviews) { 
     sql.append(" left join a.reviews rvs"); 
    } if(isFetchRequests) { 
     sql.append(" left join a.requests rqs"); 
    } if(isFetchGigs) { 
     sql.append(" left join a.gigs gs"); 
    } if(isFetchVenues) { 
     sql.append(" left join a.venues vs"); 
    } 

    sql.append(" where a.id=:id"); 

    TypedQuery<Artist> query = em.createQuery(sql.toString(), Artist.class); 
    query.setParameter("id", id); 
    query.setMaxResults(1); 
    List<Artist> resultList = query.getResultList(); 
    return resultList.get(0); 
} 

そしてここでは、エンティティクラスのアーティストが

@Entity 
@Table(name="ARTIST") 
public class Artist extends DescribingEntity { 

private static final long serialVersionUID = -7264327449601568983L; 

@ManyToMany(mappedBy="artists", targetEntity=Member.class, fetch=FetchType.LAZY, cascade={MERGE, REFRESH}) 
private List<Member> members; 

@OneToMany(mappedBy="artist", targetEntity=VenueReview.class, fetch=FetchType.LAZY, cascade={MERGE, REFRESH, REMOVE}) 
private List<VenueReview> reviews; 

@OneToMany(mappedBy="artist", targetEntity=Gig.class, fetch=FetchType.LAZY, cascade={MERGE, REFRESH, REMOVE}) 
private List<Gig> gigs; 

@OneToMany(mappedBy="artist", targetEntity=GigRequest.class, fetch=FetchType.LAZY, cascade={MERGE, REFRESH, REMOVE}) 
private List<GigRequest> requests; 

@ManyToMany(cascade={MERGE, REFRESH}, fetch=FetchType.LAZY) 
@JoinTable(name="VENUE_ARTIST_REL", 
    [email protected](name="ARTIST_ID", referencedColumnName="ARTIST_ID"), 
    [email protected](name="VENUE_ID", referencedColumnName="VENUE_ID")) 
private List<Venue> venues; 

getters and setters... 

である私はそれがエラーを返していない方法をステップ実行していて、私はその後、何が悪かったのかを調べるためにデバッグモードに入ると、例外はスローされません。コレクションがあまりに早く返され、DBからのすべてのデータが正しく設定される時間がないことがありますか? JPAについては初心者ですので、間違ったことを教えてください。ここに例があります。結果を取得する必要はありませんので、ここでは左結合を使用していますが、インスタンス化されたコレクションが必要です。

Arquillianを使用して同じことをテストしましたが、エラーはありません。シナリオが同じ他のエンティティに対しても同様の方法があります。単に実行すると、ステップスルーデバッグ中にエラーが発生します。

子コレクションでHibernate.initialize(Object o)を使用するとうまくいきますが、私が間違っている場合は正しい子供になるようにDBのクエリを作成する必要があるため、私の知る限りそれはできません。

私はあなたのコレクションの遅延ロードだと囲むセッションを持ってして、そのコレクションにアクセスしようとすると、LazyInitializationExceptionが発生し、スタックトレース一般に

Stack Trace

答えて

1

にペーストビンのリンクを追加しましたあなたがレイジーコレクションにアクセスしようとしているコンテキスト(本質的なメソッド)。あなたはあなたの問題ここ

+0

私が追加スタックトレースをリンクとして使用します。 – Johan

+1

セッションなしではなく、トランザクションなし。例えば。デタッチされたエンティティ –

+0

私の悪い、セッションなしのはい。私を修正してくれてありがとう。 – Shriram

1

への正確な解像度を得るためにあなたのエラーのスタックトレースを投稿することができた場合には、はるかに参考になる原因は説明している:

問題

共通の課題典型的な(ウェブ)アプリケーションでは、アクションの主ロジックが完了した後で、Hibernate Sessionがすでに閉じられており、データベーストランザクションが終了した後でビューのレンダリングが行われます。 JSP内のセッション(または他のビューレンダリング機構)にロードされたデタッチオブジェクトにアクセスすると、アンロードされたコレクションまたは初期化されていないプロキシがヒットする可能性があります。あなたが得る例外は次のとおりです:LazyInitializationException:セッションが閉じられている(または非常によく似たメッセージです)。もちろん、これはあなたがすでにあなたの作業単位を終了した後に、期待されることです。

解決策は、オープンセッションビューパターンです。スプリングベースのアプリケーションでは、org.springframework.orm.hibernate5.support.OpenSessionInViewInterceptorまたはorg.springframework.orm.hibernate5.support.OpenSessionInViewFilterを使用できますが、どちらのプロジェクトでも両方を実際に使用することはできません。

しかし、いくつかのreasionのために、それはアンチパターンとして扱われます。

**参考:**

Open Session in View

関連する問題