2011-09-05 36 views
0

我這是一個奇怪的問題,但它去了!Hibernate的flush()方法中的無限遞歸

放在上下文中: 我正在執行我的JUnit測試,我正在測試一個名爲songJPA的類。我創建了一首歌曲(OK),然後我創建了一個具有相同名稱的歌曲,並期望有一個例外(OK),最後我想要刪除第一首歌曲創建(在下一次執行測試時間中不會有錯誤)。

問題是,當我單獨執行DeleteSongTest()時,它工作並刪除我的歌曲,但是當我執行它們全部時,它不起作用,它進入無限遞歸。我認爲它在flush()方法中發生,我嘗試調試但不可能。

我粘貼所有我認爲正在工作的類。

JUnit測試類:

public class SongCRUDTest { 

private SongJPA testSong1; 
private SongJPA testSong2; 
private SongJPAJpaController slc; 

@Before 
public void setUp() { 
    testSong1= new SongJPA("TestTitle", 120, 19, new SongInfoJPA(), "TestArtist", Genre.CLASSICAL); 
    testSong2= new SongJPA("TestTitle", 122, 12, new SongInfoJPA(), "TestArtist2", Genre.BLUES); 
    slc = new SongJPAJpaController(); 
} 

@Test 
public void A_createSong(){ 
    slc.create(testSong1); 
} 


@Test(expected = PersistenceException.class) 
public void B_createDuplicatedTestSong() { 
    slc.create(testSong2); 
} 

@Ignore 
@Test 
public void C_deleteSong() throws NonexistentEntityException{ 
    SongJPA songToDelete= slc.findSongJPAByTitle("TestTitle"); 
    if(songToDelete!=null) 
     slc.destroy(songToDelete.getId()); 
} 

的銷燬方法,只有當我單獨執行工作。 (從NetBeans的模板)

public void destroy(int id) throws NonexistentEntityException { 
    EntityManager em = null; 
    try { 
     em = getEntityManager(); 
     em.getTransaction().begin(); 
     SongJPA songJPA; 
     try { 
      songJPA = em.getReference(SongJPA.class, id); 
      songJPA.getId(); 
     } catch (EntityNotFoundException enfe) { 
      throw new NonexistentEntityException("The songJPA with id " + id + " no longer exists.", enfe); 
     } 
     em.remove(songJPA); 
     em.flush(); 
     em.getTransaction().commit(); 
    } finally { 
     if (em != null) { 
      em.close(); 
     } 
    } 
} 

版1:創建()方法

public void create(SongJPA songJPA) { EntityManager em = null; try { em = getEntityManager(); em.getTransaction().begin(); em.persist(songJPA); em.getTransaction().commit(); } finally { if (em != null) { em.close(); } } }

enter image description here

秒鐘後

54587 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 1205, SQLState: 41000 54587 [main] ERROR org.hibernate.util.JDBCExceptionReporter - Lock wait timeout exceeded; try > restarting transaction

TIA求助!!!!

+0

你可以顯示'create()'方法嗎? – axtavt

+0

當然@axtavt – migueloop

回答

2

從JPA方法中獲得異常後,必須考慮事務必須回滾,並且EM必須關閉:第一級高速緩存處於不良狀態並且無法恢復。詳情請參閱http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html_single/#transactions-demarcation-exceptions

使用EM.find而不是EM.getReference,並測試爲null。 getReference用於當您知道存在具有給定ID的實體。如果它晚些時候出現,它會拋出一個異常,但它已經太晚了。 find執行查詢以獲取實體的狀態,如果不存在則返回null。如果實體尚不存在,您可以創建該實體,如果實體存在,也可以將其刪除。

此外,您似乎期待測試以固定順序運行。你不應該。每個單元測試都應該單獨運行,並且應該運行,不管之前的測試是否已經運行。在每次測試後使用用@After註釋的方法執行一些清理。

+0

好的,謝謝你的回覆@JB Nizet。 第一個問題,我嘗試使用EM.find,它也沒有工作,我只是在getId()方法中添加了一個System.out.println(),並且它返回了正確的ID。稍後在flush()方法中出現問題。 關於第二個問題,我也嘗試過使用After和AfterClass註釋,但它是一樣的。 我試圖以一個固定的順序執行該方法因爲我試圖等待一點,然後執行有問題的方法 我正在考慮製作不同的測試類,將此方法與其他測試類分開,然後將所有內容都包含在TestSuite中。 – migueloop

+0

好的,當然,如果我將測試類中的方法分開,並且運行在一個通用測試套件中,那是一樣的...還有更多建議嗎? – migueloop