Spring Data JPAダイナミッククエリ(4)


Spring Data JPA第1章ダイナミッククエリ(4)
Specification sダイナミッククエリの紹介
あるエンティティを照会するとき、与えられた条件は固定されていない.このとき、対応するクエリ文を動的に構築する必要があり、Spring Data JPAでは、JpaSpecification Exectorインターフェースで照会することができる.JPQLに比べて、タイプが安全で、より対象に向くのが強みです.
  • JpaSpecification Exectorインターフェースは複雑なクエリの主要な入口であり、Specificationオブジェクトというインターフェースに入る方法はすべて上のインターフェースSpecificationをめぐって書いたSpecificationオブジェクトを使用して複雑なクエリ文を構築したいので、Dao層はこのインターフェースを継承してからSpecificationのtoPredicate方法を実現する必要があります.
      import java.util.List;
    
      import org.springframework.data.domain.Page;
      import org.springframework.data.domain.Pageable;
      import org.springframework.data.domain.Sort;
      import org.springframework.data.jpa.domain.Specification;
      
      /**
       *	JpaSpecificationExecutor      
       **/
       public interface JpaSpecificationExecutor {
         	//          
       	T findOne(Specification spec);	
         	//        
       	List findAll(Specification spec);
         	//        
       	Page findAll(Specification spec, Pageable pageable);
         	//      
       	List findAll(Specification spec, Sort sort);
         	//    
       	long count(Specification spec);
      }
    
  • JpaSpecification Exectorについては、このインターフェースは基本的にSpecificationインターフェースをめぐって定義されている.Specification構造は照会条件であると簡単に理解できます.
  • AbstractQueryインターフェースは、rootを取得し、クエリー条件
      public interface AbstractQuery extends CommonAbstractCriteria {
      	//     from  ,              
           Root from(Class entityClass);
           Root from(EntityType entity);
          AbstractQuery where(Expression restriction);
          AbstractQuery where(Predicate... restrictions);
          AbstractQuery groupBy(Expression>... grouping);
          AbstractQuery groupBy(List> grouping);
          AbstractQuery having(Expression restriction);
          AbstractQuery having(Predicate... restrictions);
          AbstractQuery distinct(boolean distinct);
          Set> getRoots();
          Selection getSelection();
          List> getGroupList();
          Predicate getGroupRestriction();
          boolean isDistinct();
          Class getResultType();
      }
    
  • を構築することができます.
  • CriteriaQueryインターフェースは、クエリ条件
      public interface CriteriaQuery extends AbstractQuery {
          CriteriaQuery select(Selection extends T> selection);
          CriteriaQuery multiselect(Selection>... selections);
          CriteriaQuery multiselect(List> selectionList);
          CriteriaQuery where(Expression restriction);//           
          CriteriaQuery where(Predicate... restrictions);//           
          CriteriaQuery groupBy(Expression>... grouping);
          CriteriaQuery groupBy(List> grouping);
          CriteriaQuery having(Expression restriction);
          CriteriaQuery having(Predicate... restrictions);
          CriteriaQuery orderBy(Order... o);
          CriteriaQuery orderBy(List o);
          CriteriaQuery distinct(boolean distinct);
          List getOrderList();
          Set> getParameters();
          }
    
  • を構築するためのAbstractQueryインターフェースを継承しています.
  • CriteriaBuiderインターフェースはCriteriaQueryオブジェクトを作成することができ、クエリー条件(Expression式)を作成することができ、ほとんどのSql論理判定に関する表現の作成方法を定義しています.機能が非常に完全であるため、このインターフェースでの方法が一般的です.実装クラスは、ヒベルナタから
      //     Expression    ,      
      
      * Expression (   :isNull、isNotNull、in、as。。。)
      * Predicate(   :not,      {AND,OR}。。。)
      * Subquery(     ,   select、where、groupBy、having。。。)
      * Path(JPA   ,         ,       ,        )
      	* From(JPA   ,     join     )
      		* Join(    ,   join   on。。。)
      		* Root(          )
    
  • を提供する.
  • Specificationインターフェースは複雑なクエリを処理しています.例えば、複数の条件のページごとにSpecificationインターフェースの使用と意味を問い合わせると、基本的な接続文の動的な追加方法が定義されています.Specificationはこのインターフェースの実装の種類です.注意方法toPredicate(断言方法)は、criteria文の条件を処理するためのものであり、この方法を実現する必要がある
      //      
      /**
        *	root:Root  ,        ,    root        
        *	Root:     
            CriteriaQuery:      ,     
            CriteriaBuilder:         ,          ,             
            Predicate(Expression):              
      	    query:          ,       
      	    **/
          public Predicate toPredicate(Root root, CriteriaQuery> query, CriteriaBuilder cb);
    
  • Criteriaクエリの原理
    は、セキュリティとオブジェクト指向のタイプのクエリです.
  • 基本オブジェクトの構築
  • EnttityManagerのget CriteriaBuiderまたはEnttityManager Factoryのget CriteriaBuider方法により、CriteriaBuilderオブジェクト(このオブジェクトはhibergerから提供される)
  • を得ることができます.
  • CriteriaBuiderのcreateQueryまたはcreateTupleQueryを呼び出すことにより、CriteriaQueryのインスタンス
  • を得ることができます.
  • CriteriaQueryのfrom方法を呼び出すことにより、(方法はAbstractQueryで定義されているが、CriteriaQueryImplで実現されている)Rootインスタンス
  • が得られる.
  • フィルタ条件
  • フィルタ条件はSQL文のFROMサブルーチンに適用されます.criteriaクエリでは、クエリ条件は、PredicateまたはExpressionのインスタンスを介してCriteriaQueryオブジェクトに適用される.
  • これらの条件はCriteriaQuery.where法を用いてCriteriaQueryオブジェクトに適用される
  • .
  • CriteriaBuiderもPredicateの例の工場として、CriteriaBuilderの条件方法(equal、notEqual、gt、ge、lt、le、between、likeなど)を呼び出してPredicateオブジェクトを作成します.
  • 複合のPrdicate文は、CriteriaBuilderのand、or andnot法を用いて
  • を構築することができる.
    Specificationのダイナミックな実現
  • 条件クエリー
      //  id      
      @Test
      public void getCustomerByName(){
          Specification  spec = new Specification() {
              public Predicate toPredicate(Root root, CriteriaQuery> criteriaQuery, CriteriaBuilder criteriaBuilder) {
              //1.       
              Path custId = root.get("custId");
    
              //2.       select * from cst_customer where cst_name = ?
              /***
               *      :       
               *      :         
               */
              Predicate predicate =  criteriaBuilder.equal(custId,8l);
              return predicate;
          }
      };
      Customer customer =  customerDao.findOne(spec);
      System.out.println("        :"+customer);
       }
    
  • 多条件クエリー
    @Test
    public void getCustomerByNameAndIndustry(){
        Specification  spec = new Specification() {
            public Predicate toPredicate(Root root, CriteriaQuery> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                //1.       
                Path custName = root.get("custName");
                Path custIndustry = root.get("custIndustry");
    
            //2.       select * from cst_customer where cst_name = ?
            /***
             *      :       
             *      :         
             */
            Predicate predicate1 =  criteriaBuilder.equal(custName,"    ");
            Predicate predicate2 =  criteriaBuilder.equal(custIndustry,"  ");
            Predicate p = criteriaBuilder.and(predicate1,predicate2);
            return p;
        }
    };
    Customer customer =  customerDao.findOne(spec);
    System.out.println("        :"+customer);
    
  • あいまい検索
      @Test
      public void getCustomerByNameLike(){
          Specification  spec = new Specification() {
              public Predicate toPredicate(Root root, CriteriaQuery> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                  //1.    
                  Path custName = root.get("custName");
                  //2.         
                  Predicate predicate =  criteriaBuilder.like(custName.as(String.class),"  %");
                  return predicate;
              }
          };
          List list =  customerDao.findAll(spec);
          for (int i = 0; i < list.size(); i++) {
              System.out.println("        :"+list.get(i));
          }
      }
    
  • あいまいなクエリと並べ替え
      @Test
      public void getCustomerBySort(){
              Specification  spec = new Specification() {
              public Predicate toPredicate(Root root, CriteriaQuery> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                     //1.    
                     Path custName = root.get("custName");
                     //2.         
                     Predicate predicate =  criteriaBuilder.like(custName.as(String.class),"  %");
                     return predicate;
                  }
              };
              //       
              Sort sort = new Sort(Sort.Direction.DESC,"custId");
              List list =  customerDao.findAll(spec,sort);
              for (int i = 0; i < list.size(); i++) {
                  System.out.println("        :"+list.get(i));
              }
          }
    
  • 注:複数の条件並べ替え
  • は、複数のソトオブジェクトを構成し、
     //     ,    :ASC/DESC,     :       ,      
     Sort sort = new Sort(Sort.Direction.DESC,"adminId");
     Sort sort1 = new Sort(Sort.Direction.ASC,"adminUsername");
     final Sort mergeSort = sort1.and(sort);
    
  • を統合する.
  • ダイレクト構造Sortオブジェクト並べ替え
     Sort sortMulti = new Sort(Sort.Direction.DESC,"adminId","adminUsername");//    
    
  • あいまいなクエリの並べ替えは、
      @Test
      public void getCustomerByPagin(){
          Specification  spec = new Specification() {
              public Predicate toPredicate(Root root, CriteriaQuery> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                  //1.    
                  Path custName = root.get("custName");
                  //2.         
                  Predicate predicate =  criteriaBuilder.like(custName.as(String.class),"  %");
                  return predicate;
              }
          };
          //       
          /**
           *       
           *      :   ( 0   )
           *      :       
           */
          Pageable pageable = new PageRequest(0,2);
          Page page  =  customerDao.findAll(predicate,pageable);
          System.out.println("    :"+page.getTotalElements());
          System.out.println("       :"+page.getContent());
          System.out.println("   :"+page.getTotalPages());
          List list = page.getContent();
    
          for (int i = 0; i < list.size(); i++) {
              System.out.println("        :"+list.get(i));
          }
      }
    
  • ページに分かれています.
  • inクエリー
     @Test
     public void testIn(){
       final  Long[] ids={1l,2l};
         Specification spec = new Specification() {
             public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder cb) {
                 List list = new ArrayList();
                 CriteriaBuilder.In in = cb.in(root.get("custId"));
                 for (Long id :ids) {
                     in.value(id);
                 }
                 return cb.and(in);
             }
         };
         List list = customerDao.findAll(spec);
         for (int i = 0; i < list.size(); i++) {
             System.out.println(list.get(i).toString());
         }
     }
    
  • 方法対応関係
  • メソッド名
    Sql対応関係
    eque
    filed=value
    gt(greaterThan)
    filed>value
    lt(lessThan)
    filed
    ge(greater ThanOrEqualTo)
    filed>=value
    le(lessThanOrEqualTo)
    filed<=value
    notEqule
    filed!=value
    like
    filed like value
    not Like
    filed not like value