I have an enterprise project configured by spring mvc4 + hibernate5 that all of its relation are eager and its performance is very bad...So I am transforming all eager relations to lazy step by step...But I see many errors in each step...and it works sometimes properly and sometimes not....
in this example HeaderFromStore is an instnace of RequestHeaders and a child of RequestLine. DeliveryPoint is child of requestHeader and I don't want to fetch deliveryPoint of requestHeader...But if don't use it in select query it couldn't fetch HeaderFromStore !!
I used this query and I get error!
select m from MAMRequestLines m join fetch m.mamRequestHeaders r
left join fetch m.requestHeaderFromStore rr where m.id =:id
If I use this query I don't get error
select m from MAMRequestLines m join fetch m.mamRequestHeaders r
left join fetch m.requestHeaderFromStore rr
join fetch rr.mamDeliveryPoints
left join fetch r.mamDeliveryPoints
join fetch where m.id =:id
RequestLine.java
@Entity(name = "RequestLines")
@Table(name = "_REQUEST_LINES")
//@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property = "@id")
public class RequestLines extends Entity implements Serializable {
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private RequestHeaders requestHeaders;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private RequestHeaders requestHeaderFromStore;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "_REQUEST_Line_SEQ")
@SequenceGenerator(name = "_REQUEST_Line_SEQ", sequenceName = "_REQUEST_Line_SEQ")
@Column(name = "REQUEST_LINE_ID")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "REQUEST_HEADER_ID", nullable = false)
public RequestHeaders getRequestHeaders() {
return RequestHeaders;
}
public void setRequestHeaders(RequestHeaders requestHeaders) {
this.RequestHeaders = requestHeaders;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "REQUEST_HEADER_FROM_STORE")
public RequestHeaders getRequestHeaderFromStore() {
return requestHeaderFromStore;
}
public void setRequestHeaderFromStore(RequestHeaders requestHeaderFromStore) {
this.requestHeaderFromStore = requestHeaderFromStore;
}
}
RequestHeader.java
@Entity(name = "RequestHeaders")
@Table(name = "REQUEST_HEADERS")
//@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class RequestHeaders extends Entity implements Serializable {
private long id;
// @JsonInclude(JsonInclude.Include.NON_EMPTY)
// @JsonIgnore
private DeliveryPoints DeliveryPoints;
@JsonIgnore
private Set<RequestLines> RequestLinesSet;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "_REQUEST_HEADERS_SEQ")
@SequenceGenerator(name = "_REQUEST_HEADERS_SEQ", sequenceName = "_REQUEST_HEADERS_SEQ")
@Column(name = "REQUEST_HEADER_ID")
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "DELIVERY_POINT_ID", nullable = false)
public DeliveryPoints getDeliveryPoints() {
return DeliveryPoints;
}
public void setDeliveryPoints(DeliveryPoints DeliveryPoints) {
this.DeliveryPoints = DeliveryPoints;
}
@OneToMany(mappedBy = "RequestHeaders", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@OnDelete(action = OnDeleteAction.CASCADE)
public Set<RequestLines> getRequestLinesSet() {
return RequestLinesSet;
}
public void setRequestLinesSet(Set<RequestLines> RequestLinesSet) {
this.RequestLinesSet = RequestLinesSet;
}
}
exception:
No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: domain.RequestLine["HeaderFromStore"]->.domain.RequestHeaders["DeliveryPoint"]->domain.DeliveryPoint_$$_jvst393_f["handler"])
notice that I used JsonIgnore and JsonInclude(on fields and class) but none of them doesn't work...
Edit:
I finally found this solution to avoid exception and ignoring unwanted properties.
I added this part of code to WebMvcConfig extends WebMvcConfigurerAdapter
class:
{
public MappingJackson2HttpMessageConverter jacksonMessageConverter(){
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
ObjectMapper mapper = new ObjectMapper();
//Registering Hibernate4Module to support lazy objects
mapper.registerModule(new Hibernate4Module());
messageConverter.setObjectMapper(mapper);
return messageConverter;
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
//Here we add our custom-configured HttpMessageConverter
converters.add(jacksonMessageConverter());
super.configureMessageConverters(converters);
}
But I have another problem now...all post requests will receive with null properties in request body ....for example in this code all properties of "requestHeaders" in input is null or empty!
@RequestMapping(value = "/requestHeader/", method = RequestMethod.POST, consumes = {"application/json"})
public ResponseEntity<Void> createRequestHeaders(@RequestBody RequestHeaders requestHeaders, UriComponentsBuilder ucBuilder) {
requestHeaders.setDeliveryPoints(deliveryPointsService.find(requestHeaders.getDeliveryPointsId()));
requestHeadersService.add(requestHeaders);
HttpHeaders headers = new HttpHeaders();
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
you should add each entities which have relation this annotation at the top of class definition.
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
details are explained here and here
I hope these solves your problem.
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