Solution of Spring Boot JPA Entity Jackson Serialization Triggering Lazy Load

Keywords: Java Spring Hibernate JSON Gradle

Spring Jpa technology is often used in Spring development.

Entity's Association lazy loading is used in today's project, but when returning to Json, data serialization will be triggered regardless of whether the association data is loaded or not. If the association relationship is not loaded, it is a Hibernate Proxy, not real data, which results in an error.

For example, this Topic Entity:

@Entity
@Table(name = "yms_topics")
@Getter
@Setter
@NoArgsConstructor
@EntityListeners(AuditingEntityListener.class)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@NamedEntityGraphs({
        @NamedEntityGraph(name = "topic.all",
                attributeNodes = {
                        @NamedAttributeNode(value = "author"),
                        @NamedAttributeNode(value = "category")
                })
})
public class Topic implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(targetEntity = User.class, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User author;

    @ManyToOne(targetEntity = TopicCategory.class, cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "category_id")
    private TopicCategory category;

    @Column(nullable = false, length = 200)
    private String title;

    @Lob
    @Column(nullable = false, length = 50000)
    private String content;

    @CreatedDate
    private Date createdAt;

    @LastModifiedDate
    private Date updatedAt;
}

author and category are many-to-one associations, i.e. authors and classifications. They define lazy loading LAZY. Now they need to page out records. Repository is as follows:

@EntityGraph(value = "topic.all")
Page<Topic> findAll(Pageable pageable);

This is an association to read author and category data, without any problems. But if some associations do not need to be loaded, removing EntityGraph will cause an error.

Page<Topic> findAll(Pageable pageable);

The reason is that Hibernate Proxy can't be serialized. There are many methods on the Internet, such as JsonIgnore Properties, which is the way to cure symptoms and root causes.

The goal now is to serialize the associated data, not return it when it does not exist, or return it directly to Null.

In fact, to solve this problem is very simple, that is to use Jackson's package jackson-data type-hibernate 5.
First gradle adds dependencies:

compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-hibernate5', version: '2.9.8'

Note the jackson-datatype-hibernateX version, which is based on the version of Hibernate.

Then we will rewrite Spring Mvc's Mapping Jackson 2HttpMessageConverter and register Hibernate5Module to ObjectMapper.

We create a new WebMvcConfig class as follows:

@Configuration
public class WebMvcConfig {

    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        ObjectMapper mapper = converter.getObjectMapper();
        Hibernate5Module hibernate5Module = new Hibernate5Module();
        mapper.registerModule(hibernate5Module);
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        return converter;
    }
}

This is a Config class, simple

  • That is to inject a Bean, type Mapping Jackson 2HttpMessageConverter, to get ObjectMapper
  • Register Module through mapper.registerModule(hibernate5Module); Register Module
  • You can also define a time-due serialization format.
  • Note that if you want to make the output completely non-loaded, then use Empty for class-level annotations in Entity, such as @Json Include (Json Include. Include. NON_EMPTY), or null will be output when the data is null.

Here we can achieve the desired goal.

This may lead to the failure of spring.jackson's configuration, which will be studied later.

Posted by bpops on Mon, 04 Mar 2019 18:21:23 -0800