※学習中のため間違っている箇所があるかもしれません
はじめに
今回はRepository
に関して実装していきます。
Repository
はデータベースとのやり取りを行うレイヤーで、CRUD実装する際に重要な役割を果たします。
Repository
層に関して簡単に解説していきます。
Repository
Repository
は主にデータベースとのやり取りで、検索(SELECT)、削除(DELETE)、更新(UPDATE)、保存(INSERT)を行うためのクラスです。
基本的なCRUD機能はインターフェースを継承するだけで利用でき、必要なクエリのみメソッド定義で追加します。
@Repository
はSpringのコンポーネントスキャンによってBean
登録される、例外(例:SQLException)をSpringの例外階層に変換する役割も担う。
※Bean/DIに関しては次回詳細に記載します。
RepositoryはDBとのやり取りを担当しますが、それと同時に、
「データアクセスの実装をインターフェースに隠蔽し、Service層から抽象的に扱えるようにする」役割も担います。
→ この分離により、テストやメンテナンスが容易になります。
主にService
から呼び出され、DBとのやり取りを担当する責務を担います。
その後Entityとして返却され、Service
へ返却します。
実装例
実装するリポジトリ
- 最新記事一覧
- 閲覧数順の記事取得
- ライク数順の記事取得
- 特定ユーザーの記事一覧
- 検索結果
- ユーザー一覧・実装不要
- 登録、削除、更新・実装不要
- タグ一覧・実装不要
JpaRepositoryを継承することで、基本的なCRUD操作(登録・取得・削除・更新)は実装不要になります
articleリポジトリー
import java.util.List;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import com.example.spring_article_java_api.entity.Article;
@Repository
public interface ArticleRepository extends JpaRepository<Article, Integer> {
//基本的な保存・更新・削除などはJpaRepositoryから継承されます。
//新着順取得
List<Article> findAllByOrderByCreatedAtDesc();
//特定ユーザーの記事一覧
@Query("SELECT a FROM Article a WHERE a.userId = :userId ORDER BY a.createdAt DESC")
List<Article> findByUserId(@Param("userId") int userId, Pageable pageable);
//閲覧数順記事一覧
List<Article> findAllByOrderByViewCntDesc(Pageable pageable);
//like数順記事一覧
List<Article> findAllByOrderByLikeCntDesc(Pageable pageable);
//検索結果一覧
List<Article> findByTitleContainingIgnoreCase(String keyword, Pageable pageable);
}
tagリポジトリー
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.example.spring_article_java_api.entity.Tag;
@Repository
public interface TagRepository extends JpaRepository<Tag, Integer> {
//基本的な動作はJpaRepositoryから継承
}
userリポジトリー
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.example.spring_article_java_api.entity.User;
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
//基本的な動作はjparepositoryから継承
}
※今回は@Query
を使用しなくても、命名規則で実現可能ですが
学習用に@Query
を使用しています
解説
Repositoryの命名規則
@Repository
では抽象メソッドの命名規則により、JPAが自動でJPQL
を発行してくれます。
構文を以下に記載します。
findBy[検索条件][OrderByXXXDesc](例:findByUserIdOrderByCreatedAtDesc)
簡単な取得処理だとこのように記載することで、@Query
を使用せずにJPQL
を発行することができます。
※命名規則で表現できないような複雑な結合や集計、サブクエリが必要な場合は、@Query
を使うことで柔軟なクエリ設計が可能になります。
JPQL
JPQL
とはエンティティクラスを対象にしたJPA仕様で定義されているクエリ言語です。
アノテーションにJPQL
を記述して実行することで、JPAが内容を解釈し、
アノテーションやO/Rマッピングの情報をもとに、SQL文を組み立てます。
@Queryでは、JPQLを記載することでエンティティベースのクエリ設計が可能になり、
JPAの機能(キャッシュ、永続化コンテキスト)との連携を保ちつつ、柔軟なデータ取得ができます。
書き方
SELECT エイリアス FROM エンティティ名 エイリアス WHERE エイリアス.変数名
JpaRepository
JpaRepository
は@Repository
クラスに継承することで、基本的なDB操作を行うことができます。
以下継承される代表的なメソッドです。
- getReferenceById(ID id):指定されたidを持つEntityへの参照を返却する
- save(S entity):CrudRepositoryから継承、指定されたエンティティを保存します
- delete(T entity):CrudRepositoryから継承、指定されたエンティティを削除します
- findAll():型のすべてのインスタンスを返します
上記継承されるメソッドを使用することでCRUDの削除、検索、更新、登録といった基本的な動きを持たせることができます。
@Query
@Query
はJPQL(エンティティベースのクエリ言語)を記述するためのアノテーションです。
※native SQLを使いたい場合は、nativeQuery = true
を指定します。
SQLクエリを記載し、呼び出すことでクエリを実行することができる。
※@Query
内ではテーブル名ではなくエンティティ名を使用する必要があります。
@Param
SQLクエリで使用したパラメータにバインドするためのアノテーション。
今回は:userId
に値をバインドするために使用している。
Pageable
ページネーションに関するプロパティ設定を管理します。
Pageable
はページネーション処理を行うためのインターフェースです。Spring Data JPAでは、Repositoryのメソッドに引数として渡すだけで、自動的にLIMIT/OFFSETが適用されます。
Pageable pageable = PageRequest.of(0, 10); // 1ページ目・10件
List<Article> articles = articleRepository.findAllByOrderByCreatedAtDesc(pageable);
まとめ
今回はRepository
を実装していきました。
JpaRepository
を継承することでCRUDの基本的な動きを持たせることができます。
Repository
はデータベースとのやり取りをする重要なレイヤーです。
基本をしっかりと押さえておきましょう。
次回以降の予定
- Service
- Controller
今回の記事が少しでもspring boot初学者の助けになれば幸いです。
参考
今回は「Repository」に焦点を当てた内容ですが、
初回記事である「機能整理と設計メモ」もあわせてご覧ください。
github:MNawata-coding
前:Spring Boot + Reactで記事投稿アプリを作成予定|Entity・三層アーキテクチャ学習ログ
次:Spring Boot + Reactで記事投稿アプリを作成予定|Service、DTOの機能を洗い出してみた