2010-12-14 12 views
3

私はかなり複雑なクエリ(HQLクエリまたはCriteriaクエリのネストレベルが多すぎます)があるので、SQLQueryとして記述しました。 AliasToBeanResultTransformerを使用して結果をリストに変換したいのですが、いくつか問題があります。私は今、私が得たものの下にコードスニペットを含めました。AliasToBeanResultTransformerとHibernate SQLQuery

変換されたクエリの結果をログに記録すると、トランスフォーマがリストを作成することがわかりますが、各AdvancedClauseSearchResultDTOのすべてのフィールドはnullです。私はそれがAliasToBeanResultTransformerが呼び出したい正しいセッターを見つけることができないという、エイリアシングに何か間違ったことをしていることを意味します。ただし、AdvancedClauseSearchResultDTOクラスには、SQL文字列でエイリアス化した各列のパブリックセッターがあります。これがCriteria問合せの場合は、返す各列の別名を定義するために投影法を使用しますが、SQLQueryを使用して同じことを達成する方法がわかりません。

エイリアスを取得してResultTransformerで使用できるようにする方法についてアドバイスしますか?私は、 'aliasName'メソッドを使用するとうまくいくはずだと示唆している限定されたドキュメントを見たことがありますが、それは私のためではないようです。

エイリアス 'などの' 定義resultTransformer

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

AdvancedClauseSearchResultTransformerクラスの

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作成&設定に注意し、クエリ文字列の定義のスニペットの開始(当時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

今日はこの上でいくつかのより多くの研究をしました、そして最終的に私はなっていた根本的なエラーの良いスタックトレース、およびHibernateのフォーラムのエントリに気づきましたそれは私がこれを過ぎるのを助けた。

私はなっていた例外がある:org.hibernate.PropertyNotFoundException:によって引き起こさ Hibernateは私のキャメルケースを取っているかのようにCLAUSEDETAILID

ため

をセッターを見つけることができませんでしたそれはそう、すべて大文字にそれらを回し&のエイリアス表示されます私のAdvancedClauseSearchResultDTOクラスで一致するセッターを見つけることができません。

はここで正しい方向に私を指摘フォーラムのエントリーです:

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

私は自分のResultTransformerのためにそのポストに詳述されたアプローチを使用して終了、それは私のために働いています。

3

私は あなたの問題を解決するために、結果のトランスを書くための良い方法ではないと思います。あなたのために必要な フィールドを設定するsetterメソッドを変更し、

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

そしてAdvancedClauseSearchResultDTOクラスでは、このような何かを試してみてください。例えば、

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

13

これは使用しているバックエンドによって異なりますが、あなたの投稿には記載されていません。

各種DBのバックエンドは、あなたがそれらを適切にエスケープない限り、列のために大文字小文字を区別しないネーミングを使用するので、彼らはあなたが適切な場合に列の結果名を指定してもCLAUSEDETAILIDまたはclausedetailid、として取得されて終わります。

のPostgreSQLで

(と私はあまりにもオラクルを、信じて)、あなたは(列引用注意してください)。このようなあなたのクエリを記述する必要があります。Hibernateは適切にプロパティを認識し、マッピングすることができますので、その

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()); 

をあなたはまた、形質転換のをspecfied提供、Beanになる:

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

@ zinan.yumakによって提案されたよう。

+0

あなたはDB2の別名も引用する必要があります – Andreas