hql中in的用法


平時經常用Hibernate,由於習慣表間不建立關聯,所以HQL查詢時候經常要用in語句。

由於表間沒有建立外鍵的關聯關系所以使用in是最常見的代替使用對象po中的set。

但是在寫hql時如果在new object()對象的前面寫上distinct關鍵字是可以去掉重復記錄的,完全不必考慮使用in排除重復記錄,但是在本公司框架中前台的ecside獲得記錄總數時調用的方法中,獲得記錄總數代碼如下:

public Page findBy(String query, PageInfo pageInfo)
  {
    String countQuery = "select count(*) " + HqlRemoveUtils.removeSelect(query);
    return findBy(query, countQuery, pageInfo);
  }

 

public static String removeSelect(String hql)
  {
    Assert.hasText(hql);
    int beginPos = hql.toLowerCase().indexOf("from");
    Assert.isTrue(beginPos != -1, " hql : " + hql + " must has a keyword 'from'");
    return hql.substring(beginPos);
  }

可以看到其獲得記錄總數是從from后面截取hql然后重組hql才獲得記錄總數的,此時在new前面加上distinct關鍵字雖然獲得的記錄是對的,但是在前台的ecside中的記錄總數是錯誤的。

為了避免這種bug不用distinct而使用in關鍵字。這樣就可以不用關聯其他表避免造成多條重復記錄的情況,而是使用子查詢通過where中的條件使用in限制查詢條件,排除重復記錄

使用distinct的代碼如下:

String sql = "select distinct new com.luguang.product.model.LgpProductVo(a.lgpProductId,a.productName,a.productNum,d.userAlias,a.productLeader,a.productGoal,a.description,a.accessControl,'')  from LgpProduct  as a , LgmUser as d , LgpProjectGroup as e   where 1=1 "
    +" and a.productLeader=d.userId"
    +" and ((a.lgpProductId=e.lgpProductId "
    +" and e.userId='"+userId+"'"
    +" )or a.accessControl=0)"
       + "/~ and a.productName = '[productName]' ~/"
    + "/~ and a.productNum = '[productNum]' ~/"
    + "/~ and d.userId = '[productLeader]' ~/"
    + "/~ and a.accessControl = '[accessControl]' ~/"
    + "/~ order by [sortingColumn] [sortingDirection] ~/";

 

使用in的代碼如下:

String sql = "select distinct new com.lg.product.model.LgpProductVo(a.lgpProductId,a.productName,a.productNum,d.userAlias,a.productLeader,a.productGoal,a.description,a.accessControl,'')  from LgpProduct  as a , LgmUser as d   where 1=1 "
    +" and a.productLeader=d.userId"
    +" and ((a.lgpProductId in (select e.lgpProductId from LgpProjectGroup as e where e.userId='"+userId+"') "
    +" )or a.accessControl=0)"
       + "/~ and a.productName = '[productName]' ~/"
    + "/~ and a.productNum = '[productNum]' ~/"
    + "/~ and d.userId = '[productLeader]' ~/"
    + "/~ and a.accessControl = '[accessControl]' ~/"
    + "/~ order by [sortingColumn] [sortingDirection] ~/";

以后處理重復記錄時盡量采用in的形式(針對公司框架目的是避免在ecside中的記錄總數中產生錯誤的記錄統計數量),原始的hibernate框架中使用distinct較為簡單可靠。

    我最常用的情況有2種:

   1、in后是個子查詢,如 FROM A WHERE A.ID IN (SELECT B.AID FROM B WHERE ...),這樣是沒問題的,如果A.ID 和B.AID是相同的數據類型。

   2、in的參數如果已知了,可以直接拼接在后面 如FROM A WHERE A.ID IN (1,2,3,4...)。

   3、上面的情況下,通常(1,2,3,4...)都是作為參數傳遞過來的,可能是數組或者List。

    假設List<Integer> a;a里面已經有數據了,則HQL查詢條件可以為:        

Java代碼 復制代碼  收藏代碼
  1. String hql="FROM A WHERE A.ID IN (:alist)";   
  2. Query query = getSession().createQuery(hql);   
  3. query.setParameterList("alist", a);  
String hql="FROM A WHERE A.ID IN (:alist)";
Query query = getSession().createQuery(hql);
query.setParameterList("alist", a);

   另外,query.setParameterList中的第二個參數,還可以是數組類型,如int[] a,不要被方法名稱迷惑。我也是最近剛學會的這種in參數設置。


免責聲明!

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



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