복붙노트

[SPRING] JSON 시리얼 라이저에서 지연로드 오류

SPRING

JSON 시리얼 라이저에서 지연로드 오류

나는 그런 종류의 @OneToOne Hibernate relationShip을 가지고있다.

public class Address implements Serializable {

    private String id;
    private String city;
    private String country;
//setter getters ommitted
}

public class Student implements Serializable {

    private String id;
    private String firstName;
    private String lastName;    
    private Address address;
}

주소 항목은 LAZY로 매핑됩니다.

이제 사용자를 불러오고 주소를 사용하고 싶습니다.

session.load(Student.class,id);

내 DAO 서비스.

그런 다음 스프링 MVC 컨트롤러에서 JSON으로 리턴한다.

@RequestMapping(value="/getStudent.do",method=RequestMethod.POST)
    @ResponseBody
    public Student getStudent(@RequestParam("studentId") String id){
        Student student = daoService.getStudent(id);
        return student;
    }

불행히도 Lazy 클래스로 인해 작동하지 않습니다.

org.codehaus.jackson.map.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: com.vanilla.objects.Student_$$_javassist_1["address"]->com.vanilla.objects.Address_$$_javassist_0["handler"])
    at org.codehaus.jackson.map.ser.StdSerializerProvider$1.serialize(StdSerializerProvider.java:62)

OpenSessionInViewInterceptor를 사용하고 잘 작동합니다. 나는 사용자가 HQL 질의에 참여하고 학생과 주소를 검색하여 문제를 해결할 수 있음을 이해한다. 또한 EAGER와의 관계를 바꾸면 해결 될 수 있음을 이해합니다.

하지만 표준 잭슨 메시지 변환기를 사용하여 JSON 지연 클래스에 직렬화 할 수 있습니다. 원인은 XML 파일에 추가 된 원인입니다.

해결법

  1. ==============================

    1.가장 쉬운 솔루션 : 엔티티를 직렬화하지 않고 값 객체를 사용하십시오.

    가장 쉬운 솔루션 : 엔티티를 직렬화하지 않고 값 객체를 사용하십시오.

    이것이 옵션이 아니라면 엔티티 객체가 분리되었는지 확인하십시오.

    JPA (2)를 사용하면 EntityManager.detach (entity)를 사용하고, 평이한 Hibernate는 Session.evict (entity)와 동등합니다.

  2. ==============================

    2.일단 내가 이것을 처리하기위한 프로세서를 작성했지만 지금은 jackson hibernate 모듈을 사용하여 이것을 고칠 수있다.

    일단 내가 이것을 처리하기위한 프로세서를 작성했지만 지금은 jackson hibernate 모듈을 사용하여 이것을 고칠 수있다.

  3. ==============================

    3.DAO 메소드 내에서 Hibernate.initialize ()를 추가하십시오. 이 문제를 해결하십시오.

    DAO 메소드 내에서 Hibernate.initialize ()를 추가하십시오. 이 문제를 해결하십시오.

    Student student = findById(<yourId>);
    Hibernate.initialize(student.getAddress());
    ...
    return student;
    

    위와 같이 시도하십시오.

  4. ==============================

    4.문제를 해결하는 또 다른 옵션이 있습니다. 이 필터는 web.xml에 추가 할 수 있습니다.

    문제를 해결하는 또 다른 옵션이 있습니다. 이 필터는 web.xml에 추가 할 수 있습니다.

    <filter>
        <filter-name>springOpenEntityManagerInViewFilter</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>springOpenEntityManagerInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
    

    문제는 엔터티가 느슨하게로드되고 직렬화가 완전히로드되기 전에 발생한다는 것입니다.

  5. ==============================

    5.우선,이 문제를 해결하기 위해서만 DTO / Value Object를 사용할 것을 권장하지 않습니다. 처음에는 쉽게 찾을 수 있지만 새로 개발 / 변경 될 때마다 중복 코드 란 매번 두 번씩 수정하는 것을 의미합니다. 그렇지 않으면 버그가 발생합니다.

    우선,이 문제를 해결하기 위해서만 DTO / Value Object를 사용할 것을 권장하지 않습니다. 처음에는 쉽게 찾을 수 있지만 새로 개발 / 변경 될 때마다 중복 코드 란 매번 두 번씩 수정하는 것을 의미합니다. 그렇지 않으면 버그가 발생합니다.

    나는 VO 나 DTO가 나쁜 냄새가 나는 것은 아니지만 논리적 계층에 따라 다른 내용 / 구조를 제공하거나 해결할 수없는 직렬화 문제를 해결하는 것과 같이 설계된 이유로 사용해야 함을 의미합니다. VO / DTO없이 직렬화 문제를 해결할 수있는 깨끗하고 효율적인 방법이 있고 필요하지 않으면이를 사용하지 마십시오.

    그리고 그것에 대해서, 당신이 Hibernate 엔티티와 함께 ​​Jackson을 사용할 때 게으른 로딩 문제를 푸는 많은 방법이 있습니다.

    실제로 가장 간단한 방법은 FasterXML / jackson-datatype-hibernate를 사용하는 것입니다.

    그것은 Hibernate3Module / Hibernate4Module / Hibernate5Module을 제공한다.이 모듈은 Hibernate 특이성과 관련된 잘 정의 된 확장 집합을 제공하기 위해 ObjectMapper에 등록 할 수있는 확장 모듈이다.

    이 작업을 수행하려면 필요한 종속성을 추가하고 Jackson Module은 필요한 곳에서 처리가 가능합니다.

    최대 절전 모드 3을 사용하는 경우 :

      <dependency>
         <groupId>com.fasterxml.jackson.datatype</groupId>
         <artifactId>jackson-datatype-hibernate3</artifactId>
         <version>${jackson.version.datatype}</version>
      </dependency>
    

    최대 절전 모드 4를 사용하는 경우 :

      <dependency>
         <groupId>com.fasterxml.jackson.datatype</groupId>
         <artifactId>jackson-datatype-hibernate4</artifactId>
         <version>${jackson.version.datatype}</version>
      </dependency>
    

    그래서 ...

    jackson.version.datatype은 사용 된 Jackson 버전과 ackson-datatype 확장자에 대해 동일해야합니다.

    Spring Boot를 사용하거나 사용한다면, 특정 Configuration 클래스 나 SpringBootApplication 클래스에서 Bean으로 선언 할 필요가 있으며 생성 된 Jackson ObjectMapper에 대해 자동으로 등록됩니다.

    74.3 Jackson ObjectMapper Spring Boot 사용자 정의 섹션에는 다음 내용이 나와 있습니다.

    예 :

    @Configuration
    public class MyJacksonConfig {
    
        @Bean
        public Module hibernate5Module() {
          return new Hibernate5Module();
        }
    }
    

    또는 :

    @SpringBootApplication
    public class AppConfig {
    
        public static void main(String[] args) throws IOException {
          SpringApplication.run(AppConfig.class, args);
        }
    
        @Bean
        public Module hibernate5Module() {
          return new Hibernate5Module();
        }
    }
    
  6. from https://stackoverflow.com/questions/6277439/lazy-loadng-error-in-json-serializer by cc-by-sa and MIT license