2011-09-05 9 views
0

이것은 이상한 문제이지만 거기에 간다!최대 절전 모드의 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()); 
} 

은 내가 개별적으로 실행할 경우에만 작동 방법을 파괴한다.

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 (A 넷빈즈 템플릿에서인가) : 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 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() 메서드에서 발생합니다. 두 번째 문제에 관해서도 After 및 AfterClass 주석을 사용하여 시도했지만 동일한 내용입니다. 문제가있는 메서드를 실행하기 전에 잠시 기다려야했기 때문에 고정 된 순서로 메서드를 실행하려고 시도했습니다. 다른 테스트 클래스를 만들고이 메서드를 다른 것으로부터 분리 한 다음 모든 것을 TestSuite에 포함하려고합니다. – migueloop

+0

테스트 클래스에서 메소드를 분리하고 공통 테스트 스위트에서 실행하면 좋습니다. 물론 더 많은 제안이 있습니까? – migueloop

관련 문제