2017-01-17 8 views
0

내 응용 프로그램에서 JPA에이 문제가 발생했습니다. 나는 모든 것을 게으르게 가져 오도록 설정 한 다른 엔티티와 일대일/많은 에칭 관계를 가진 상위 엔티티 아티스트를 보유하고 있습니다. 조인 쿼리를 사용하여 이러한 엔티티를 가져옵니다. 이 모든 잘 작동하는 것하지만 때로는 LazyInitializationException 얻을. 백엔드에서 JPA와 웹 레이어에서 스프링 MVC를 사용하여 Stateless EJB를 사용하고 있습니다. 여기 엔티티 클래스 아티스트JPA에서 가져 오기 결합으로 LazyInitializationException이 발생하는 경우가 있음

@Entity 
@Table(name="ARTIST") 
public class Artist extends DescribingEntity { 

private static final long serialVersionUID = -7264327449601568983L; 

@ManyToMany(mappedBy="artists", targetEntity=Member.class, fetch=FetchType.LAZY, cascade={MERGE, REFRESH}) 
private List<Member> members; 

@OneToMany(mappedBy="artist", targetEntity=VenueReview.class, fetch=FetchType.LAZY, cascade={MERGE, REFRESH, REMOVE}) 
private List<VenueReview> reviews; 

@OneToMany(mappedBy="artist", targetEntity=Gig.class, fetch=FetchType.LAZY, cascade={MERGE, REFRESH, REMOVE}) 
private List<Gig> gigs; 

@OneToMany(mappedBy="artist", targetEntity=GigRequest.class, fetch=FetchType.LAZY, cascade={MERGE, REFRESH, REMOVE}) 
private List<GigRequest> requests; 

@ManyToMany(cascade={MERGE, REFRESH}, fetch=FetchType.LAZY) 
@JoinTable(name="VENUE_ARTIST_REL", 
    [email protected](name="ARTIST_ID", referencedColumnName="ARTIST_ID"), 
    [email protected](name="VENUE_ID", referencedColumnName="VENUE_ID")) 
private List<Venue> venues; 

getters and setters... 

그때 무엇이 ​​잘못되었는지 알아 디버그 모드로 가서 내가 방법을 단계별로하고대로 오류를 반환하지 않습니다

public Artist getArtistWithChildren(long id, boolean isFetchReviews, boolean isFetchRequests, boolean isFetchGigs, boolean isFetchVenues) { 
    StringBuilder sql = new StringBuilder(); 
    sql.append("select a from Artist a join fetch a.members mrs"); 
    if(isFetchReviews) { 
     sql.append(" left join a.reviews rvs"); 
    } if(isFetchRequests) { 
     sql.append(" left join a.requests rqs"); 
    } if(isFetchGigs) { 
     sql.append(" left join a.gigs gs"); 
    } if(isFetchVenues) { 
     sql.append(" left join a.venues vs"); 
    } 

    sql.append(" where a.id=:id"); 

    TypedQuery<Artist> query = em.createQuery(sql.toString(), Artist.class); 
    query.setParameter("id", id); 
    query.setMaxResults(1); 
    List<Artist> resultList = query.getResultList(); 
    return resultList.get(0); 
} 

그리고 다음은 방법입니다 예외는 발생하지 않습니다. DB에서 모든 데이터가 올바르게 채울 시간이 없도록 콜렉션이 너무 빨리 반환 될 수 있습니까? JPA에 관해서는 초보자입니다. 그래서 내가 잘못한 것을 알려주십시오. 다음은 그 예입니다. 결과를 얻지 못해서 여기서 왼쪽 조인을 사용하고 있지만 인스턴스화 된 컬렉션이 필요합니다.

Arquillian을 사용하여 동일한 작업을 테스트했지만 오류가 발생하지 않았으며 동일한 시나리오가있는 다른 엔티티에 대해서도 비슷한 방법이 있습니다. 단순히 실행하면 단계별 디버깅 중에 오류가 발생합니다.

자식 컬렉션에 대해 Hibernate.initialize(Object o)을 사용하면 문제가 없지만 각 자식에 대해 DB 쿼리를 작성해야하기 때문에 내 지식이 좋지 않습니다.

나는

일반에 Stack Trace

답변

1

는, LazyInitializationException이 당신이 컬렉션 게으른 로딩있어과를 둘러싸는 세션을 가진 밖으로 해당 모음에 액세스하려고 할 때 발생하는 스택 추적에 페이스트 빈 링크를 추가 컨텍스트 (본질적으로)에서 당신이 게으른 콜렉션에 액세스하려고 시도하는 것이다. 당신이 당신의 문제에 대한 정확한 해상도를 얻을 수 있도록 오류 스택 추적을 게시 할 수있는 경우는 다음

+0

내가 추가 스택 트레이스를 링크로 사용합니다. – Johan

+1

세션이 없으며 트랜잭션이 없습니다. 예 : 분리 된 엔티티 –

+0

나쁘다. 세션이 없다. 나를 고쳐 주셔서 고마워요. – Shriram

1

이 원인이 설명되어 훨씬 더 도움이 될 것이다 :

일반적인 문제

문제 일반적인 (웹) 애플리케이션에서 동작의 주요 로직이 완료된 후 뷰가 렌더링되므로 Hibernate Session은 이미 닫혀 있고 데이터베이스 트랜잭션은 종료되었다. JSP (또는 다른 뷰 렌더링 메커니즘) 내부의 세션에로드 된 분리 객체에 액세스하면 언로드 된 콜렉션이나 초기화되지 않은 프록시에 충돌 할 수 있습니다. 예외는 다음과 같습니다. LazyInitializationException : 세션이 닫혔습니다 (또는 매우 유사한 메시지). 물론, 이것은 당신이 이미 당신의 작업 단위를 끝낸 후에 예상 될 것입니다.

해결 방법은 열기 세션보기 패턴입니다. 스프링 기반 응용 프로그램에서는 org.springframework.orm.hibernate5.support.OpenSessionInViewInterceptor 또는 org.springframework.orm.hibernate5.support.OpenSessionInViewFilter을 사용할 수 있지만 두 프로젝트를 실제로 하나의 프로젝트에서 사용할 수는 없습니다.

그러나 일부 reasion에 대한

은, 그것이 안티 패턴으로 처리됩니다

** 참고 : **

Open Session in View