Chapter 35

Repositoryクラス

kazpgm
kazpgm
2022.01.11に更新

自動作成されたRepositoryクラスを説明する。

商品情報Repositoryクラス(ShohinRepository.java)

repository.ShohinRepository.java

package com.kaz01u.demo.repository;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import com.kaz01u.demo.entity.Shohin;

・DB操作用のRepositoryインターフェース。JpaRepository<>と、RepositoryCustom.java(条件検索Repositoryクラス)を継承している。
・商品情報のDBアクセスに使用しているメソッドです。
 ・ShohinRepositoryのsave()メソッド、flush()メソッド、delete()メソッドは何も定義しなくても動く。
 ・findByPrimaryKey()メソッド、findAllByOrderByProductsAsc()メソッドは定義している。
 ・finds(countSql, selectSql, argsList, pageable)メソッド、finds(selectSql, argsList)メソッドは、継承しているRepositoryCustom.javaに定義してあり、条件検索に使用している。特にfinds(countSql, selectSql, argsList, pageable)メソッドは検索結果がPageオブジェクトなので、商品情報一覧のページングに使用する。

public interface ShohinRepository extends JpaRepository<Shohin, String>, 
                                            RepositoryCustom {

・findByPrimaryKeyメソッド:主キー指定で抽出する。JPQLで、JPAで使用できるクエリを作成する。
・@Query:基本的な文法はネイティブなクエリと同じ。テーブルではなくEntityをベースに作成する点が異なる。 
・メソッドパラメーターに@Paramを付与することで、名前付きパラメーターを使用することができます。

    @Query("select s from Shohin s where s.products = :products")
    Shohin findByPrimaryKey(@Param("products") String products);

・findAllByOrderByProductsAscメソッド:products昇順ソートで全件抽出する。implもいらないし、SQLもいらない。けど、Repositoryにルールに従ってメソッドを定義しているので動く。

    public List<Shohin> findAllByOrderByProductsAsc();
}

条件検索Repositoryクラス(RepositoryCustom.java)

repository.RepositoryCustom.java
条件検索RepositoryクラスImpl(RepositoryCustomImpl.java)参照

条件検索RepositoryクラスImpl(RepositoryCustomImpl.java)

repository.impl.RepositoryCustomImpl.java

package com.kaz01u.demo.repository.impl;

import java.util.Collections;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import org.springframework.beans.factory.annotation.Autowired;

・Page:情報一覧ページングのための、情報一覧データとPageableを含んだオブジェクト。

import org.springframework.data.domain.Page;

・PageImpl:Pageのimpl

import org.springframework.data.domain.PageImpl;

・PageRequest:情報一覧ページングのため
・PageRequest.ofを使用してPageableを作成している。

import org.springframework.data.domain.PageRequest;

・Pageable:ページ検索に必要な情報が格納されている。

import org.springframework.data.domain.Pageable;
import com.kaz01u.demo.repository.RepositoryCustom;

・条件検索Repositoryのimplクラス

public class RepositoryCustomImpl implements RepositoryCustom {
    @Autowired
    EntityManager entityManager;

・Spring Data JPAを使用して動的SQL(JPQLのプリペアド・ステートメント)を検索し、結果をListオブジェクトとして戻す。

     @SuppressWarnings({ "rawtypes" })
    public List finds(String selectSql, List<Object> paras) {

・JPQLで、selectSql(データ取得SQL)からクエリを作成し、paras(バインドリスト)をプレースホルダにバインドし、実行する。

         //データ取得SQL
        Query query = entityManager.createQuery(selectSql);
        int i = 0;
        for (Object para:paras) {
            i++;
             //プレースホルダにバインド
            query.setParameter("p".concat(Integer.toString(i)), para);
        }        
        List recs = null;
        // 範囲指定にてデータ取得
        recs = query.getResultList();

・Listオブジェクトを戻す。

        //Listオブジェクトを戻す
        return recs;
     }

・Spring Data JPAを使用して動的SQL(JPQLのプリペアド・ステートメント)を、Pageableオブジェクトの範囲指定で検索し結果をPageオブジェクトとして戻す。

     @SuppressWarnings({ "rawtypes", "unchecked" })
    public Page finds(String countSql,String selectSql, List<Object> paras, Pageable pageable) {

・JPQLで、countSqlcountSql(全件数取得SQL)からクエリを作成する。

         //全件数取得SQL
         TypedQuery<Long> countQuery = entityManager.createQuery(
                 countSql,
                Long.class);

・JPQLで、selectSql(データ取得SQL)からクエリを作成し、paras(バインドリスト)をプレースホルダにバインドする。

         //データ取得SQL
        Query query = entityManager.createQuery(selectSql);
        int i = 0;
        for (Object para:paras) {
            i++;
             //プレースホルダにバインド
            countQuery.setParameter("p".concat(Integer.toString(i)) , para);
            query.setParameter("p".concat(Integer.toString(i)), para);
        }        

・全件数取得SQLクエリを実行し、全件数を取得する。

         //全件数取得
        long total = countQuery.getSingleResult().longValue();
        List recs = null;
        //Pageable pageable1 = PageRequest.of(0, 3);

・全件数が0以外の時、指定されたページ(pageable.getPageNumber())が全件数内に存在しないとき、最終ページを求めpageableとする。

         if (total != 0) {
            //ページが存在しない場合(最終ページで削除が起きた時起きることがある)
            if (((int) Math.ceil(total / (pageable.getPageSize() + 0.0))) < 
                        (pageable.getPageNumber() + 1)) {
                //最終ページ設定
                pageable = PageRequest.of(((int) Math.ceil(total / (pageable.getPageSize() + 0.0)) - 1), 
                        pageable.getPageSize());
            }           

・データ取得SQLクエリを、オフセット=pageable.getOffset()、レコード件数=pageable.getPageSize()で検索し、画面ページに表示するデータを取得する。

            query.setFirstResult((int)pageable.getOffset());
            query.setMaxResults(pageable.getPageSize());
            // 範囲指定にてデータ取得
            recs = query.getResultList();
        } else {

・全件数が0の時は 、空のリスト(Collections.emptyList())を取得する。

            recs = Collections.emptyList();
        }

・Pageオブジェクトを戻す。

        //Pageオブジェクトを戻す
        return new PageImpl (recs, pageable, total);
    }
}