SpringBoot - Spring Data Jpa Tuning

Continue to create, accelerate growth! This is the 4th day of my participation in the "Nuggets Daily New Plan · June Update Challenge", click to view the details of the event

Hibernate is very convenient in rapid development, but due to the complexity of sql in the query process and the N+1 query problem, it is not widely used in China. The following provides some tuning solutions for the N+1 query problem for reference only.

N+1 queries resulting from executing the query method

Criteria query

Use the fetch method in the Specification.toPredicate method. The writing method is as follows. After use, the query will be related to the query. However, for the attribute of the collection entity, incorrect data will be generated. It is not recommended to use this method to query the collection attribute.

   public Predicate toPredicate(Root<实体> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
    root.fetch("xxx");
    ...
    List<Predicate> predicates = new ArrayList<>();
    return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
   }
复制代码

Paging query needs to add a judgment, because paging query will check the count first

   public Predicate toPredicate(Root<实体> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
    if(criteriaQuery.getResultType().equals(实体.class)){
     root.fetch("xxx"); 
    }
    ...
    List<Predicate> predicates = new ArrayList<>();
    return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
   }
复制代码

root.fetch("xxx") where xxx is the specific attribute in the entity

Query with @Query

 @Query(value = "select d from Document d join fetch e.filetype ")
 List<User> findDocuments();

复制代码

Other: fetch all properties aggressively queries all properties, but collection properties do not automatically feach

 @Query(value = "select d from Document d fetch all properties")
 List<User> findDocuments();
复制代码

N+1 queries resulting from serialized entities

background note

Two configurations are explained before tuning:

//是否支持当实体在没有标记事务的方法中访问设置为lazy的属性
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
//使用jackson序列化时 实体属性为lazy时是否报错
spring.jackson.serialization.FAIL_ON_EMPTY_BEANS = false
复制代码

After the configuration is enabled, the property marked as Lazy will be called during the json serialization process of the entity returning to the front-end page, which will trigger a secondary query. If it is not turned on, the following two exceptions will not occur in the loop of serialization returning to the front end in the system.

//List属性:
 com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of 属性名: 实体.属性, could not initialize proxy - no Session
// 实体属性:
org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer];
复制代码

Solution

  • The best way for json serialization is to use @JsonIgnore to ignore collection properties and fetch entity properties.
  • Convert entity to vo in service

References

yq.aliyun.com/articles/23…

www.cnblogs.com/lcchuguo/p/…

www.java2s.com/Tutorials/J…

docs.jboss.org/hibernate/o…

Guess you like

Origin juejin.im/post/7102686972417671181