JPA错误:交易当前处于活动状态

时间:2011-10-10 07:16:54

标签: java spring jpa

当我单独运行单元测试时,它们工作正常,即。 (省略断言)

@Test
public void testSave()
 {
EntityManagerHelper emh = new EntityManagerHelper();
LevelDAO dao = new LevelDAO();
Level l = new Level();
l.setName("aname");
emh.beginTransaction();
dao.save(l);
emh.commit();
}

然后在下面运行此单独测试没问题

@Test
public void testUpdate()
 {
EntityManagerHelper emh = new EntityManagerHelper();
LevelDAO dao = new LevelDAO();
Level l = new Level();
l.setName("bname");
l.setLevelid(1);
emh.beginTransaction();
dao.update(l);
emh.commit();
}

当它们按顺序同时运行时,我收到该错误 - 交易当前处于活动状态。是否有办法允许每个单元测试仅在上一个工作的事务未激活后运行?我应该看看Spring吗?

更新

EntityManagerHelper可以访问持久化上下文,如此

emf = Persistence.createEntityManagerFactory("bw_beta");        
threadLocal = new ThreadLocal<EntityManager>();

看起来像问题

所以一个hacky解决方法是使用local local ie。

    EntityManagerFactory factory = Persistence.createEntityManagerFactory("bw_beta");
    EntityManager entityManager = factory.createEntityManager();
    entityManager.getTransaction().begin();
    dao.save(l);
    entityManager.persist(l);
    entityManager.getTransaction().commit();

非常确定有更好的方法 - 也许使用Spring?

2 个答案:

答案 0 :(得分:1)

  • 非常确定有更好的方法 - 也许使用Spring?

是的,Spring会清理它并让您控制您在交易中运行的内容,而不会污染实际测试。

使用Spring,您的测试看起来像这样:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:META-INF/conf/spring/application-context.xml",
                        "classpath:META-INF/conf/spring/test-datasource-spring-config.xml" })
@TransactionConfiguration(transactionManager="txMgr", defaultRollback=false)
public class LevelDaoTest {

    @Resource( name="levelDao" )
    LevelDao levelDao;

    @Test
    public void shouldSaveNewLevels() {

        Level l = new Level();
        l.setName("aname");
        levelDao.save(l);
        // assert
    }

    @Test
    public void shouldUpdateExistingLevels() {

        Level l = new Level(); // or I would assume, you'd read this level back from DB, or set a proper ID, so the DAO will know to update it.. But that is besides the point
        l.setName("bname");
        levelDao.update(l);
        // assert
    }
}

查看Testing => Transaction Management下的Spring文档以获取更多详细信息。

P.S。从您的示例:

dao.save(l);
entityManager.persist(l);

看起来很奇怪,因为通常你会将entityManager封装在一个DAO中,所以你需要做的就是dao.save(l)

答案 1 :(得分:0)

对于任何可能遇到此问题的人来说,我是如何解决它的。我正在进行多次保存,并且我一直收到此错误。您不希望在不检查它是否处于活动状态的情况下开始多个事务。

if(!entityManager.getTransaction().isActive())
    entityManager.getTransaction().begin();
dao.save(l);
entityManager.persist(l);
entityManager.getTransaction().commit();

我实施了一种Singleton方法来处理它。