JPA調用存儲過程


1.例子

   @Transactional
    public BasAccount findByAccount(String account) {
        System.out.println(account);
        Query q = em.createNativeQuery("{call QueryBasAccount(?)}",BasAccount.class);
        q.setParameter(1, account);
        List<BasAccount> list = q.getResultList();
        BasAccount ba = null;
        if(list.size()>0){
             ba = (BasAccount)q.getResultList().get(0);
        }
        return ba;
    }

 

2.語法

   {call methodName(?)} Query .setParameter(1, param1);

   {call methodName(?,?)} Query .setParameter(1, param1);Query .setParameter(2, param2);

 

3.createNativeQuery

   概述:

         在JPA 2.0 中我們可以使用entityManager.createNativeQuery()來執行原生的SQL語句。

         但當我們查詢結果沒有對應實體類時,query.getResultList()返回的是一個List<Object[]>。

         也就是說每行的數據被作為一個對象數組返回。

   常見的用法是這樣的:

          Query query = entityManager.createNativeQuery("select id, name, age from t_user"); 
          List rows = query.getResultList(); 
          for (Object row : rows) { 
             Object[] cells = (Object[]) row; 
             System.out.println("id = " + cells[0]); 
             System.out.println("name = " + cells[1]); 
             System.out.println("age = " + cells[2]); 
          }

    總結:這樣用會使代碼非常不容易讓人理解, 究竟下標為0的元素到底是什么, 不去數查詢語句是不知道的,

             而且一旦查詢語句被調整,Java代碼也要一起調整。這時候我們想如果返回的是Map的話,用起來會清晰的多。

 
             可惜的是JPA的API中並沒有提供這樣的設置。其實很多JPA的底層實現都是支持返回Map對象的。例如:
             EclipseLink的query.setHint(QueryHints.RESULT_TYPE, ResultType.Map); 
             Hibernate的.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
      
     個人理解:返回不需要知道實體對象
     另一種:
         Query query = entityManager.createNativeQuery("select id, name, age from t_user"); 
         query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP); 
         List rows = query.getResultList(); 
         for (Object obj : rows) { 
                Map row = (Map) obj; 
                System.out.println("id = " + row.get("ID")); 
                System.out.println("name = " + row.get("NAME")); 
                System.out.println("age = " + row.get("AGE")); 
          }
        注:這里需要注意的是, 用Map肯定要比用Object數組來的效率低。所以你要看性能下降是否在可接受范圍內。
                再就是在我的Hibernate 4.2.x的環境下,無論你原生SQL中寫的是大寫字母還是小寫字母,返回的字段名都是大寫的。
                當然你可以通過自定義ResultTransformer的形式對字段名進行一定的處理, 甚至是返回自己需要的POJO。
 

4.createQuery與createSQLQuery(createNativeQuery)區別

   第一點:前者用的hql語句進行查詢,后者可以用sql語句查詢  --也可以用實體
   第二點:前者以hibernate生成的Bean為對象裝入list返回,后者則是以對象數組進行存儲

                 所以使用createSQLQuery有時候也想以hibernate生成的Bean為對象裝入list返回

       例子:

              @Override
              public List<Commodity> findCommodityByActyId(int activityId) {
                  String sql = "SELECT aa.ACTIVITYSCOPE_VALUE from activity_scope aa LEFT JOIN activity_rule ar ON aa.ACTIVITYRULE_ID = ar.ACTIVITYRULE_ID LEFT JOIN"
                 +" activity ac on ar.ACTIVITY_ID = ac.ACTIVITY_ID where ac.ACTIVITY_ID ="+activityId+" and ac.status=3";
                 System.out.println(sql);
                 Query query = entityManager.createNativeQuery(sql);
                 List<Integer> commoditiyIds = (List<Integer>)(query.getResultList());
                 List<Commodity> commodities = new ArrayList<Commodity>();
                 for(int i=0;i<commoditiyIds.size();i++) {
                    String sql2 = "from Commodity c where c.commodityId=:c1";
                    Query query2 = entityManager.createQuery(sql2);
                    query2.setParameter("c1", commoditiyIds.get(i));
                    Commodity c = (Commodity) query2.getResultList().get(0);
                    commodities.add(c);
                  }
                  return commodities;
              }

   第三點:這兩種都是動態查詢,也不被緩存

 

5.自定義函數

    //調用數據庫自定義函數
    @Query(value="SELECT a FROM Client a WHERE function('DISTANCE',?1,?2,a.LONGITUDE,a.LATITUDE)<=2")
     public List<Client> findNearClient(Float LONGITUDE,Float LATITUDE);

 

6.jpa通過解析方法名創建查詢和使用@Query創建自定義查詢

   第一種: jpa通過解析方法名創建查詢:

                 JpaRepository會對Repository層所有未加@Query的方法名進行校驗,不符合規范會報錯,除非添加@Query注解;

                  查詢方法以find | read | get 開頭 ——建議統一用find開頭;

                  格式findBy**And/Or**;findBy**NotLike等,具體參考如圖:

               

      

           例子:

                List<User>   findByUserName(String  username);

                User  findByUserNameAndPassword(String  username,String password);

 

            注意:按方法名解析的查詢方法通常只適用於單表查詢,且建議where條件參數不多於三條的情況下,返回值通常上對應表的實體Bean,

                      通常用實體類List類型;具體要看返回結果,當返回值與類型不匹配時會造成查詢錯誤;

 

   第二種:使用@Query創建自定義查詢

           概述:@Query注解的使用非常簡單,只需在聲明的方法上面標注該注解,同時提供一個 JP QL查詢語句即可;

           查詢策略:

                      <jpa:repositories>提供了guery-lookup-strategy 屬性,用以指定查找的順序。它有如下三 個取值:

                      第一:create-if-not-found: 如果方法通過@Query指定了查詢語句,

                              則使用該語句實現查詢, 如果沒有,則查找是否定義了符合條件的命名查詢,

                              如果找到,則使用該命名查詢,如果兩者都沒有找到,

                              則通過解析方法名字來創建查詢。這是query-lookup-strategy 屬性的默認值;

                     第二:create:通過解析方法名字來創建查詢。即使有符合的命名查詢,

                                或者方法通過@Query 指定的查詢語句,都將會被忽略;

                     第三:use-declared-query: 如果方法通過@Query指定了查詢語句,則使用該語句實現查詢,

                                如果沒有,則查找是否定義了符合條件的命名查詢,如果找到,則使用該命名查詢;

                                如果兩者都沒有找到,則拋出異常。

 

     使用:

         import com.xdja.timingDemo.model.Cert;

        import org.springframework.data.jpa.repository.JpaRepository;
        import org.springframework.data.jpa.repository.Modifying;
        import org.springframework.data.jpa.repository.Query;
        import org.springframework.data.repository.query.Param;
        import org.springframework.stereotype.Repository;
        import java.util.Date;
        import java.util.List;
       import java.util.Optional;
       @Repository
       public interface CertDao extends JpaRepository<Cert,Integer> {
    
          //方法名解析JpaRepository<Cert,Integer>  @Repository這兩個是重點
          Optional<Cert>  findById(Integer Id);
 
         List<Cert> findAll();
         //自定義解析
         @Query(value = "select  expire_date_time from Cert where time < '1609344000'")
         List<Date> findAllDate();
 
         @Modifying //DML操作需添加該注解
         @Query(value = "delete  from Cert where time < '1609344000'")
         void deleteTime();
 
         @Modifying
         @Query(value = "update  Cert set status = 0 where time < '1550645979'")
         void updateStatus();
    
         @Modifying
         @Query(value = "update  Cert set status = 0 where time < :time ")
         void updateStatusByTime(@Param("time") Long time);
      }
  

 

學習來源:https://www.cnblogs.com/LittleDirewolf/p/5121626.html

                  https://blog.csdn.net/qq_31678877/article/details/52935942

                  http://www.voidcn.com/article/p-vhqlnady-po.html

                  //@query自定義函數

                  https://blog.csdn.net/qq_33296651/article/details/89027914

                 //解析方法名的查詢

                 https://blog.csdn.net/weixin_42209368/article/details/87918285


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM