I'm currently running a spring-boot application where an endpoint returns a Page of a particular object stored in the database. For our purpose lets call that object "x". Within "x" there is a list of objects that are set to be lazily fetched.
@Entity
@DynamicUpdate
class x {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@JsonIgnore
@OneToMany(mappedBy = "x", cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
private List<y> lazilyFetchedList;
@Override
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@JsonIgnore
public List<y> getLazilyFetchedList() {
return lazilyFetchedList;
}
public void setLazilyFetchedList(List<y> lazilyFetchedList) {
this.lazilyFetchedList = lazilyFetchedList;
}
}
I set @JsonIgnore
above because I don't want lazilyFetchedList
to be sent to the client upon a GET call.
My problem is, even though that field is successfully ignored by jackson as a client viewing the JSON response. But additional querys are still made by hibernate to fetch the lazilyFetchedList
when serializing the Java object "x" (even though jackson is not using the result).
I have already tried answers from Avoid Jackson serialization on non fetched lazy objects but none of the answers seem to work.
Here is what my controller looks like:
@RequestMapping(value = "/{id}/x", method = RequestMethod.GET)
public ApiResponse<?> findX(@PathVariable Integer id, PagingInfo info) {
Page<x> page = repo.findX(id, toPageable(info));
return toResponse(page, FIND_LIST_STATUS);
}
Here's what my configuration of the object mapper looks like:
@Configuration
@EnableWebMvc
public class ApiWebConfig extends WebMvcConfigurerAdapter {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
configureDefaultObjectMapper(objectMapper);
customizeObjectMapper(objectMapper);
return objectMapper;
}
public static void configureDefaultObjectMapper(ObjectMapper objectMapper) {
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true);
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
objectMapper.registerModule(new Hibernate5Module());
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(ZonedDateTime.class, ZonedDateTimeSerializer.INSTANCE);
javaTimeModule.addSerializer(OffsetDateTime.class, OffsetDateTimeSerializer.INSTANCE);
objectMapper.registerModule(javaTimeModule);
}
/**
* Only register a json message converter
*/
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.clear();
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON, ActuatorMediaTypes.APPLICATION_ACTUATOR_V1_JSON));
converter.setObjectMapper(objectMapper());
converters.add(converter);
}
}
Versions:
Add the following dependency to your pom.xml:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-hibernate5</artifactId>
</dependency>
(add the version if it is not managed by spring-boot-dependencies or spring-boot-starter-parent) Add the following code to your spring configuration class:
@Bean
protected Module module() {
return new Hibernate5Module();
}
With the following imports:
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With