web-dev-qa-db-ja.com

CrudRepository findOne()とJpaRepository getOne()の違い

私はgetOne()が遅延ロードされ、findOne()がエンティティ全体をすぐにフェッチすることを読みました。デバッグログを確認し、SQLサーバーで監視を有効にして、どのステートメントが実行されるかを確認しました。getOne()findOne()の両方が同じクエリを生成して実行していることがわかりました。ただし、getOne()を使用すると、値は最初はnullになります(もちろん、idは除きます)。

では、どちらの方法でもデータベースで同じクエリを実行するのであれば、なぜ一方を他方に使用する必要があるのでしょうか。私は基本的に、すべての子/属性を取得せずにエンティティをフェッチする方法を探しています。

EDIT1:

エンティティコード

ダオコード:

_@Repository
public interface FlightDao extends JpaRepository<Flight, Long> {
}
_

デバッグログfindOne()とgetOne()

EDIT2:

Chlebikのおかげで、問題を特定することができました。 Chlebikが述べたように、getOne()によってフェッチされたエンティティのプロパティにアクセスしようとすると、完全なクエリが実行されます。私の場合、デバッグ中に動作を確認していましたが、一度に1行ずつ移動していましたが、デバッグ中にIDEがデバッグ目的でオブジェクトのプロパティにアクセスしようとしたことを忘れていました(または少なくともそれが私は起こっていると思います)、デバッグは完全なクエリの実行をトリガーします。デバッグを停止してログを確認したところ、すべてが正常に見えます。

getOne() vs findOne()(このログはMySQL _general_log_から取得され、休止状態ではありません。

デバッグログ

デバッグログなし

8
prettyvoid

単なる推測ですが、「純粋なJPA」には、getReferenceというEntityManagerのメソッドがあります。また、IDのみが含まれるエンティティを取得するように設計されています。その使用は主に、エンティティ全体を取得する必要なしに参照が存在することを示すためでした。多分コードはもっと教えてくれるでしょう:

// em is EntityManager
Department dept = em.getReference(Department.class, 30);  // Gets only     entity with ID property, rest is null
Employee emp = new Employee();
emp.setId(53);
emp.setName("Peter");
emp.setDepartment(dept);
dept.getEmployees().add(emp);
em.persist(emp);

getOneが同じ目的を果たしていると思います。生成されたクエリがあなたが尋ねたものと同じであるのはなぜですか?まあ、JPA聖書のAFAIR-Pro JPA2 by Mike KeithとMerrick Schincariol-ほとんどすべての段落に「動作はベンダーに依存している」のようなものが含まれています。

編集:

自分で設定しました。最後に、あなたが何らかの方法でgetOneでフェッチされたエンティティに干渉すると(entity.getId()でも)、SQLが実行されました。プロキシを作成するためだけに使用している場合(たとえば、上記のコードに示すような関係インジケーターの場合)、何も起こらず、追加のSQLは実行されません。だから私はあなたのサービスクラスであなたがこのエンティティで何かをする(ゲッターを使って何かをログに記録する)と仮定します、そしてそれがこれら二つのメソッドの出力が同じに見える理由です。

サンプルコードを含むChlebikGitHub
とても役立つ質問#1
とても役立つ質問#2

9
Chlebik

IDでEntityを削除するとします。 SQLでは、次のようなクエリを実行できます。

"delete form TABLE_NAME where id = ?". 

そしてHibernateでは、最初にEntityのマネージドインスタンスを取得し、それをEntityManager.removeメソッドに渡す必要があります。

Entity a = em.find(Entity.class, id);
em.remove(a);

しかし、この方法では、削除する前に、データベースから削除するEntityをフェッチする必要があります。それは本当に必要ですか?

メソッドEntityManager.getReferenceは、データベースをクエリしてエンティティのプロパティを設定せずにHibernateプロキシを返します。返されたプロキシのプロパティを自分で取得しようとしない限り。

メソッドJpaRepository.getOneは、EntityManager.getReferenceメソッドの代わりにEntityManager.findメソッドを使用します。したがって、マネージオブジェクトが必要であるが実際にデータベースにクエリを実行する必要がない場合は、JpaRepostory.getOneメソッドを使用して不要なクエリを削除することをお勧めします。

4
chubock

データベースに存在するIDでエンティティをクエリすると、findOne(id)を使用するとnullが取得され、getOne(id)を使用するとオブジェクトがnullフィールドに取得されるため、getOne(id) == nullは期待どおりに機能しません。

0
Justas

特定のIDのテーブルにデータが見つからない場合、findOneはnullを返しますが、getOneはjavax.persistence.EntityNotFoundExceptionをスローします。どちらにも独自の長所と短所があります。以下の例をご覧ください。

  1. 見つからないデータが失敗のケースではない場合(たとえば、データが削除され、成功するとデータがnullになるかどうかを確認するだけの場合)、findOneを使用できます。
  2. 別のケースでは、getOneを使用できます。

結果がわかっている場合は、要件に応じて更新できます。

0
Kailas Andhale