JPAがcreateNamedQueryを使用する理由
-
08-07-2019 - |
質問
私は、DAOレイヤーをHibernate APIの使用から純粋なJPA API実装の使用に変更するプロセスにいます。推奨される方法は、エンティティマネージャからcreateNamedQueryを使用することです。名前付きクエリは、モデル/エンティティクラスの注釈に保存されます。これは私には意味がありません。モデルオブジェクトでJPAクエリを定義し、DAOで使用するのはなぜですか。 DAO自体からcreateQueryを使用して、DAOでクエリを定義するだけでなく、DAO自体で名前付きクエリを定義するだけでも、より意味がありませんか?
JPA APIを使用してDAOレイヤーを実装した人は、クエリをどのように定義しましたか?
解決
名前付きクエリを使用します。
その理由は2つあります:
- これらは、ランダムなcreateQuery()呼び出しでコードに散らばるのではなく、より中心的な場所に配置します。そして
- ビルドプロセスはクエリを検証できます(本当に便利です)。
他のヒント
Spring Data JPA をご覧ください。手動で実行を実装しなくても、インターフェイスを簡単に定義してクエリを実行できます。
エンティティ:
@Entity
@NamedQuery(id="User.findByLastname" query="from User u where u.lastname = ?1")
public class User implements Persistable<Long> {
@Id
private Long id;
private String username;
private String lastname;
private int age;
}
リポジトリ:
public interface UserRepository extends CrudRepository<User, Long> {
// Will trigger the NamedQuery due to a naming convention
List<User> findByLastname(String lastname);
// Will create a query from the methodname
// from User u where u.username = ?
User findByUsername(String username);
// Uses query annotated to the finder method in case you
// don't want to pollute entity with query info
@Query("from User u where u.age > ?1")
List<User> findByAgeGreaterThan(int age);
}
セットアップ:
EntityManager em = Persistence.getEntityManagerFactory().createEntityManager();
JpaRepositoryFactory factory = new JpaRepositoryFactory(em);
UserRepository repository = factory.getRepository(UserRepository.class);
ご覧のように、メソッドから実行されるクエリを派生させるさまざまな方法から選択できます。メソッド名から直接派生することは、おそらく @NamedQuery
(JPA標準)または @Query
(Spring Data JPAアノテーション)依存から選択する単純なクエリには適しています基準をどの程度守りたいかについて。
Spring Data JPAは、データアクセスレイヤー実装のさまざまなコーナーでサポートを提供し、メソッドのカスタム実装を提供し、Springとうまく統合します。
クレトスの経験とはまったく逆の経験がありました。何の利点も見られず、使いにくいと感じました。些細なクエリはどこで定義しても違いはありませんが、些細でないクエリは通常、単一のエンティティに関連付けるのは困難ですが、ビジネス指向のメソッドでは簡単です。
DAOで多かれ少なかれ洗練されたインフラストラクチャ(再利用と一貫性のため)を使用する場合、名前付きクエリの使用は実装と読みやすさの両方を複雑にする傾向があり、明らかな利点はありません。
ビルドプロセスによるクエリの検証は興味深いですね-私はそれが本当に何を意味するのかをもっと知りたいです...すべてのDAOメソッドは理にかなっている限りユニットテストされるので、私のクエリはエラーのマージンをほとんど残しません。
どこでも名前付きクエリを使用するだけでなく、クエリがほとんど使用されない場合など、必要に応じて構築するとより効率的になる場合があるなど、それらが適切でない場合があります。
名前付きクエリは複雑になり、頻繁に実行される場合に意味があります。
[更新済み]
代わりに、マッピング時に名前付きクエリを作成できます。
andの力を受け入れます:)モデルに入れる意味のあるクエリがある場合は、そうします。そうしないなら、しないでください。 「なぜJPSでDAOを書いているのですか?」答えが「データベースからコードを分離する」場合です。これは、JPAを実装するライブラリによって行われます。答えが「コードを私が物事を永続化する方法の変更から隔離すること」である場合、JPAは異なる実装を許可することでそれを行います。 複雑なクエリにはクエリオブジェクトを使用しますが、可能な場合は名前付きクエリを使用します。名前付きクエリがコンパイルされるという事実が気に入っているので、バグの発見がはるかに速くなっています。 DAOレイヤーがありません。