Spring Data JPA で遊んでみる 〜その7〜

名前付きクエリの話。JPAはもともとこの名前付きクエリをサポートしています。エンティティにつけるアレです。

@Entity
@NamedQuery(name = "Emp.findByUseNamedQuery", query = "select e from Emp e where e.id > ?1")
public class Emp {
// ..

これをSpring Data JPAリポジトリで利用するには、nameの指定にルールがあり、ドメインクラス名(エンティティ).メソッド名となるようにします。

この定義したクエリをリポジトリのメソッドで使うには以下のように、nameで指定したメソッド名で定義します。

List<Emp> findByUseNamedQuery(Long id);

これでfindByUseNamedQueryを実行すると、定義されているクエリが使用されます。

これ以外にもSpring Data JPA独自の @Query というアノテーションを使用出来ます。通常JPAでの名前付きクエリはエンティティクラス、またはXMLに定義します(XMLとかあまり使わないけど)が、@Query は リポジトリのメソッドに付与してクエリを定義できるものです。

@Query("select e from Emp e where e.id > ?1")
List<Emp> findByUseQueryAnnotation(Long id);

上記の様に、クエリ内の変数は、メソッドの引数の順番で処理することができますが、この方法はリファクタリング等、変更に非常に弱いので、名前付きでの指定も可能になっています。

こんなん

@Query("select e from Emp e where e.id > :id")
List<Emp> findByUseQueryAnnotationWithParam(@Param("id") Long id);

個々まで見てきたのでは、selectのみですが、updateもできます。

@Query("update Emp e set e.name = :name where e.id = :id")
@Modifying
//    @Modifying(clearAutomatically = false)
int setName(@Param("id") Long id, @Param("name") String name);

メソッドの戻り値定義と@Modifyingが必要です。@Modifyingが指定されているとEntityManager#clearが自動的に呼びされますが、呼び出したくない場合はclearAutomatically = falseを指定してください。

@Modifyingが正直よくわからなくてJPAのexecuteUpdate()になるやつで必要なのかなぁーと思ったのですが

@Query("delete from Emp e where e.id = :id")
int deleteById(@Param("id") Long id);

deleteは指定しなくても動きました。中身は覗いていない。

サンプルはこのへん。
https://github.com/yamkazu/springdata-jpa-example/tree/namedquery