2011-09-05 12 views
0

これは奇妙な問題ですが、そこに行く!Hibernateを使用したflush()メソッドの無限再帰

文脈に入れる: 私はJUnitテストを実装しています。私はsongJPAというクラスをテストしています。私は曲を作って(OK)、同じ名前の曲を作って、Exception(OK)を期待し、最後に最初の曲を削除したい(次回の実行時にエラーがないように)。

問題は、私がDeleteSongTest()を個別に実行すると、それが動作し、私の曲を削除することですが、すべてを実行すると、動作しません、無限再帰で入力します。私はそれがflush()メソッドで起こっていると思うし、デバッグしようとしましたが、不可能です。

私はすべてのクラスを貼り付けています。

JUnitテストのCLASS:

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(); 
     } 
    } 
} 

EDITION1:ヘルプは

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をクローズする必要があると考える必要があります。第1レベルのキャッシュは不良状態であり、回復できません。詳細は、http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html_single/#transactions-demarcation-exceptionsを参照してください。

EM.getReferenceではなくEM.findを使用し、nullをテストします。 getReferenceは、の場合、指定されたIDを持つエンティティが存在する場合に使用されます。それで、後で表示されても表示されない場合は例外がスローされますが、それはすでに遅すぎます。一方、findはクエリを実行してエンティティの状態を取得し、存在しない場合はnullを返します。エンティティがまだ存在しない場合は作成し、存在する場合は削除することができます。

さらに、テストが固定された順序で実行されると思われます。あなたはしないでください。各ユニットテストは別々に実行する必要があり、以前のテストが既に実行されているかどうかにかかわらず実行する必要があります。 @Afterと注釈を付けたメソッドを使用して、各テストの後にクリーンアップを実行します。

+0

あなたの返信ありがとうございます@JB Nizet。 最初の問題は、私はEM.findで試してみました。どちらもうまくいきませんでした。getId()メソッドのSystem.out.println()を追加して、正しいIDを返してくれました。この問題は後でflush()メソッドで発生します。 2番目の問題については、AfterとAfterClassアノテーションを使用しても試みましたが、同じです。 問題のあるメソッドを実行する前にちょっと待つことにしたので、一定の順序でメソッドを実行しようとしました 異なるテストクラスを作成し、このメソッドを別のクラスから分離してから、すべてをTestSuiteに組み込みます。 – migueloop

+0

確かに、テストクラスでメソッドを分離し、共通のテストスイートで実行すると同じです...これ以上の提案はありますか? – migueloop

関連する問題