しばらく問題なく使用している Hibernate エンティティがあります。状態変数を使用して (問題なく動作する) メソッドを保護するためのコードをいくつか追加し、別のトランザクションで状態を設定およびクリアしました。これにより、同じクラスのローカル プライベート変数にアクセスするメソッドで問題が発生しました。以前はこれらの変数に直接アクセスできましたが、現在は get メソッドを使用して変数を取得する必要があります。そうしないと、それらの変数のアンロードされた値を取得します。
以下は、機能した最初のコードです
- 取引を開く
- Hibernate を介してオブジェクトをフェッチする
- メソッドを呼び出す (doTheWork())
- プライベート変数を参照する
初期化された値ではなく、変数の保存された値が表示されます (1)
public class Desktop { public static void main() { String tx = createTransaction(); Desktop desktop = getDesktop(tx); desktop.doTheWork(); commitTransaction(tx); } private static Desktop getDesktop(String tx) { return (Desktop)txFactory.getSession(tx).load(Desktop.class, 5L); } Long nextVersion = new Long(1); public Long getNextVersion() { return nextVersion; } public void doTheWork() { Log.info("Value of nextVersion is " + nextVersion); }
}
以下は変更されたコードです
- トランザクションを開いてオブジェクトをフェッチする
- メソッドを呼び出す
- 別のトランザクションで状態変数を設定する
- 別のトランザクションを開き、新しいトランザクションでこのオブジェクトのコピーを取得します
- (本質的に)同じメソッドを呼び出す(doTheWorkImpl())
永続化された変数ではなく、初期化された変数 (1) の値が表示されるようになりました。
パブリック クラス デスクトップ
public static void main() { String tx = createTransaction(); // Hibernate transaction Desktop desktop = getDesktop(tx); // Fetch object using Hibernate desktop.doTheWork(); commitTransaction(tx); }
ロング nextVersion = 新しいロング (1);
public Long getNextVersion() { return nextVersion; } private void doTheWork() { String tx = createTransaction(); setState(State.BUSY); commitTransaction(tx); tx = createTransaction(); Desktop desktop = getDesktop(tx); desktop.doTheWorkImpl(); commitTransaction(tx); tx = createTransaction(); setState(State.NORMAL); commitTransaction(tx); } private void doTheWorkImpl() { Log.info("Value of nextVersion is " + nextVersion); }
}
変数への直接参照を変更して getNextVersion() を呼び出すと、正しい値が表示されます。
Hibernate がプロキシを使用することは理解していますが、以前はこのコードが機能していた理由がわかりません。現在、プロキシのロードを強制する必要があります。基本的に同じように動作する Hibernate オブジェクトが多数ある (Hibernate を介してロードされた後に変数を直接参照する) ため、ここで紹介したパターンを変更するものを理解したいと思います。
ここで、session.load() ではなく session.get() を使用することを提案する回答を見ましたが、上記のコードのように常に load を使用してきました。