創造を続け、成長を加速させましょう!「ナゲッツデイリーニュープラン・6月アップデートチャレンジ」に参加して4日目です。クリックしてイベントの詳細をご覧ください。
Hibernateは迅速な開発に非常に便利ですが、クエリプロセスのSQLの複雑さと、N + 1クエリの問題のため、中国では広く使用されていません。以下に、参照用のN+1クエリ問題のチューニングソリューションをいくつか示します。それだけ。
クエリメソッドの実行から生じるN+1クエリ
基準クエリ
Specification.toPredicateメソッドでfetchメソッドを使用します。書き込みメソッドは次のとおりです。使用後、クエリはクエリに関連付けられます。ただし、コレクションエンティティの属性については、誤ったデータが生成されます。お勧めしません。このメソッドを使用してコレクション属性を照会します。
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()]));
}
复制代码
ページングクエリは最初にカウントをチェックするため、ページングクエリは判断を追加する必要があります
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")ここで、xxxはエンティティ内の特定の属性です
@Queryを使用したクエリ
@Query(value = "select d from Document d join fetch e.filetype ")
List<User> findDocuments();
复制代码
その他:すべてのプロパティをフェッチすると、すべてのプロパティが積極的にクエリされますが、コレクションのプロパティは自動的に偽造されません
@Query(value = "select d from Document d fetch all properties")
List<User> findDocuments();
复制代码
シリアル化されたエンティティから生じるN+1クエリ
背景メモ
チューニングの前に、2つの構成について説明します。
//是否支持当实体在没有标记事务的方法中访问设置为lazy的属性
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
//使用jackson序列化时 实体属性为lazy时是否报错
spring.jackson.serialization.FAIL_ON_EMPTY_BEANS = false
复制代码
構成を有効にすると、フロントエンドページに戻るエンティティのJSONシリアル化プロセス中にLazyとマークされた属性が呼び出され、セカンダリクエリがトリガーされます。オンにしない場合、システムのフロントエンドに戻るシリアル化のループで次の2つの例外は発生しません。
//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];
复制代码
解決
- jsonシリアル化の最良の方法は、@ JsonIgnoreを使用してコレクションのプロパティを無視し、エンティティのプロパティをフェッチすることです。
- エンティティをサービス中のvoに変換します