2014-09-18 4 views
6

를 직렬화하지 않습니다 내 컨트롤러. 잭슨이 객체를 직렬화 할 때 게으른로드 된 필드는 어떤 방법 으로든 제외 할 수 있습니까?잭슨 내가 엔티티가 게으른 개체

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

감사 :

이 내 ObjectMapper의 구성입니다!

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

+0

[과도] [1] [1] : http://stackoverflow.com/ 질문/20700530/why-use-transient-keyword-in-java 이 주제를 사용하여 anserw를 얻으십시오.) – Fincio

+0

안녕하세요 @Fincio, 장르가 일시적으로 변할 수 없습니다. 데이터 베이스. – lorraine

+0

흠, @JsonIgnoreProperties ({ "genre"}) 또는 @JsonIgnore는 어떨까요? – Fincio

답변

7

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

latest version's javadoc (2.4 right now)에 따르면 필드 값이 null이거나 비어있는 경우 주석이 추가 된 속성을 포함 할 것인지 여부를 간단한 주석으로 지정할 수 있습니다.

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

이 동작을 변경하려면, 당신은 클래스에 주석을 추가 할 수 있습니다

크게 .. 포함 된 모든 혜택과 함께, JSON 응답의 크기를 줄일 수 있습니다 비어 있거나 null 값을 포함하지 않는하기 위해 지정 수준 또는 단일 속성/getterMethod 수준.필드에 다음과 같은 주석을 추가 할 수

봅니다 당신은 포함하지 않는 비어있는 경우 :

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

이것은 Spring JPA + Spring REST Controller 솔루션에서 작동하지 않습니다. 게으른 페칭은 여전히 ​​JSON 직렬화가 발생할 때 발생합니다 ... –

+0

이것은 EclipseLink와 함께 JPA 2.1에 대한 정답이 아닙니다! 문제는 잭슨이 getter를 호출하여 "NON_EMPTY"속성을 확인하고 Lazy Loading을 트리거하는 것입니다. 불행하게도 AccesType "Field"Json Annotation 등은 도움이되지 않습니다. 이것은 Moxy가 지원하는 방식에 의한 것입니다 (저는 이것이 JAXB 주석을 사용한다고 생각합니다). – Nabi

+0

@RonyeVernaes 그것은'Hibernate5Module' 빈을 추가 한 후에 작동합니다. http://stackoverflow.com/questions/21708339/avoid-jackson-serialization-on-non-fetched-lazy-objects에서 chrismarx의 대답을 참조하십시오. – Zeemee

1

아마도 이것은 a known issue about lazy loading과 관련됩니다.

나는 jackson-datatype-hibernate를 사용하지 않지만 동일한 문제를 해결하기 위해 수행 한 작업은 최대 절전 모드 개체를 직접 직렬화하는 대신 DTO를 사용하여 그림에서 영구 컬렉션을 얻는 것입니다. Dozer와 같은 도구를 사용하면 도움이됩니다. 또는 이와 같은 매핑을 수행하기 위해 작성한 small utility이 있습니다.

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

2

당신은 Jackson's JSON Filter Feature 사용할 수 있습니다

@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) 
     } 

} 

, 당신이 제어 할 수 있습니다 당신은 런타임에 게으른 관계를 필터링 할 때

+0

편집 대기열이 가득 차서 한 줄을 수정해야합니다. addFilter()의 두 번째 인수는 ** SimpleBeanPropertyFilter **. serializeAll ...이 아닌 SimpleFilterProvider ** serializeAll ... 클래스 –