2014-09-16 4 views
0

계속해서 반복되는 Hibernate Lazy Loading 오류로 인해 중첩 된 객체를 편집하고 업데이트하는 데 어려움을 겪고 있습니다. 내 응용 프로그램에서Hibernate 프록시 객체에 세션 오류가 없습니다.

는 :

  1. 나는 제품으로 설정 이미지를 결합한다.
  2. 포맷 상자를 사용하여 선택 상자에서 사용하기 위해 이미지 세트를 변환 했으므로 사용자가 이미지 세트를 선택할 수 있습니다.
  3. 양식이 성공하고 개체가 바인딩되고 관계가 올바르게 저장되면 제대로 작동합니다.
  4. 그러나 유효성 검사에 실패하면 UI 레이어가 중첩 된 개체 값에 액세스하려고 할 때마다 두려운 Lazy Initialization/No Session 오류가 발생합니다! 그 방법 작품

    @Transactional 
    public void initObject(Variant variant) { 
        Hibernate.initialize(variant.getOption1()); 
        Hibernate.initialize(variant.getOption2()); 
        Hibernate.initialize(variant.getOption3()); 
        Hibernate.initialize(variant.getImageSet()); 
    } 
    

    제 3 개 라인들 (이것들은 하나의 단방향 하나)이지만 아무튼 네번째 :

그래서이 해결책으로 관련된 객체를 초기화하는 방법을 작성하려고 't (이것은 1 대 다), 여전히 프록시는 없다고 말합니다.

나는 모든 것을 열망하는 가져 오기 유형을 만들려고 시도했습니다.

이들 중 어느 것도 작동하지 않았습니다.

문제는 아마도 상위 개체를 만들고 있는데 유효성 검사 오류가 발생하면 데이터베이스에 저장되지 않지만 중첩 개체는 가져 오기 유형에 관계없이 어떤 이유에서든 지연 프록시 개체입니다. 아래 포맷터 참조).

어떻게 해결할 수 있습니까?

포맷터 성분이다

@Component 
public class ImageSetFormatter implements Formatter<ProductImageSet> { 

    private static Logger logger = LogManager.getLogger(VariantController.class.getName()); 

    @Autowired 
    private ProductImageService imageService; 

    @Override 
    public ProductImageSet parse(String s, Locale locale) throws ParseException { 
     logger.entry(); 

     Long imageSetId = Long.valueOf(s); 
     logger.exit(); 
     return imageService.getImageSet(imageSetId); 
    } 

    @Override 
    public String print(ProductImageSet productImageSet, Locale locale) { 
     logger.entry(); 

     logger.exit(); 
     return Long.toString(productImageSet.getId()); 
    } 
} 

스택 트레이스시 라인들 Hibernate.initialize (variant.getImageSet())가 호출 :

org.springframework.web.util.NestedServletException : 요청한 요청 실패; 상자의 예외는 org.hibernate.LazyInitializationException입니다 : 프록시 초기화 할 수 없습니다 - 아니 세션 org.springframework.web.servlet.FrameworkServlet.processRequest (FrameworkServlet.java:973) org.springframework.web.servlet.FrameworkServlet.doPost (FrameworkServlet를 .java : 863) org.springframework.web.servlet.FrameworkServlet.service (FrameworkServlet.java:837) javax.servlet.http.HttpServlet.service (HttpServlet.java:644) 서비스 (HttpServlet.java:725) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal (CharacterEncodingFilter.java:88) org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:107) org.springframework .web.f ilter.HiddenHttpMethodFilter.doFilterInternal (HiddenHttpMethodFilter.java:77) org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:107) org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter (FilterChainProxy.java : 330) org.springframework.security.web.access.ExceptionTranslationFilter.doFilter (ExceptionTranslationFilter.java:113) org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter (FilterChainProxy.java:342) org.springframework.security.web.session.SessionManagementFilter.doFilter (SessionManagementFilter.java:103) org.springframework.security.web.FilterChainProxy $ VirtualFilterChain. doFilter (FilterChainProxy.java:342) org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter (AnonymousAuthenticationFilter.java:113)

관련 개체 관계 :

@Entity 
@Table(name="variants") 
@EntityListeners({AuditingEntityListener.class}) 
public class Variant extends AbstractAuditable<Customer, Long> { 

    @OneToOne 
    private VariantOptionValue option1; 

    @OneToOne 
    private VariantOptionValue option2; 

    @OneToOne 
    private VariantOptionValue option3; 

    ... 

    @ManyToOne 
    @JoinColumn(name="image_set_id") 
    @LazyCollection(LazyCollectionOption.FALSE) 
    private ProductImageSet imageSet; 



} 


@Entity 
@Table(name="product_image_set") 
@EntityListeners({AuditingEntityListener.class}) 
public class ProductImageSet extends AbstractAuditable<Customer, Long> { 


    public ProductImageSet(String label) 
    { 
     this.label = label; 
    } 

    public ProductImageSet(){ 

    } 

    @Basic 
    @Column(length = 50, nullable = false) 
    private String label; 

    @OneToMany(mappedBy = "imageSet", fetch = FetchType.EAGER) 
    private List<ProductImage> images; 

    @OneToMany(mappedBy = "imageSet", fetch = FetchType.EAGER) 
    private List<Variant> variants; 

    private int sequence; 

    @ManyToOne 
    @JoinColumn(name = "product_id") 
    private Product product; 

    ... 
} 
+0

당신은 당신이 점점 예외의 실제 스택 트레이스를 게시 할 수 있습니까? 오류 메시지는 오류가 무엇인지에 대한 단서를 제공 할 수 있습니다. 사용중인 오브젝트를 게시하거나 관계에 대한 자세한 설명을 제공 할 수 있습니까 (X에는 Y가 많고 Y에는 Z가 하나) – JamesENL

+0

오브젝트 관계에 대한 설명을 게시 할 수 있습니까? 당신은 부모 개체에 대해 이야기하지만 부모가 무엇이고 자식이 무엇인지 알아야합니다. – JamesENL

+0

fetch = FetchType.EAGER의 몇 가지 변형을 시도했음을 유의하십시오. LazyCollection은 최신 수정 사항 일뿐입니다. –

답변

0

두 가지 당신이 수도 시도하고 싶다.

1 세션에 개체/양식/모델을 추가

@Controller 
@SessionAttributes("yourEntityFormModel") 
public class YourController { 
    ... 
} 

--------- 업데이트를 OpenEntityManagerInViewFilter

<filter> 
    <filter-name>openEntityManagerInViewFilter</filter-name> 
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class> 
    <init-param> 
     <param-name>entityManagerFactoryBeanName</param-name> 
     <param-value>entityManagerFactory</param-value> 
    </init-param> 
</filter> 

<filter-mapping> 
    <filter-name>openEntityManagerInViewFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

2를 추가 무엇 트랜잭션 내에서 실행되는 주석 된 메소드에서, Hibernate는 필요에 따라 그 엔티티로부터 관계를 검색 할 수 있습니다.

따라서 아래 예는 정상적으로 작동합니다.

@Transactional 
public void updateEmployeesFromDepartment(int depId) { 

    Department dep = departmentRepository.findOne(dep.getId()); 
    for (Employee e : dep.getEmployees()) { 
     // update whatever you want 
    } 

} 

하지만이 작업을 기대하지 않습니다는 ...

public void updateEmployeesFromDepartment(int depId) { 

    Department dep = departmentRepository.findOne(dep.getId()); 
    for (Employee e : dep.getEmployees()) { 
     // update whatever you want 
    } 

} 
+0

왜 1 번이 나쁜 생각인지 [this] (http://stackoverflow.com/questions/1538222/why-not-to-use-springs-openentitymanagerinviewfilter)를 참조하십시오. – JamesENL

+0

또한 RESTful 응용 프로그램 인 경우 숫자 2는 세션에 모델을 추가하여 상태 저장을 수행 할 때 RESTful 구현을 완전히 파기합니다. – JamesENL

+0

@JamesMassey 나는 요점을 이해합니다 ... 논쟁의 여지가 tho ... 이것은 한때 구원 받았던 사람들 중 하나입니다. 그러나 사람들 (!?!)은 더 이상 그것을 좋아하지 않습니다. 사전에 모든 필수 정보를로드하는 것을 선호하지만, 여기있는 친구를 도울 수 있으면 나중에 좋아하는지 결정할 수 있습니다. :) – Desorder