两个线程可以共享相同的JPA事务吗?

时间:2015-08-04 18:27:55

标签: java spring jpa spring-data openjpa

我正在JUnit为消息驱动的Pojo(MDP)编写集成测试:

@JmsListener(destination = "jms/Queue", containerFactory = "cf")
public void processMessage(TextMessage message) throws JMSException {
    repo.save(new Entity("ID"));
}

其中repospring-data存储库

我的单元测试:

@Test
public void test() {
    //sendMsg
    sendJMSMessage();
    //verify DB state
    Entity e = repo.findOne("ID");
    assertThat(e, is(notNullValue()) );
}

现在,问题是processMessage()方法在与test()方法不同的线程中执行,因此我发现我需要以某种方式等待processMessage()方法在验证DB的状态之前完成。我能找到的最佳解决方案是基于CountDownLatch。所以现在方法看起来像这样:

@JmsListener(destination = "jms/Queue", containerFactory = "cf")
public void processMessage(TextMessage message) throws JMSException {
    repo.save(new Entity("ID"));
    latch.countDown();
}

和测试

@Test
public void test() {
    //set the countdownlatch
    CountDownLatch latch = new CountDownLatch(1);
    JMSProcessor.setLatch(latch);
    //sendMsg
    sendJMSMessage();
     try {
        countDownLatch.await();
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    //verify DB state
    Entity e = repo.findOne("ID");
    assertThat(e, is(notNullValue()) );
}

所以我为自己感到骄傲,然后我进行了测试而失败了。 repo.findOne("ID")返回null。在第一个反应中,我在该行设置了一个断点并继续进行调试。在调试会话期间,repo.findOne("ID")实际返回了@JMSListener侦听器方法插入的实体。

在我的头脑中搔了一会儿之后的当前理论:由于spring-data存储库是在两个不同的线程中访问的,因此它获得了两个不同的EntityManager实例,因此它们是两个线程处于不同的交易中。尽管使用CountDownLatch进行了某种同步,但当JUnit @JMSListener带注释的方法启动新的时,绑定到执行@Test带注释的方法的线程的事务尚未提交事务并尝试检索实体。

所以我的问题是:

  1. 一个线程是否有办法等待另一个线程的提交。
  2. 两个线程可以在这样的同步上下文中共享一个事务(即,两个线程不会同时访问EntityManager
  3. 我的测试方法是废话还是有更好的方法吗

0 个答案:

没有答案