SpringデータJPA

40042 ワード

Spring data JPA
これはSpringが提供するプロジェクトで、共通のインタフェースを通じてCRUDを解決します.
実装体はSpringデータJPAによって生成され注入され,開発者は直接JPAインタフェースを実現する必要はない.
public interface MemberRepository extends JpaRepository<Member, Long> {}
ばねデータこうじ
Jpa Repositoryを継承および使用できる主な方法
T=エンティティ
ID=エンティティの識別子タイプ
S=エンティティおよびそのサブアイテム
save(S)、新しいエンティティを保存し、すでに存在する場合は変更
delete(T)、エンティティを削除
findOne(ID)エンティティの検索
エージェントによるgetOne(Id)エンティティの表示
findAll(...) すべてのエンティティのクエリー、ソート、またはページング条件をパラメータとして指定します.
エンティティに識別値がない場合、save()は新しいエンティティと判断してpersistを呼び出し、ない場合はmergeを呼び出します.
クエリーメソッド機能
  • メソッド名を使用してクエリー
  • を作成
  • メソッド名でJPA NamedQuery
  • を呼び出す
    クエリーがクエリー・ライブラリ・インタフェースで直接定義された
  • @Queryデモ
    1.メソッド名を使用したクエリーの定義
    public interface MemberRepository extends Repository<Member ,Long> {
    	List<Member> findByEmailAndName(String email, String name);
    }
    findByEmailAndNameメソッドを実行すると、SpringデータJPAはメソッド名を解析することによってJPQLを生成および実行します.
    select m from Member m where m.email =?1 and m.name =?2
    Spring Data JPAの公式文書に記載されている表のルールに従って命名すると、Spring Data JPAは独自にJPQLを生成します.
    キーワードの例JQCLの例AndfindByLastname AndFirstname...where x.lastname =?1 and x.firstname = ?2OrfindByLastnameOrFirstname...where x.lastname =?1 or x.firstname = ?2Is, EqualsfindByFirstname , findByFirstnamels, findByFirstnameEqauls...where x.firstname = ?1BetweenfindByStartDateBetween...where x.startDate between 1? and 2?LessThanfindByAgeLessThan...where x.age < ?1GreaterThanfindByAgeGreaterThan... where x.age >1LessThanEqualfindByAgeLEssThanEqual...where x.age <= ?1AfterfindByStartDateAfter...where x.startDate > ?1BeforefindByStartDateBefore...where x.startDate < ?1IsNullfindByAgeIsNull...where x.age is nullIsNotNull, NotNullfindByAge(is)NotNull...where x.age is not nullLikefindByFirstnameLike...where x.firstname like = ?1NotLikefindByFirstnameNotLike...where x.firstname like not = ?1StartingWithfindByFirstnameStartingWith...where x.firstname like = ?1 (parameter bound with prepended %)EndingWithfindByFirstnameEndingWith...where x.firstname like = ?1 (parameter bound with prepended %)OrderByfindByAgeOrderByLastnameDesc...where x.age = ?1 order by x.lastname descNotfindByLastnameNot...where x.lastname <> ?1InfindByAgeIn(Collection age)...where x.age in ?1NotInfindByAgeNotIn(Collection age)...where x.age not in ?1TruefindByActiveTrue...where x.active = trueFalsefindByActiveFalse...where x.active = false
    メソッド名を使用してJPA NamedQueryを呼び出す
    メソッド名でJPA NamedQueryを呼び出す機能を提供します.
    // @NamedQuery 에노테이션으로 네임드 쿼리 정의
    
    @Entity
    @NamedQuery(
    	name="Member.findByUsername"
    	query="select m from Member m where m.username =  :username
    )
    public class Member {...}
    
    
    // 스프링 데이터 JPA에서 네임드 쿼리 사용
    
    public interface MemberRepository extends JpaRepository<Member, Long> { // 여기 선언한 Member 도메인 클래스
    
    	List<Member> findByUsername(@Param("username") String username );
    }
    Spring Data JPAは、宣言された「ドメインクラス+.(ポイント).メソッド名」を使用してNamedQueryを検索して実行します.
    上記の例はメンバーです.findByUsername
    @Param名前ベースのパラメータのバインドに使用
    @Queryプレゼンテーションを使用して、Repositoryインタフェースでクエリーを直接定義
    @Queryプレゼンテーションを使用して、直接ライブラリにメソッドを定義します.
    無名氏クエリとも呼ばれます.
    
    public interface MemberRepository extends JpaRepository<Member, Long> {
    	@Query("select m from Member m where m.username = ?1")
        Member findByusername(String username);
    
    // 네이티브 SQL 사용하려면  nativeQuery= true를 사용한다. 참고로 네이티브 SQL은 위치기반 파라미터가 0부터 시작한다.
    	@Query(value ="SELECT * FROM MEMBER WHERE USERNAME = ?0 , nativeQuery= true) ;
    	Member findByUsernameForNative(@Param("username") String username );
    }
    バインドパラメータ
    Spring Data JPAは、位置ベースのパラメータバインドと名前ベースのパラメータバインドを同時にサポートします.
    既定値は、位置ベースのパラメータバインドです.
    名前ベースのパラメータセミエンコーディングを行うには
    パラメータに@Paramコメントを追加します.
    @Query("select m from Member m where m.username = :username")
    Member findByUsernameForNative(@Param("username") String username );
    
    クエリーの一括変更
    @Modifying
    @Query("update Product p set p.price =  p.price  * 1.1 where p.stockAmount < :stockAmount")
    	int bulkPriceUp(@Param("stockAmount") String stockAmount);
    主体性の変更、クエリーの削除には@Modifyingコメントを使用します.
    マスター・クエリーの実行後に永続コンテキストを初期化する場合は、「@自動=true」オプションを指定します.
    戻りタイプ
    ばねデータJPAは、結果が1つ以上の場合は集合インタフェースを使用し、そうであれば半種類を指定する柔軟な戻りタイプをサポートします.
    結果がない場合、コレクションは空のコレクションを返しますがnullで、
    ただし、2つ以上のクエリを行うと、NonUniqueResultExceptionが発生します.
    改ページとソート
    Spring Data JPAでは、クエリー・メソッドのページングとソートに使用する2つの特殊なパラメータが用意されています.
    Sort型パラメータ:ソート機能
    Pageableパラメータ:ページング機能(内部sortを含む)
    Pageableを使用すると、タイプを返してListまたはPageタイプが取得されます.
    Pageはcountクエリーを呼び出してデータ全体をクエリーします.
    Page<Member> findByName(String name , Pageable pageable); // count 쿼리 사용
    
    List<Member> findByName(String name , Pageable pageable); // count 쿼리 x
    
    List<Member> findByName(String name , Sort sort);
    検索条件:姓金で始まるメンバー
    ソート条件:降順名
    ページング条件:1ページ目、1ページあたり10件
    // 인터페이스 정의
    public interface MemberRepository extends JpaRepository {
    Page findByNameStartWith(String name , Pageable pageable);
    }
    //使用
    PageRequest pageRequest = new PageRequest(0,10, new Sort(Direction.DESC, "name"));
    Page result = memberRepository.findByNameStartWith(“kim”,pageRequest);
    List members = result.getContent();//クエリーのデータ
    int totalPage = result.getTotalPages();//合計ページ数
    boolean hasNextPage = result.hasNextPage();
    ## 힌트
    
    ```java
    @QueryHints(value ={ @QueryHint(name = "org.hibernate.readOnly", value="true")}, forCounting = true)
    Page<Member> findByName(String name , Pageable pageable);
    forcountingプロパティは、戻りタイプとしてPageインタフェースを使用する場合、後続の呼び出しのページングカウントクエリーにもクエリー・プロンプトを適用します.
    オプションを設定します.
    詳細
    本域主導設計は明細の概念を紹介する.
    Spring Data JPAは、JPA Criteriaであり、この概念の使用をサポートしています.
    明細を理解するためのコア単語は述語であり,単純に真または偽と評価される.
    これはANO、ORなどの演算子に組み合わせることができます.
    たとえば、検索データの各制約条件を述語と呼ぶことができます.
    Spring Data JPAは述語をSepcificationクラスとして定義します.
    Sepcificationは複合モードで構成されており,複数のSepcificationを組み立てることができる.
    したがって、複数の検索条件を組み合わせて、新しい検索条件を作成することができます.
    詳細機能を使用すると、JpaSepcificationExcutorインタフェースを継承できます.
    public interface JpaSpecificationExecutor <T> {
    	T findOne(Sepcification <T> spec);
        List<T> findAll(Sepcification<T> spec);
        Page<T> findAll(Sepcification<T> spec, Pageable pageable);
        List<T> findAll(Sepcification<T> spec, Sort sort);
        long count(Sepcification<T> secp);
    
    
    public interface OrderRepository extends JpaRepository<Order,Long> , JpaSpecificationExecutor<Order> {
    }
    JpaSpecificationExecutionのメソッドは、条件を検索するためにSepcificationをパラメータとして使用します.
    public List<Order> findOrders(String name) {
    	List<Order> result = orderRepository.findAll(
        	where(memberName(name)).and(isOrderStatus())
       );
       
       return result;
    )  
    カスタムリポジトリの実装
  • は、方法
  • を直接実装するためのカスタムインタフェースを作成する.
    public interface MemberRepositoryCustom {
    	public List<Member> findMemberCustom();
    }
  • カスタムインタフェースを実装するクラスの作成
    ルール)リポジトリ名+Impl,Spring Data J.P.Aを使用してカスタムインプリメンテーションクラスと見なす必要があります.
  • public class  MemberRepositoryCustomImpl implements MemberRepositoryCustom {
    	public List<Member> findMemberCustom() {...}
    }
    最後にspringが提供するインタフェースとカスタムインタフェースを一緒に実現すればよい.
    public interface MemberRepository extends JpaRepository<Member, Long> , MemberRepositoryCustom {
    }
    WEB拡張
    使いやすい機能
    1.ドメインクラスコンテンツバッファを識別子としてドメインクラスに直接バインドします.
    2.ページングとソート機能
    1.ドメインクラス変換器機能
    HTTPパラメータに渡されたエンティティのIDを使用して、エンティティオブジェクトを検索してバインドします.
    ex/member/updade?id=1
    // 도메인 클래스 ( 컨버터 기능 사용 x )
    @Controller
    public class MemberController {
    
    @AutoWired
    MemberRepository memberRepository;
    
    @PostMapping("/member/updade")
    public class memberUpdate(@RequestParam("id") Long id, Model model) {
    	Member member = memberRepository.findOne(id);
    		...
    	}
    }
    
    
    // 도메인 클래스 ( 컨버터 기능 사용)
    @Controller
    public class MemberController {
    
    @AutoWired
    MemberRepository memberRepository;
    
    @PostMapping("/member/updade")
    public class memberUpdate(@RequestParam("id") Member member, Model model) {
        	soutv(member.getName());
    	}
    }
    ただし、ここからのエンティティを変更しても実際のデータは変更されません.
    ページングとソート機能
    @RequestMapping(value ="/members")
    public String list(Pageable pageable , Model model){
    	Page<Member> page = memberService.findMember(pageable);
    
    	model.addAttribute("members", page.getContent());
    
    	return "member/memberList";
    }
    パラメータでPageableを受け取ったことを確認できます.Pageableは、次の要求パラメータ情報によって作成されます.
    page:現在のページ0から
    size ; 1ページに表示するデータの数
    sort:ソート結合の定義
    ex)/members?page=0&size=20&sort=name,desc&sort=address.city
    接頭辞
    使用するページ情報が2つ以上ある場合は@Qualifier Anoeを使用します.
    public String list(
    	@Qualifier("member") Pageable memberPageable,
    	@Qualifier("order") Pageable orderPageable), ...
    {接頭辞}で区切る
    ex/members?member_page=0&order_page=1
    デフォルト
    page=0, size= 20
    変更時
    @GetMapping("/members_page")
    public String list(@PageableDefault(size=12, sort="name", direction=Sort.Direction.DESC) Pageable pageable){
    	...
    }
    
    SpringデータJPAとQueryDSLの統合
    Spring Data JPAは、2つの方法でQueryDSLをサポートしています.
    1. QueryDslPredicateExecutor
    2. QueryDslRepositorySupport
    1.QueryDslPredicatorアクチュエータの使用
    public interface ItemRepository extends JpaRepository<Item, Long>, QueryDslPredicateExecutor<Item> {}
    
    商品レジストリでQueryDSLを使用できるようになりました.
    // QueryDSL 사용예제
    QItem item = Qitem.item;
    
    Iterable<Item> result = itemRepository.findAll(
    	item.name.contains("장난감").and(item.price.between(1000,2000))
    );
    しかし,QueryDslPredicateExecutionはSpringデータjpaからQueryDSLを容易にマッピングできるが,一定の限界がある.join、fetchは互換性がありません.
    したがって、JPAQueryを直接使用するか、QueryDslRepositorySupportを使用する必要があります.
    2. QueryDslRepositorySupport
    QueryDSLのすべての機能を使用するには、JPAQueryオブジェクトを直接作成して使用します.これにより、QueryDslRepositorySupportを継承して使用することができ、QueryDSLを簡単に使用できます.
    
    public interface CustomOrderRepository {
    	public List<Order> search(OrderSearch orderSearch);
    }
    public class CustomOrderRepositoryImpl extends QueryDslRepositorySupport implements CustomOrderRepository {
    	public CustomOrderRepositoryImpl (){
    		super(Order.class);
    	}
        
        @Override
        public List<Order> search(OrderSearch orderSearch) {
        	QOrder order = QOrder.order;
            QMember member =QMember.member;
            
            JPQLQuery query = from(order);
            
            if(StringUtils.hasText(orderSearch.getMemberName())){
            	query.leftJoin(order.member, member)
                	.where(member.name.contains(orderSearch.getMemberName()));
    		}
            
            if(orderSearch.getOrderStatus() != null ) {
            	query.where(order.staus.eq(orderSearch.getOrderStatus()));
    		}
            
            return query.lisr(order);
    	}
    }