2011-09-05 64 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