web-dev-qa-db-ja.com

アクティブな春のトランザクション内でデータベースにデータをフラッシュする方法は?

Springテストフレームワークを使用して、Hibernateセッションのsave()メソッドをテストしたいと思います。 @Testメソッドは次のとおりです。

@Test
@Transactional
public void testSave() {
    User expected = createUser();
    getGenericDao().currentSession().save(expected);
    User actual = getUser(generatedId);
    assertUsersEqual(expected,actual);
}

ユーザーをデータベースにフラッシュしたい。このメソッドの後でユーザーをデータベースに入れたい

getGenericDao().currentSession().save(expected);

次に、Springデータフレームワークを使用してデータベースに移動し、この保存されたユーザーを次の行でフェッチします。

User actual = getUser(generatedId);

私は次のような休止状態のフラッシュ方法を使用しようとしました:

currentSession().setFlushMode(MANUAL);
//do saving here
currentSession().flush();

ユーザーをデータベースにフラッシュしません!ただし、@ Transactionalスプリングアノテーションを使用せず、ユーザーをプログラマティックスプリングトランザクションに保存すると、希望どおりの結果が得られます。残念なことに、春に@Transactionalがないため、dbに保存されたユーザーはロールバックされません。したがって、私のテストメソッドは、後続のテストメソッドのdbと動作を変更します。

したがって、ユーザーをテストメソッド内で(最後ではなく)dbにフラッシュし、テストメソッドの最後ですべての変更をdbにロールバックする必要があります。

[〜#〜] update [〜#〜]次のようにメソッドを準備するための提案:

@Transactional
public void doSave(User user){
    getGenericDao().currentSession().save(user);
}

そして、testSave内でdoSaveを呼び出しても何も起こりません。このメソッドを実行した後も、dbにユーザーがいません。ブレークポイントを設定し、コマンドラインからデータベースをチェックします。

[〜#〜] update [〜#〜]返信ありがとうございます。問題は、メソッドflush()がユーザーをデータベースに入れないことです。Isolation.READ_UNCOMMITTEDを試してみましたが、ユーザーがデータベースに入れられません。 @TestメソッドでSpringトランザクションをオフにして、プログラムによるトランザクションで保存を行った場合にのみ、希望どおりの結果を得ることができます。ただし、@ Testメソッドはロールバックされず、保存されたユーザーは後続の@Testメソッドに残されます。ここでは、ユーザーを保存する@Testメソッドは、ロールバックされないため、ユーザーを削除する@Testメソッドほど危険ではありません。そのため、@ Testメソッドのトランザクションサポートが必要です。これにより、ユーザー(または削除)をdbに入れることができなくなります。実際には、@ Testメソッドが終了し、@ Testメソッドのトランザクションがコミットされた後にのみ、ユーザーがデータベースに配置(または削除)されます。 ユーザーを@Testメソッドの途中でdbに保存し、@ Testメソッドの最後でロールバックしたい

ありがとうございました!

17

最後に、私は次の解決策にこだわりました:

まず、私の_@Test_メソッドが春の_@Transactional_サポート内で実行されていません。それがどれほど危険であるかを知るために この記事 を参照してください。次に、_@Repository_メソッド内で_@Test_ Beanを使用する代わりに、_@Service_アノテーションを使用する_@Transactional_ Beanを自動配線します。奇跡は、このような_@Test_メソッドです

_@Test
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void testSave() {
    Answer created = createAnswer();
    Long generatedId = answerService.save(created);
//at this moment answer is already in db
    Answer actual=getAnswerById(generatedId);
... }
_

answerオブジェクトをデータベースに入れ(answerService.save(created);の直後)、メソッドgetAnswerByIdがDBに移動して抽出し、保存が正しいかどうかを確認します。
_@Test_メソッドでデータベースに加えられた変更を削除するには、_JdbcTestUtils.executeSqlScript_でデータベースを再作成します

11
  1. ご覧ください こちら _@Transactional_テストに関する警告付き( 春の落とし穴:トランザクションテストは有害と見なされます )。 _@org.springframework.test.context.jdbc.Sql_を使用して、サービステストでDBを再設定し、_@Transactional_をコントローラーに使用しました。
  2. 無効なデータを含むコントローラー更新テストのConstraintViolationExceptionは、トランザクションがコミットされたときにのみスローされました。だから私は3つのオプションを見つけました:
    • 2.1 _@Commit_または@Transactional(propagation = Propagation.NEVER)を使用してテストに注釈を付けます。 DBの変更に注意してください。
    • 2.2 TestTransactionを使用する

コード:

_     TestTransaction.flagForCommit();
     TestTransaction.end();
_
  • 2.3 TransactionTemplateを使用する

コード:

_    @Autowired
    private PlatformTransactionManager platformTransactionManager;

    @Test(expected = Exception.class)
    public void testUpdate() throws Exception {
        TransactionTemplate transactionTemplate = new TransactionTemplate(platformTransactionManager);
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        String json = ...
        transactionTemplate.execute(ts -> {
            try {
                mockMvc.perform(put(REST_URL + USER_ID)
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(json))
                    .andExpect(status().isOk());
                ...
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        });
_
4
Grigory Kislin

flushが機能しない場合は、データベースの分離レベルに大きく依存します。

Isolationは、データベースのACIDプロパティの1つであり、1つの操作によって加えられた変更が他の同時操作に対してどのように/いつ可視になるかを定義します。

分離レベルはRead CommittedまたはRepeatable Readに設定されていると思います。

1
JSS

また、インポートされたパッケージにも注意する必要があります。

import javax.transaction.Transactional;

の代わりに

import org.springframework.transaction.annotation.Transactional;

1
Meinew