アプリケーション内の問題をデバッグおよび診断するのが困難です。
で作業を実行するために JPA イベントリスナーが接続されていPOST_COMMIT_INSERT
ます。実行される作業もトランザクションです。
トランザクション後のトランザクションで発生した作業をキャプチャするテストを書くのに苦労しています。
私の現在のテストは、@PostTransaction
メソッドでアサーションを実行します。ただし、(ログ ステートメントを使用して) データが永続化されていることはわかりますが、postTransaction-transaction の作業は利用できません。
私の@PostTransaction
方法では、まだ早すぎて、別のトランザクションが進行中であるためだと思います。
シナリオを大まかに示すサンプルを次に示します。
を
Foo
作成して保存したら、 を作成して保存しBar
ます。
// Step 1. The factory that responds to creation of the Foo, and build a bar.
@Component
class BarFactory implements PostInsertEventListener
{
// Note: I've tried various versions of @Transactional on different points
// within this class, and none have worked.
@Autowired
private BarRepository repository;
@Override
public void onPostInsert(PostInsertEvent event)
{
if (event.getEntity() instanceof Foo)
{
createBar();
}
}
@Transactional
public createBar()
{
Bar bar = new Bar();
repository.save(bar);
log.info("Bar was created: " + bar.getId());
}
}
// Step 2: Register the BarFactory
@Component
class LifecycleListenerFactory {
// This is a spring bean, and the listeners are also spring beans
// so we have to use a somewhat long-winded approach to register them
// with the EntityManager
@Autowired
public LifecycleListenerFactory(EntityManager em, BarFactory barFactory)
{
SessionFactory sessionFactory = getSessionFactory(em);
EventListenerRegistry registry = ((SessionFactoryImpl) sessionFactory).getServiceRegistry().getService(EventListenerRegistry.class);
EventListenerGroup<PostInsertEventListener> eventListenerGroup = registry.getEventListenerGroup(EventType.POST_COMMIT_INSERT);
eventListenerGroup.appendListener(barFactory);
}
SessionFactory getSessionFactory(EntityManager entityManager) {
Session session = (Session) entityManager.getDelegate();
SessionFactory sessionFactory = session.getSessionFactory();
return sessionFactory;
}
}
// Step 3: Test.
@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
@TransactionConfiguration(defaultRollback=false)
class MyTest {
@Autowired
private FooRepository fooRepo;
@Autowired
private BarRepository barRepo;
@Test
public void test()
{
fooRepo.save(new Foo());
}
@AfterTransaction
public void assert()
{
assertThat(barRepo.findAll().size(),equalTo(1));
}
}
このシナリオでは、次の出力が表示されます。
INFO: Bar was created: 1
しかし、テストは失敗します。
私が間違ったトランザクションの後に実行しているという私の仮定は正しい@AfterTransaction
ですか、それともここで何か問題がありますか?
もしそうなら、どうすればこれをテストできますか?
@Transaction
で境界を移動しようとしましBarFactory
たが、効果はありませんでした。