我有一个实体:
@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响应中。当jackson序列化对象时,我可以用任何方式排除那些延迟加载的字段吗?
这是我的ObjectMapper的配置:
Hibernate4Module hm = new Hibernate4Module();
hm.configure(Hibernate4Module.Feature.FORCE_LAZY_LOADING, false);
registerModule(hm);
configure(SerializationFeature.INDENT_OUTPUT, true);
谢谢!
我无法将其标记为JsonIgnore,因为它将永远不在序列化框中。有时候我需要随书检索这些类型,然后我会在查询中使用“fetch join”,这样它就不会为空。
答案 0 :(得分:11)
您可以使用杰克逊@JsonInclude
注释执行此操作。
根据latest version's javadoc (2.4 right now),如果字段值为null或为空,则可以使用简单注释指定是否包含带注释的属性。
默认情况下,它是JsonInclude.Include.ALWAYS
,这意味着即使您的懒惰未加载值为null,Jackson也会包含该属性。
指定不包含空值或空值可以显着减小JSON响应的大小,包括所有好处..
如果要更改此行为,可以在类级别或单个属性/ getterMethod级别添加注释。
尝试将以下注释添加到您不想包含的字段(如果为空):
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@OneToMany(fetch = FetchType.LAZY, mappedBy = ("movie"),cascade = CascadeType.ALL)
private List<Genre> genre;
答案 1 :(得分:3)
您可以使用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中指定要过滤的内容:
@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)
}
}
通过这种方式,您可以控制何时在运行时过滤惰性关系
答案 2 :(得分:1)
这可能与a known issue about lazy loading有关。
我不使用jackson-datatype-hibernate,但是我为解决同样的问题所做的是通过使用DTO而不是直接序列化Hibernate对象来获取图片中的持久集合。像Dozer这样的工具可以帮助你解决这个问题。或者,我写了一个small utility来做这样的映射。
如果您只想试验DTO的外观,可以使用常规的空集合替换已卸载的持久集合,例如books.setGenre(new ArrayList&lt;&gt;());不幸的是,我不知道是否有一种方法来判断是否已加载延迟加载的对象,因此您无法自动进行此重新分配。您需要根据具体情况确定替换持久性集合的位置。
答案 3 :(得分:1)
您可以使用 spring 配置默认禁用强制延迟加载!
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
Hibernate5Module hibernate5Module = new Hibernate5Module();
hibernate5Module.configure(Feature.FORCE_LAZY_LOADING, false);
// Enable below line to switch lazy loaded json from null to a blank object!
//hibernate5Module.configure(Feature.SERIALIZE_IDENTIFIER_FOR_LAZY_NOT_LOADED_OBJECTS, true);
mapper.registerModule(hibernate5Module);
return mapper;
}
}
答案 4 :(得分:-1)
您可以使用Gson代替ObjectMapper,并在定义实体时将字段标记为“瞬态”
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 **transient** List<Genre> genre;
}
在使用gson.toJson(book)
进行反序列化时,Gson不会对该元素进行反序列化。