복붙노트

[SPRING] jackson - 게으른 객체를 직렬화하지 않는다.

SPRING

jackson - 게으른 객체를 직렬화하지 않는다.

엔티티가 있습니다.

@Entity
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column
    private String title;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = ("movie"),cascade = CascadeType.ALL)
    private List<Genre> genre;

}

그런 다음 책을 검색하는 목적을 가진 컨트롤러가 있습니다. 제 문제는 장르 필드가 컨트롤러의 json 응답에 포함되어 있다는 것입니다. 잭슨이 객체를 직렬화 할 때 게으른로드 된 필드를 제외 할 수는 있습니까?

이것은 내 ObjectMapper의 구성입니다.

Hibernate4Module hm = new Hibernate4Module();
hm.configure(Hibernate4Module.Feature.FORCE_LAZY_LOADING, false);
registerModule(hm);
configure(SerializationFeature.INDENT_OUTPUT, true);

감사!

그것은 serialization 상자에서 영원히 벗어날 것이므로 JsonIgnore로 표시 할 수 없습니다. 장르와 함께 장르를 검색해야 할 때가있을 것입니다. 그러면 내 쿼리에 "fetch join"을 사용하여 null이되지 않습니다.

해결법

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

    1.Jackson @JsonInclude 주석으로이를 수행 할 수 있습니다.

    Jackson @JsonInclude 주석으로이를 수행 할 수 있습니다.

    최신 버전의 javadoc (2.4 현재)에 따르면 필드 값이 null이거나 비어있는 경우 주석이 달린 속성을 포함할지 여부를 간단한 주석으로 지정할 수 있습니다.

    기본적으로 JsonInclude.Include.ALWAYS이며 지연되지 않은 값이 null 인 경우에도 Jackson은 해당 속성을 포함합니다.

    빈 값이나 null 값을 포함하지 않도록 지정하면 JSON 응답의 크기가 크게 줄어들어 모든 이점이 포함됩니다.

    이 동작을 변경하려면 클래스 수준 또는 단일 속성 / getterMethod 수준에서 주석을 추가 할 수 있습니다.

    비어있는 경우 포함시키지 않으려는 필드에 다음 주석을 추가하십시오.

    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    @OneToMany(fetch = FetchType.LAZY, mappedBy = ("movie"),cascade = CascadeType.ALL)
    private List<Genre> genre;
    
  2. ==============================

    2.Jackson의 JSON 필터 기능을 사용할 수 있습니다.

    Jackson의 JSON 필터 기능을 사용할 수 있습니다.

    @Entity
    @JsonFilter("Book") 
    public class Book {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private long id;
    
        @Column
        private String title;
    
        @OneToMany(fetch = FetchType.LAZY, mappedBy = ("movie"),cascade = CascadeType.ALL)
        private List<Genre> genre;
    } 
    
    @Entity
    @JsonFilter("Genre")
    public class Genre {
       ...
    }
    

    그런 다음 컨트롤러에서 필터링 대상을 지정합니다.

    @Controller
    public class BookController {
          @Autowired
          private ObjectMapper objectMapper;
    
          @Autowird
          private BookRepository bookRepository;
    
           @RequestMapping(value = "/book", method = RequestMethod.GET, produces =  "application/json")
           @ResponseBody
           public ResponseEntity<String> getBooks() {
    
              final List<Book> books = booksRepository.findAll();
              final SimpleFilterProvider filter = new SimpleFilterProvider();
              filter.addFilter("Book", SimpleFilterProvider.serializeAllExcept("Genre");
              return new ResponseEntity<>(objectMapper.writer(filter).writeValueAsString(books), HttpStatus.OK)
           }
    
    }
    

    이렇게하면 런타임에 지연 관계를 필터링 할시기를 제어 할 수 있습니다.

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

    3.이것은 게으른 로딩에 대한 알려진 문제와 관련이 있을지도 모릅니다.

    이것은 게으른 로딩에 대한 알려진 문제와 관련이 있을지도 모릅니다.

    나는 jackson-datatype-hibernate를 사용하지 않지만 같은 문제를 해결하기 위해 해왔 던 것은 Hibernate 객체를 직접 직렬화하는 대신 DTO를 사용하여 그림에서 영구 컬렉션을 얻는 것이다. Dozer와 같은 도구를 사용하면 도움이됩니다. 또는 이와 같은 매핑을 수행하기 위해 작성한 작은 유틸리티가 있습니다.

    DTO가 어떻게 보이는지 실험 해 보려면 언로드 된 영구 컬렉션을 books.setGenre (new ArrayList <> ())와 같이 일반적인 빈 컬렉션으로 바꿀 수 있습니다. 불행히도 느슨하게로드 된 객체가로드되었는지 여부를 알 수 없으므로이 재 할당을 자동으로 수행 할 수 없습니다. 영구 수집을 대체하는 장소는 사례별로 결정해야합니다.

  4. from https://stackoverflow.com/questions/25906985/jackson-do-not-serialize-lazy-objects by cc-by-sa and MIT license