Spring Boot + Reactで記事投稿アプリを作成予定｜Repositoryを実装・解説してみた

※学習中のため間違っている箇所があるかもしれません
# はじめに
今回は`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リポジトリー
```java
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リポジトリー
```java
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リポジトリー
```java
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が適用されます。
```java
Pageable pageable = PageRequest.of(0, 10); // 1ページ目・10件
List<Article> articles = articleRepository.findAllByOrderByCreatedAtDesc(pageable);
```

# まとめ
今回は`Repository`を実装していきました。
`JpaRepository`を継承することでCRUDの基本的な動きを持たせることができます。

`Repository`はデータベースとのやり取りをする重要なレイヤーです。
基本をしっかりと押さえておきましょう。

次回以降の予定
- Service
- Controller

今回の記事が少しでもspring boot初学者の助けになれば幸いです。

# 参考
今回は「Repository」に焦点を当てた内容ですが、  
初回記事である「[機能整理と設計メモ](https://qiita.com/suica1010/items/1910e82dea147c19cddb)」もあわせてご覧ください。
[github:MNawata-coding](https://github.com/MNawata-coding)

[前：Spring Boot + Reactで記事投稿アプリを作成予定｜Entity・三層アーキテクチャ学習ログ](https://qiita.com/suica1010/items/7e7a200a0fef2338d94d)
[次：Spring Boot + Reactで記事投稿アプリを作成予定｜Service、DTOの機能を洗い出してみた](https://qiita.com/suica1010/items/cc8439cd5b83f04da167)