1

アプリケーション内の問題をデバッグおよび診断するのが困難です。

で作業を実行するために 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たが、効果はありませんでした。

4

0 に答える 0