使用Hibernate在flush()方法中进行无限递归

时间:2011-09-05 10:26:13

标签: hibernate jpa junit

我认为这是一个奇怪的问题,但它确实存在!

放入上下文: 我正在实现我的JUnit测试,我正在测试一个名为songJPA的类。我创建了一首歌(OK),然后我创建了一个同名的歌曲,我期待一个异常(OK),最后我想删除第一首歌创建(在下一个执行测试时间没有错误)。

问题在于,当我单独执行DeleteSongTest()时,它会工作并删除我的歌曲,但是当我执行所有这些时,它不起作用,它进入无限递归。我认为它发生在flush()方法中,我试图调试,但这是不可能的。

我粘贴了所有正在工作的课程。

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

仅在我单独执行时才有效的destroy方法。 (来自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:create()方法

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错误:1205,SQLState:41000   54587 [main] ERROR org.hibernate.util.JDBCExceptionReporter - 超出锁定等待超时;试试>重启交易

TIA寻求帮助!!!!

1 个答案:

答案 0 :(得分:2)

从JPA方法获得异常后,必须考虑必须回滚事务,并且必须关闭EM:第一级缓存处于错误状态且无法恢复。有关详细信息,请参阅http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html_single/#transactions-demarcation-exceptions

使用EM.find而不是EM.getReference,并测试null。当您知道具有给定ID的实体时,将使用getReference。因此,如果它稍后出现它会引发异常,但它已经太晚了。而find执行查询以获取实体的状态,而如果它不存在则返回null。如果实体尚不存在,您可以创建该实体,如果存在,则删除它。

此外,您似乎期望测试按固定顺序运行。你不应该。每个单元测试应该单独运行,并且应该运行是否已经运行了先前的测试。使用注释为@After的方法在每次测试后执行一些清理。