JPA照会問題の探究
引用する
最近、実体図に関するブログを見て、海外のお兄さんは
ちょうど実体図は前に華軟を書いたときに勉強したことがありますが、理解していないだけで、プロジェクトで実際に応用していないので、ちょうどこの機会に勉強してみました.
実際には、
今日発見されたのは、
探究する
エンティティ関係
最も簡単な教務システムモデル、教師、クラス、学生.
ベースデータ
二人の教師、一人の教師は二人のクラスを連れて、一人のクラスの中で二人の学生です.
単一テーブルクエリ
最も簡単なクエリ文は、
単純な単一テーブルクエリでは、ベースフィールド
普通のコードを見ていると、みんな書いたはずですが、実は中には学問があります.
テスト環境
テスト環境の実行エラー、
ここでは、ユニットテストにおける
ソリューション
どちらのソリューションもベストプラクティスではありません.
事務を加える
プラストランザクションは
原因は調べられなかったが、ここで推測した.
トランザクションの正常な実行を維持するために、トランザクションのコミットとロールバックは
これは実現できますが、これは最悪の解決策です.
エンティティの注釈に加えられているので、異なる方法で使用し、関連していないエンティティを使用しないで、一度にすべて調べます.
複数対複数注釈、デフォルト
1対のマルチ注釈、デフォルト
複数対1注釈、デフォルト
1対1の注釈、デフォルト
データベースの分野では、
同時に、性能の面では、
実行環境
同じコードを
その後、正常に動作し、使用するときにデータベースをクエリーし、
問題の再現
私は華軟の中で
そして
私が考えていたのは、方法の間で相手を伝え合って、
それから私は試み始めて、
総括と思考
ネット上には、複数の文の性能が悪いという文章がある.教師が学生とクラスを持ち出すには、
私は自分の観点を述べます:1対がどれだけ遅いかは、どれだけの文を実行したからではなく、データベースが1対多、多対多を調べるのが遅いからです.
実体図を使用して
実体図は、私が教師を必要とする
最近、実体図に関するブログを見て、海外のお兄さんは
JPA
の実体間の関連は何度もクエリーを実行し、データ量が大きいと性能が非常に悪いと言っています.ちょうど実体図は前に華軟を書いたときに勉強したことがありますが、理解していないだけで、プロジェクトで実際に応用していないので、ちょうどこの機会に勉強してみました.
実際には、
jpa
のプロジェクトを構築し、jpa
がどのように検索されているのかを実際にテストします.今日発見されたのは、
Spring Boot
が2.1.5
に更新されたことです.探究する
エンティティ関係
最も簡単な教務システムモデル、教師、クラス、学生.
ベースデータ
二人の教師、一人の教師は二人のクラスを連れて、一人のクラスの中で二人の学生です.
単一テーブルクエリ
Iterable teachers = teacherRepository.findAll();
for (Teacher teacher : teachers) {
System.out.println(teacher.getName());
}
最も簡単なクエリ文は、
findAll
の後にname
フィールドを取得します.Hibernate: select teacher0_.id as id1_2_, teacher0_.name as name2_2_ from teacher teacher0_
単純な単一テーブルクエリでは、ベースフィールド
id
とname
が検出されます.OneToMany
複数テーブル関連クエリーIterable teachers = teacherRepository.findAll();
for (Teacher teacher : teachers) {
System.out.println(teacher.getName());
for (Klass klass : teacher.getKlasses()) {
System.out.println(klass.getName());
for (Student student : klass.getStudents()) {
System.out.println(student.getName());
}
}
}
普通のコードを見ていると、みんな書いたはずですが、実は中には学問があります.
テスト環境
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.yunzhiclub.jpa.entity.Teacher.klasses, could not initialize proxy - no Session
テスト環境の実行エラー、
no session
.Hibernate
では、すべてのデータベースに対する操作がsession
で実行される必要があります.これは、データベースの直接操作の代わりに、データベースのエージェントオブジェクトとして理解することができます.Hibernate
のSession
とJDBC
のConnection
の違いについては、このお兄さんの答えを参考にすることができます:What is the difference between a Session and a Connection in Hibernate?-StackOverflow OneToMany
はデフォルトで不活性ロードなので、使用するときにクエリーします.ここでは、ユニットテストにおける
session
の役割ドメインが1行しかないことを示しています.findAll
以降session
は閉まっています.ソリューション
どちらのソリューションもベストプラクティスではありません.
事務を加える
プラストランザクションは
session
閉鎖の問題を解決することができます.ここではユニットテストであり、トランザクションも必要であるため、ユニットテストでの不活性なロードによる問題は、トランザクションを追加する方法で実現されます.原因は調べられなかったが、ここで推測した.
Hibernate
とはあくまで原生のjdbc
メソッドをカプセル化したものであり,原理は以下のようなコードを生成することである.Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
// do some work
...
tx.commit();
} catch (Exception e) {
if (tx != null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
トランザクションの正常な実行を維持するために、トランザクションのコミットとロールバックは
session
の有効範囲内にあることがわかります.言い換えれば、session
はトランザクションが完了した後に閉じられ、トランザクションの管理の下で実行する方法で、session
を正常に使用することができます.EAGER
ロードEAGER
は急いで、一度にすべて調べて、ここもでたらめに翻訳する勇気がなくて、意会はすぐです./**
*
*/
@OneToMany(mappedBy = "teacher",fetch = FetchType.EAGER)
private List klasses = new ArrayList<>();
/**
*
*/
@OneToMany(mappedBy = "klass", fetch = FetchType.EAGER)
private List students = new ArrayList<>();
これは実現できますが、これは最悪の解決策です.
エンティティの注釈に加えられているので、異なる方法で使用し、関連していないエンティティを使用しないで、一度にすべて調べます.
と
のクエリは、データテーブル全体を編集する必要があることを知っています.そのため、調べにくいです.EAGER
に変更すると、深刻なパフォーマンスの問題が発生します.Hibernate
注記設計Hibernate
対の注釈の設計を見てみましょう.複数対複数注釈、デフォルト
LAZY
:1対のマルチ注釈、デフォルト
LAZY
:複数対1注釈、デフォルト
EAGER
:1対1の注釈、デフォルト
EAGER
:データベースの分野では、
Hibernate
は牛に違いない.牛がこのように設計されている以上、私たちも自然に従うべきだ.同時に、性能の面では、
、
のクエリー性能がよく、
、
のクエリー性能はそれほどよくないことも理解されるはずです.実行環境
同じコードを
Service
に入れ、api
インタフェースを作成します.その後、正常に動作し、使用するときにデータベースをクエリーし、
no session
のエラーは発生しなかったので、ここでは、Service
のクエリー方法では、session
の役割ドメインがテストよりも広いと推測します.問題の再現
私は華軟の中で
no session
の問題に遭遇しました.どうやって現れたのですか.loadUserByUsername
メソッドのうちusername
に従ってuser
を調べ、user
メソッドをcreateUser
メソッドに渡して処理し、user
メソッドをgetAllAuthMenuByUser
メソッドに渡してこのユーザのすべてのライセンスメニューを取得する.そして
no session
になりました.私が考えていたのは、方法の間で相手を伝え合って、
session
がなぜか閉まって、それから間違ったことを報告しました.createUser
のコードをloadUserByUsername
に入れると正常だったのを覚えていますが、変更が長すぎて、このように変更しませんでした.最後にメソッドに加えたトランザクション.それから私は試み始めて、
Service
の間で互いに相手を伝え始めました.残念ながら、どのように伝えても使いやすいです.問題の再現に失敗したのは、Spring Security
と何の関係があるのか分からない.総括と思考
ネット上には、複数の文の性能が悪いという文章がある.教師が学生とクラスを持ち出すには、
SQL
文を複数実行する必要があり、クエリーの効率化に最適化できます.私は自分の観点を述べます:1対がどれだけ遅いかは、どれだけの文を実行したからではなく、データベースが1対多、多対多を調べるのが遅いからです.
実体図を使用して
SQL
に最適化できても、データベースがどのように1対多、多対多を調べるか、どのように調べるかは、文が少なく見えるだけで、性能は実際には向上していないと思います.実体図は、私が教師を必要とする
name
、クラスのname
、学生のname
を配置し、私たちのデータベースで学んだように、私のこの方法を調べてみました.select teacher.name, klass.name, student.name where xxxxx;
Java
の盛んな発展に伴い、Java
の性能はC++
に及ばないが、運行効率も極めて高い.効率のボトルネックか、データベースかを見てみましょう.Redis
はあまりありませんか?