2010-12-14 50 views
3

我有一個相當複雜的查詢(HQL或Criteria查詢的嵌套級別太多),所以我把它寫成了一個SQLQuery。我真的想使用AliasToBeanResultTransformer將我的結果轉換爲List,但我遇到了一些問題。我已經包含了我現在所掌握的代碼片段。AliasToBeanResultTransformer和Hibernate SQLQuery

當我記錄轉換查詢的結果時,我可以看到轉換器確實創建了一個List,但是每個AdvancedClauseSearchResultDTO中的所有字段都是空的。我認爲這意味着我做錯了別名... AliasToBeanResultTransformer找不到要調用的正確setter。然而,AdvancedClauseSearchResultDTO類確實對我在我的sql字符串中使用別名的每個列都有公共setter。如果這是一個Criteria查詢,我會使用投影來爲每個要返回的列定義一個別名,但我不確定如何使用SQLQuery完成同樣的事情。

有關如何獲取別名的建議,以便ResultTransformer可以使用它們嗎?我見過一些有限的文檔,建議使用'as aliasName'方法應該可行,但它似乎不適合我。

開始查詢字符串定義的片斷,注意 '爲' 別名定義

StringBuffer clauseBaseQuery = new StringBuffer(); 
     clauseBaseQuery.append("select "); 
     clauseBaseQuery.append(" clauseDetail.clause_detail_id as clauseDetailId,"); 
     clauseBaseQuery.append(" clauseDetail.clause_id as clauseId,"); 
     clauseBaseQuery.append(" providers.provider_name as provider, "); 
     clauseBaseQuery.append(" products.product_name as product, "); 

的SQLQuery創作&設置使用ResultTransformer

Query query = session.createSQLQuery(clauseBaseQuery.toString()); 
query.setResultTransformer(new AdvancedClauseSearchResultTransformer()); 
return (List<AdvancedClauseSearchResultDTO>)query.list(); 

AdvancedClauseSearchResultTransformer類(使用AliasToBeanResultTransformer然後做一些額外的處理):

class AdvancedClauseSearchResultTransformer implements ResultTransformer { 

     //Use the aliasTransformer to do most of the work 
     ResultTransformer aliasTransformer = Transformers.aliasToBean(AdvancedClauseSearchResultDTO.class); 

     @Override 
     public List transformList(List list) { 
      log.debug("transforming CLAUSE results"); 
      List<AdvancedClauseSearchResultDTO> result = aliasTransformer.transformList(list); 
      //for each row, set the status field 
      for (AdvancedClauseSearchResultDTO dto : result) { 
       log.debug("dto = " + dto); 
       String status = null; 
       Date effectiveDate = dto.getEffectiveDate(); 
       Date terminationDate = dto.getTerminationDate(); 
       Date now = new Date(System.currentTimeMillis()); 
       if (now.before(effectiveDate)) { 
        status = "Pending"; 
       } else if (now.after(terminationDate)) { 
        status = "Terminated"; 
       } else { 
        status = "Active"; 
       } 
       dto.setStatus(status); 

       if (StringUtils.isNotEmpty(dto.getReasonForAmendment())){ 
        dto.setAmended(Boolean.TRUE); 
       }else{ 
        dto.setAmended(Boolean.FALSE); 
       } 
      } 

      return result; 
     } 

     @Override 
     public Object transformTuple(Object[] os, String[] strings) { 
      Object result = aliasTransformer.transformTuple(os, strings); 

      return result; 
     } 
    } 

回答

3

注意到潛在的錯誤我得到一個很好的堆棧跟蹤,以及休眠進入論壇這幫助我克服了這個問題。

我得到的例外是: 產生的原因:org.hibernate.PropertyNotFoundException:找不到制定者CLAUSEDETAILID

看起來好像休眠正在我的駱駝別名&把它們變成全大寫,所以它無法在我的AdvancedClauseSearchResultDTO類中找到匹配的setter。

這裏的論壇條目,向我指出了正確的方向:

https://forum.hibernate.org/viewtopic.php?f=1&t=1001608

我最終使用在該職位對我自己的使用ResultTransformer詳細的辦法,而這爲我工作。

3

我想是不是寫一個結果變壓器來解決 你的問題的好方法。嘗試這樣的事情,

Query query = session.createSQLQuery(clauseBaseQuery.toString()); 
query.setResultTransformer(Transformers.aliasToBean(AdvancedClauseSearchResultDTO.class)); 

而且在AdvancedClauseSearchResultDTO類,修改setter方法來設置需要你 領域。例如,

class AdvancedClauseSearchResultDTO { 
    private Date effectiveDate; 

    private String status; 
    . 
    . 

    public void getEffectiveDate() { 
     return effectiveDate; 
    } 

    public void setEffectiveDate(Date aDate) { 
       Date now = new Date(System.currentTimeMillis()); 
       if (now.before(effectiveDate)) { 
        this.status = "Pending"; 
       } else if (now.after(terminationDate)) { 
        this.status = "Terminated"; 
       } else { 
        this.status = "Active"; 
       } 
     this.effectiveDate = aDate; 
    } 
} 

你讓我這樣做是今天一些調查研究,最後的想法...

+0

我確實嘗試過,但它沒有改變任何東西。 – elduff 2010-12-15 03:54:09

13

這取決於您使用的後端,在您的文章中未提及。

各種數據庫後端使用不區分大小寫命名爲列除非你正確地逃避他們,所以他們最終被檢索爲CLAUSEDETAILIDclausedetailid,即使你用正確的情況下指定列結果名稱。

在PostgreSQL(我相信甲骨文,太),你必須寫這樣的查詢(請注意列引用):

StringBuffer clauseBaseQuery = new StringBuffer(); 
clauseBaseQuery.append("select "); 
clauseBaseQuery.append(" clauseDetail.clause_detail_id as \"clauseDetailId\","); 
clauseBaseQuery.append(" clauseDetail.clause_id as \"clauseId\","); 
clauseBaseQuery.append(" providers.provider_name as \"provider\", "); 
clauseBaseQuery.append(" products.product_name as \"product\", "); 
Query query = session.createSQLQuery(clauseBaseQuery.toString()); 

這樣就允許Hibernate正確識別屬性和映射導致豆,只要你還規定了轉化:

query.setResultTransformer(Transformers.aliasToBean(AdvancedClauseSearchResultDTO.class)); 

正如@ zinan.yumak建議。

+0

您還需要引用DB2中的別名 – Andreas 2015-11-06 17:24:27