4

この質問を許してください、しかし私は今のところ私の研究を通して解決策を見つけることができません。(少なくとも私を助けたものは何もありません)

私の状況:

  • vaadinWebサービスにHibernateを使用しています
  • Webサービスはアップロードされたドキュメントを取得し、MySQLデータベースの休止状態を介して変更せずに配置します
  • バックグラウンドのコンピューティングサービス(後で別のサーバー上にある可能性のある別のプロセス)は、アップロードされたドキュメントに対して計算タスクを実行し、結果をデータベースに再度追加します
  • Webサービスはデータベース内の分析結果を認識し、ユーザーに表示します

私の問題:

  • 私の問題はレベル1の休止状態のキャッシュです
  • 計算サービスが開始された後、指定された検索クエリを実行したときにキャッシュに表示されないため、後で更新されたドキュメントについては何も計算しません。
  • 私のWebサービスは、計算サーバーに加えられた変更を上書きします。これは、Webサービスについても何も知らないためです。

Hibernateレベル1キャッシュがこの動作の原因であることを知っています(ちなみに、lvl 2キャッシュはアクティブではありません)。

私がこれまでに試したこと

  • 私はたくさん読んで、いくつかのことを試しました。たとえば、さまざまな場所でsession.clear()を呼び出します。これはしばしば「セッションが閉じられた」という例外を私に与え、私を助けませんでした(これが彼らの問題を助けたと言っている人々について読んだのですが)

  • 最後にセッションが常に閉じられるようにしようとしましたが、これで問題が解決しなかっただけでなく、transaction.commit()を使用した後、セッションを手動で閉じる必要がないことを読みました(Iこれはリクエストパターンごとのセッションの標準であると聞きました)

  • コンピューティングサービスがデータベースを検索する必要があるたびに、セッションファクトリを閉じて再度開いてみました。これは部分的に機能し、Webサービスでもこれを実行するとおそらく完全に機能しますが、これは私にとってあまり良い解決策ではないようです(メモリを消費しますが、そうではありませんか?)

  • 追加してみました

<property name = "hibernate.connection.isolation"> 2 </ property>

私のhibernate.cfg.xmlに追加しましたが、これも部分的にしか機能しませんでした。これを使用して、私の計算サービスは計算タスクを実行しましたが、新しいデータがWebサービスを介してアップロードされるたびに、彼の変更は再び上書きされました。そのため、新しいアップロードが検出されましたが、新しいアップロードが到着すると、すでに分析されたすべてのドキュメントが再度分析されます。

セッションの管理方法が間違っているかどうかを常に考えていました。私のクラスDAOには2つのメソッドがあり、トランザクションのすべての開始時とすべての終了時に呼び出されます。

public abstract class DAO {

/**
 * Returns the current hibernate session. Also takes care that there's
 * always an open hibernate transaction when needed.
 * 
 * @return Current hibernate session
 */
public static Session getSession() {
    Session currentSession = HibernateUtil.getSessionFactory()
            .getCurrentSession();
    if (!currentSession.getTransaction().isActive()) {
        currentSession.beginTransaction();
    }

    return currentSession;
}

/**
 * Closes the current hibernate session, if there is one.
 */
public static void closeSession() {
    Session sess = HibernateUtil.getSessionFactory().getCurrentSession();
    if (sess.getTransaction().isActive()) {
        sess.getTransaction().commit();
    }
    ThreadLocalSessionContext.unbind(HibernateUtil.getSessionFactory());
}

}

Hibernateを使用したオプティミスティックロックについても読んだことがありますが、これで問題が解決するかどうかはわかりません。オプティミスティックロックは、キャッシュオブジェクトがデータベース内にない場合にのみ例外をスローすることを読みました。しかし、それはキャッシュをロード(更新)しますか?

休止状態でこの問題をどのように処理しましたか?私にできることや、DAOクラスで何か間違ったことをしたことについて何か提案はありますか?コード例にも満足しています。繰り返しますが、すべてのプロセスが、他のプロセスによってデータベースに加えられた変更について認識している必要があります。(可能であれば、最初のキャッシュを無効にすることもできますが、これは不可能なので)

すべての回答に感謝し、あなたが私と共有していると思いました

4

2 に答える 2

5

アタッチされたオブジェクトインスタンスはSession、Hibernate内にのみ存在します。トランザクションとセッションを正しく終了すると、レベル1のキャッシュが削除されます。セッション管理にはどのようなパターンを使用しますか?セッションインビュー?

あなたの問題は私にはセッション終了の問題のように思われるので、私はこれを求めています。

編集:

コードにSession.close()または少なくともSession.disconnect()が表示されません。私の知る限り、unbind()では自動ではありません。

于 2012-07-02T23:16:54.140 に答える
1

問題を修正しました。

最初の部分は、GergelySzilagyiと彼の答えの大きな助けを借りて修正することができます:

アタッチされたオブジェクトインスタンスは、Hibernateのセッション内でのみ存在します。トランザクションとセッションを正しく終了すると、レベル1のキャッシュが削除されます。セッション管理にはどのようなパターンを使用しますか?セッションインビュー?

あなたの問題は私にはセッション終了の問題のように思われるので、私はこれを求めています。

編集:

コードにSession.close()または少なくともSession.disconnect()が表示されません。私の知る限り、unbind()では自動ではありません。

(この素晴らしい投稿に感謝します。いくつかの回答を正解としてマークできれば、あなたの回答もマークします!)

彼の答えは私のセッション管理について考えさせてくれました、そして私の問題のいくつかはこれを通して修正されました。

私の問題の2番目の部分であり、私の主な質問でも非常に重要なのは、どのようにして第1レベルのキャッシュを更新/整合性を保つことができるかということでした。多くの調査の結果、休止状態のSessionクラスには、データベースからオブジェクトを直接ロードできるメソッドが含まれていることがわかりました。

更新するエンティティオブジェクトエンティティが与えられた場合、次のように動作します。

//Call session.evict if this object is currently in the session, otherwise not necessary
//It deletes the object from the session cache (If you don't call this method although this object is currenlty in the session an exception will be thrown
session.evict(entity);
//session.get acccesses the database directly and returns you the actual saved entity
Ent1 updatedEntitEnty = (Ent1) session.get(Ent1.class, entity.getPrimaryUniqueID());

これで、受信した更新されたエンティティでの作業を続行できます。

session.get(...)はデータベースに直接アクセスし、キャッシュを無視するため、ここで最も重要なメソッドです。指定されたbackオブジェクトは、データベースに保存されている最新のものです。

注意:session.load(...)メソッドもありますが、この場合は役に立ちません。load(..)はキャッシュにアクセスし、そこからオブジェクトを取得しますが、get(..)は正しく実行します。

したがって、データベースからオブジェクトを取得する場合は、session.load(...)を使用しないでください。

この回答がいつか他の人の役に立つことを願っています。質問があれば私に連絡してください。

于 2012-07-04T13:12:01.710 に答える