2012-02-28 12 views
0

私はソースWebサイトから取得するデータのローカルキャッシュを構築するためにhibernateを使用しようとしています。私はJPAで構成されたオブジェクトを持っており(違いがある場合)、テストアプリケーションでそれらを読み書きすることができます。Hibernateを使用して一般的なオブジェクトを取得する

ここで、コードを汎用の「キャッシュ」クラスに移動して、キャッシュからオブジェクトをリクエストして通常どおりに処理できるようにします。私はデータベースからオブジェクトを読み込んで呼び出し元のクラスに渡すことができますが、オブジェクトのコレクションにアクセスしようとすると恐ろしい初期化例外が発生します。 私はこれを引き起こす原因を知っています。オブジェクトを読み取ったクラスは、データベースからオブジェクトを読み込んだ後、呼び出し元クラスにオブジェクトを返す前にトランザクションをコミットします。

これを回避するにはさまざまな方法を試しましたが、最も簡単なのは、トランザクションを閉じてオブジェクトを返す前に、オブジェクト内のすべてのコレクションにアクセスしてそれらが確実に読み込まれるようにしているようです。

このアプローチの問題は、私がデータベースから取得しているオブジェクトの構造(私にとってはHibernateの利点の一部)を知らないため、ロードする適切なメソッドを呼び出すことができないということですデータ。どのように私はこれを克服するのですか?私は本当に他のアプリケーションで使用される可能性があるので、オブジェクトのeager fetchingをしたくありません。私がそれを避けることができれば、私はhbmファイルを使用したくありません。 Cacheクラスで

Series series = (Series) Cache.getFromCache(id, Series.class) 

この

は、Cacheクラスの呼び出しです

public static Object getFromCache(String key, Class clazz) { 
Object dbObject = HibernateUtil.loadObject(clazz, key); 

    if (dbObject != null) { 
     logger.debug("Cache (Get): Got object (" + clazz.getSimpleName() + ") for " + key); 
     return dbObject; 
    } 
} 

そしてHibernateUtilの処理が行われます。すべての

public static Object loadObject(Class clazz, Serializable key) { 
    Session session = sessionFactory.getCurrentSession(); 
    Object dbObject; 

    try { 
     session.beginTransaction(); 
     dbObject = clazz.cast(session.get(clazz, key)); 
    } finally { 
     session.getTransaction().commit(); 
    } 

    return dbObject; 

答えて

1

まず、あなたは避けることができloadObjectメソッドをパラメータ化することによってキャストされる型:

public static <T> T loadObject(Class<T> clazz, Serializable key) { 
    Session session = sessionFactory.getCurrentSession(); 
    T dbObject; 

    try { 
     session.beginTransaction(); 
     dbObject = clazz.cast(session.get(clazz, key)); 
    } 
    finally { 
     session.getTransaction().commit(); 
    } 

    return dbObject; 
} 

第2の理由:なぜこの方法でトランザクションを開いてコミットしますか?呼び出し元がトランザクションを開いて、キャッシュからロードしたオブジェクトの使用が終了したときにコミットすると、問題が解決されます。

3番目:このメソッドを開いてトランザクションを終了させたい場合は、パラメータとしてInitializer<T>インスタンスを使用させます。この初期化子は、エンティティを返す前に、必要な関連付けをすべて初期化する責任があります。

public static <T> T loadObject(Class<T> clazz, 
           Serializable key, 
           Initializer<T> initializer) { 
    Session session = sessionFactory.getCurrentSession(); 
    T dbObject; 

    try { 
     session.beginTransaction(); 
     dbObject = clazz.cast(session.get(clazz, key)); 
     initializer.initialize(dbObject); 
    } 
    finally { 
     session.getTransaction().commit(); 
    } 

    return dbObject; 
} 
+0

**最初に**大変ありがとうございます。 ** 2番目:**キャッシュコードは既存のプロジェクトに追加されたままにしておきました。一度にすべてをやり直さなくても、プロジェクトを一度にリファクタリングしたいと思います。 ** Third:**私の無知を許しますが、Initializerは何ですか? – Omertron

+0

イニシャライザは作成するインターフェイスで、 'initialize(T)'メソッドを含み、Tエンティティの関連付けをloadObjectメソッドから戻す前に初期化する責任があります。 –

+0

それは ' .getCollection()。size'などを呼び出すユーティリティクラスです。 'initialize'はロードされているクラスに属していますか? – Omertron

関連する問題