1

私は(本番環境で)いくつかのコードを持っています:

  • 1 つのスレッドで、db からのデータでキャッシュを準備します
  • 別のスレッドで、キャッシュからデータを取得し、そのプロパティの反復処理を開始します。

これはLazyInitializationException.

問題を解決する方法はわかっていますが、これについてテストしたいと思います。ただし、テストの正しい部分で例外を再作成する方法がわかりません。

DB にいくつかのテスト データを準備する必要があるため、テストには@Transactional. そうしないと、セットアップが失敗し、... あなたはそれを推測しました... LazyInitializationException.

これが私の現在のテストです:

@Transactional
public class UpdateCachedMarketPricingActionTest extends AbstractIntegrationTest {

    @Autowired
    private UpdateCachedMarketPricingAction action;

    @Autowired
    private PopulateMarketCachesTask populateMarketCachesTask;

    @Test @SneakyThrows
    public void updatesCachedValues()
    {

        // Populate the cache from a different thread, as this is how it happens in real life
        Thread updater = new Thread(new Runnable() {
            @Override
            public void run() {
                populateMarketCachesTask.populateCaches();
            }
        });
        updater.start();
        updater.join();

             updateMessage = {...} //ommitted 

        action.processInstrumentUpdate(updateMessage);
    }

そのため、別のスレッドでキャッシュをプライミングして、現在の@Transactionスコープの外に取得しようとしています。さらに、キャッシュ プライマー内でも呼び出しentityManager.detatch(entity)て、キャッシュ内に存在するエンティティがコレクションを遅延ロードできないようにします。

ただし、テストはパスします...例外はスローされません。

次にエンティティのコレクションを反復しようとすると、エンティティがスローされる状態に強制するにはどうすればよいLazyInitializationExceptionですか?

4

1 に答える 1

0

各操作のトランザクションが互いに独立してコミットされていることを確認する必要があります。テスト メソッドまたはテスト クラスに注釈を付けると@Tranactional現在のテスト トランザクションは開いたままになり、テスト全体の実行後にロールバックされます。

したがって、1 つのオプションは、次のようなことを行うことです。

@Autowired
private PlatformTransactionManager transactionManager;


@Test
public void example() {
    new TransactionTemplate(transactionManager).execute(new TransactionCallbackWithoutResult() {

        @Override
        protected void doInTransactionWithoutResult(TransactionStatus status) {
            // add your code here...
        }
    });
}

独自のコールバックで最初の操作を呼び出してから、別のコールバックで 2 番目の操作を呼び出すことができます。その後、コールバック後に Hibernate または JPA エンティティにアクセスすると、エンティティは現在の作業単位 ( HibernateSessionなど) に関連付けられなくなります。したがって、その時点で遅延コレクションまたはフィールドにアクセスすると、LazyInitializationException.

よろしく、

サム

ps この手法では、変更がデータベースにコミットされたままになることに注意してください。したがって、その変更された状態をクリーンアップする必要がある場合は、メソッドで手動で行うことを検討して@AfterTransactionください。

于 2013-06-15T15:30:52.923 に答える