2011-10-10 94 views
1

當我單獨運行我的單元測試時,它們可以正常工作。 (省略斷言)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>(); 

它看起來像問題

所以哈克的解決方法是使用本地即定義。

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

很確定有更好的方法 - 也許使用Spring?

+1

'EntityManagerHelper'內發生了什麼? – axtavt

+0

@DataNucleus:他沒有說他想要並行運行它們。 –

+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); 

看起來真的很奇怪,因爲通常你會一個DAO層封裝entityManager,因此,所有你需要做的是dao.save(l)

0

對於可能有這個問題的人這是我如何解決它。我正在做多個保存,我一直得到這個錯誤。您不想在沒有檢查它是否處於活動狀態的情況下開始多個事務。

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

我實現了一個Singleton方法來處理它。

+2

錯誤的編碼。您的實體經理仍然會嘗試提交... – Andreas

相關問題