今天在Spring Boot項目中使用JPA(Hibernate)進行數據庫訪問時,
spring:
jpa:
generate-ddl: false
show-sql: true
hibernate:
ddl-auto: none
open-in-view: true
查詢一個實體對象時出現異常:
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: com.xgclassroom.model.User$HibernateProxy$PpGM4JxY["hibernateLazyInitializer"])
仔細看了下報錯信息,發現直接原因是:jackson在對hibernate的持久化實體類的代理對象進行序列化時,代理類中的"hibernateLazyInitializer"屬性為空,觸發了系列化規划SerializationFeature.FAIL_ON_EMPTY_BEANS,即“出現空Bean時觸發序列化失敗”!
"hibernateLazyInitializer"屬性為空之所以為空是因為我們禁用了延遲加載(open-in-view: true),設為false又會引發no Session錯誤。
報錯信息中告訴我們可以通過禁用jackson的SerializationFeature.FAIL_ON_EMPTY_BEANS這條系列化規則來避免該異常(異常信息中的紅色字所示),我們可以通過以下方式使用禁用了SerializationFeature.FAIL_ON_EMPTY_BEANS規則的新ObjectMapper替換默認的ObjectMapper的方法來達到目的:
@SpringBootApplication @Configuration public class ProviderUserApplication { public static void main(String[] args) { SpringApplication.run(ProviderUserApplication.class, args); } @Bean public ObjectMapper objectMapper() { return new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); } }
當然,也可以直接在相應的要實體類上通過@JsonIgnoreProperties忽略掉為空的屬性的系列化:
@Getter @Setter @Entity @JsonIgnoreProperties(value = {"hibernateLazyInitializer"}) public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Column private String username; @Column private String name; @Column private Integer age; @Column private BigDecimal balance; }
下面來看一下兩種方法重到的系列化結果樣例:
{"id":1,"username":"account1","name":"張三","age":20,"balance":100.00,"hibernateLazyInitializer":{}}
{"id":1,"username":"account1","name":"張三","age":20,"balance":100.00}