具体重现的例子参照这个Tag: https://github.com/icbd/SpringBoardToDo/releases/tag/q.getOne
报错如下:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.springboardtodo.model.Task
qfPD64HV["hibernateLazyInitializer"])
为什么
如果换用 findById
会发现就没有报错了, 这又是为什么.
/**
* Retrieves an entity by its id.
*
* @param id must not be {@literal null}.
* @return the entity with the given id or {@literal Optional#empty()} if none found.
* @throws IllegalArgumentException if {@literal id} is {@literal null}.
*/
Optional<T> findById(ID id);
/**
* Returns a reference to the entity with the given identifier. Depending on how the JPA persistence provider is
* implemented this is very likely to always return an instance and throw an
* {@link javax.persistence.EntityNotFoundException} on first access. Some of them will reject invalid identifiers
* immediately.
*
* @param id must not be {@literal null}.
* @return a reference to the entity with the given identifier.
* @see EntityManager#getReference(Class, Object) for details on when an exception is thrown.
*/
T getOne(ID id);
他们除了返回类型不同, 再就是, findById
是 EAGER 加载; getOne
是 LAZY 加载, 得到的是一个实体的引用, 这导致 Hibernate 用于维护懒加载逻辑的属性也被 Jackson 读去做序列化, Jackson 不会做就抛异常了.
怎么办
方法1:
换用findById
.
大部分情况下你感觉不到他们的差别, 除非你只想用该Entity的Id而不关心其他具体属性的时候, 才会特别想用getOne
, 具体参考 Difference between getOne and findById in Spring Data JPA?方法2:
让 Jackson 忽略异常.
往application.properties
里添加配置:
spring.jackson.serialization.fail-on-empty-beans=false
- 方法3:
让 Jackson 忽略额外的属性.
@Entity
@JsonIgnoreProperties(ignoreUnknown = true, value = {"hibernateLazyInitializer", "handler", "fieldHandler"})
public class User {
//...
}
方法4:
使用 Jackson 插件: https://github.com/FasterXML/jackson-datatype-hibernate
它使得Jackson序列化的时候忽略所有的懒加载的属性, 实现了按需加载, 也就自然解决了这个问题.方法5:
把原始的 Entity 转为 DTO 再对外暴露.
具体参见: https://mapstruct.org/
其他参考
https://blog.csdn.net/lihushiwoa/article/details/21973695
https://blog.csdn.net/jxchallenger/article/details/79307062
jackson-datatype-hibernate5