java JPA 错误:事务当前处于活动状态
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7709583/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JPA Error : Transaction is currently active
提问by MikeW
When I run my unit tests in isolation they work fine ie. (omitted the asserts)
当我单独运行我的单元测试时,它们工作正常,即。(省略断言)
@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();
}
then running this individual test below no problem
然后在下面运行这个单独的测试没问题
@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();
}
When they run at same time in sequence I recieve that error - Transaction is currently active. Is there a way to allow each unit test to run only after a transaction from previous piece of work is not active? Should I be looking at Spring instead?
当它们按顺序同时运行时,我收到该错误 -事务当前处于活动状态。有没有办法允许每个单元测试仅在上一个工作的事务不活动后运行?我应该看 Spring 吗?
Update
更新
The EntityManagerHelper gains access to the persistence context like so
EntityManagerHelper 像这样获得对持久化上下文的访问权限
emf = Persistence.createEntityManagerFactory("bw_beta");
threadLocal = new ThreadLocal<EntityManager>();
which looks like the problem
这看起来像问题
So a hacky workaround was to use define locally ie.
所以一个hacky的解决方法是在本地使用定义,即。
EntityManagerFactory factory = Persistence.createEntityManagerFactory("bw_beta");
EntityManager entityManager = factory.createEntityManager();
entityManager.getTransaction().begin();
dao.save(l);
entityManager.persist(l);
entityManager.getTransaction().commit();
Pretty sure there's a better way - maybe using Spring?
很确定有更好的方法 - 也许使用 Spring?
采纳答案by tolitius
- Pretty sure there's a better way - maybe using Spring?
- 很确定有更好的方法 - 也许使用 Spring?
Yes, Spring cleans it up a lot and gives you control on what you'd like to run within a transaction without polluting the actual test.
是的,Spring 对其进行了大量清理,并让您可以控制在事务中运行的内容,而不会污染实际测试。
With Spring, your tests would look something like this:
使用 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
}
}
Take a look at Spring Documentation under Testing => Transaction Managementto get more details.
查看测试 => 事务管理下的 Spring 文档以获取更多详细信息。
P.S. From your example:
PS从你的例子:
dao.save(l);
entityManager.persist(l);
Looks really strange, as usually you would encapsulate entityManager
within a DAO, so all you'd need to do is dao.save(l)
看起来真的很奇怪,因为通常你会封装entityManager
在一个 DAO 中,所以你需要做的就是dao.save(l)
回答by FCoffee
For anyone that may be having this issue here is how I resolved it. I was doing multiple saves and I kept getting this error. You do not want to begin multiple transactions without checking if it is active.
对于可能在这里遇到此问题的任何人,我都是如何解决它的。我进行了多次保存,但不断收到此错误。您不想在不检查它是否处于活动状态的情况下开始多个事务。
if(!entityManager.getTransaction().isActive())
entityManager.getTransaction().begin();
dao.save(l);
entityManager.persist(l);
entityManager.getTransaction().commit();
I implemented a Singleton approach to handle it.
我实现了一个单例方法来处理它。