2

編集- ライブラリhttps://github.com/FasterXML/jackson-module-hibernateを使用して、jackson/hibernate に関する特定の問題を解決しました。解決策は私がここで探したものではありませんでしたが、私の状況でも同様に有効です。

元の質問:

org.hibernate.LazyInitializationException最近、 Hibernate/Spring/Jackson を使用しているときに悪名高いものに遭遇しました。私にとっての問題は、ジャクソンがシリアル化してオブジェクトを作成しようとし、遅延フェッチされた値である属性を見つけて、それにアクセスするのに疲れたときに発生します。これに関する多くの質問、投稿、および議論を読みましたが、提案された解決策は常に2つの選択肢の変形のようです

  • トランザクションが終了する前に遅延属性がロードされていることを確認してください。
  • この属性を無視するように jackson を構成します。

私のサービスが初期化されていないいくつかの属性を持つHibernateオブジェクトを返したときに、その方法でオブジェクトを表示したいという事実があるため、別の解決策があるのではないかと思います。特定の目的のためにjacksonを構成することは、プレゼンテーション層がデータベース層の複雑な知識を必要とする戦略のようであり、それは悪い解決策のようです.

フレームワークを最初に見てから、Hibernate エンティティがトランザクションの外部でアクセスされるたびに、Hibernate がオブジェクトを気にせず、通常の POJO のように動作するようにしたいと考えています。本質的に:

  1. 取引を開始する
  2. Hibernate 管理対象オブジェクトに対して CRUD 操作を実行します。
  3. トランザクションを終了し、場合によっては、基になるデータベースにイベントが伝播することなく、読み取り/変更に使用できるフェッチ/変更されたオブジェクトを返します。

望ましい動作の例:

//Start transaction
MyEntity entity = entityManager.find(primaryKey, MyEntity.class);
entity.getLazyLoadedFooList(); //Load the list from database
//End transaction
entity.getLazyLoadedBarList(); //Return null instead of throw LazyInitializationException

基本的な考え方は、アプリケーションにはプレゼンテーション、サービス、および DAO 層があるということです。DAO レイヤーは、データベースに対する CRUD 操作に関係しています。サービス層は、DAO メソッドをトランザクションでラップし、要求されたデータを表す Java オブジェクトを返します。これらのオブジェクトは、プレゼンテーション レイヤーで使用できます。プレゼンテーション レイヤーは、オブジェクトをそのまま目的の形式 (この場合は JSON) に変換します

これに関する2つの質問:

  • 私が説明したように、または同様の方法でそれを行うことはできますか?
  • それは良い/悪い考えですか?
4

3 に答える 3

0

エンティティを取得したらdetach、休止状態のセッションから取得できます。

LazyInitializationExceptionその後は取得しません(ただし、遅延フィールドは null になります)。

あなたの例に従ってください:

   //Start transaction
   MyEntity entity = entityManager.find(primaryKey, MyEntity.class);
   entity.getLazyLoadedFooList(); //Load the list from database
   //End transaction
    entityManager.clear(); // detaches the enitities
    entity.getLazyLoadedBarList(); //Return null instead of throw LazyInitializationException
于 2013-05-27T09:30:49.823 に答える
0

エンティティを休止状態のエンティティから通常の POJO に変更するには、次のコードを試してください。コードには存在するが休止状態のプロキシには存在しないクラスの注釈を読み取る目的で使用します。

import org.hibernate.proxy.HibernateProxy;

import org.hibernate.Hibernate;
import org.hibernate.proxy.HibernateProxy;

public class StripHibernateProxy {

    // This function takes the hibernate entity and forces it to be a real java
    // object instead

@SuppressWarnings("unchecked")
public static <T> T initializeAndUnproxy(T entity) {

            if (entity == null) {
                    throw new NullPointerException("Entity passed for initialization is null");
            }

            Hibernate.initialize(entity);

            if (entity instanceof HibernateProxy) {
                    entity = (T) ((HibernateProxy) entity).getHibernateLazyInitializer().getImplementation();
            }

            return entity;
    }
}
于 2013-05-28T20:10:59.397 に答える
0

この質問に対する本当の答えはありますか?私は何年もそれに夢中になっていて、Gilead や Jackson-hibernate モジュールのようないくつかのハック ソリューションしか見つけられませんでした。hibernate が POJO コントラクトを尊重し、例外をスローしないように設定されていれば、それは素晴らしいことです。読み取り専用のものに似た何らかのヒントかもしれません。

List<Customer> list = em.createQuery(q, Customer.class)
            .setParameter("lastName", "Vest")
            .setHint("org.hibernate.readOnly", true)
            .getResultList();
于 2017-01-10T08:55:12.900 に答える