Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spring mvc 4 + hibernate 5 lazy loading configuration

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);

    }
like image 933
faraa Avatar asked Oct 18 '17 09:10

faraa


1 Answers

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.

like image 140
Can G. Avatar answered Nov 15 '22 21:11

Can G.