2009-08-11 87 views
2

我想在使用標準API構建的查詢中使用標準偏差投影。我可以做一些簡單的像這樣在Hibernate標準中使用不同的投影函數基於方言的API

public class StdDevProjection extends AggregateProjection { 

    public StdDevProjection(String propertyName) { 
     super("stddev", propertyName); 
    } 

    public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) 
    throws HibernateException { 
     return new Type[] { Hibernate.DOUBLE }; 
    } 

}

,然後我可以用我的標準,用它作爲:

myCriteriea.setProjection(new StdDevProjection(myproperty)); 

那都好。但我的問題是我使用HSQLDB進行任何db單元測試等,而我們使用Oracle進行部署。 stddev函數在oracle中完美工作,但在HSQLDB中不存在。 HSQLDB有stddev_pop和stddev_samp。那麼有什麼方法可以根據方言使用不同的功能。

我也許可以擴展HSQL方言來註冊「stddev」到適當的HSQL函數,但是我不知道如何在使用Criteria API構造的查詢中使用hsql函數。

任何幫助將gret。

感謝

回答

1

使用方言是正確的做法(雖然我不得不說,使用不同的數據庫引擎進行測試VS部署似乎有點玄乎)。你可以做到以下幾點:

  1. 擴展HSQL方言和使用registerFunction()註冊一個適當的stddev實現。
  2. 覆蓋toSqlString()方法在您的StdDevProjection類中並且具有方言渲染函數名稱。

喜歡的東西:

public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) throws HibernateException { 
    Dialect dialect = criteriaQuery.getFactory().getDialect(); 
    SQLFunction function = (SQLFunction) dialect.getFunctions().get(this.aggregate); 
    //TODO: throw an exception if function is not registered 

    //create function argument array 
    List functionArgs = new ArrayList(1); 
    functionArgs.add(criteriaQuery.getColumn(criteria, propertyName)); 

    return new StringBuffer() 
    .append(function.render(functionArgs, criteriaQuery.getFactory())) 
    .append(" as y").append(loc).append('_') 
    .toString(); 
    } 
0
public class StdDevProjection extends AggregateProjection { 
/** 
* 
*/ 
    private static final long serialVersionUID = -7056189336427534748L; 
    private String aggregateName = null; 
    public StdDevProjection(String propertyName) { 
     super("stddev", propertyName); 
     this.aggregateName = "stddev"; 
    } 
    @Override 
    public Type[] getTypes(Criteria criteria, CriteriaQuery criteriaQuery) 
    throws HibernateException { 
     return new Type[] { Hibernate.DOUBLE }; 
    } 
    @Override 
    public String toSqlString(Criteria criteria, int loc, CriteriaQuery criteriaQuery) 
      throws HibernateException { 
     Dialect dialect = criteriaQuery.getFactory().getDialect(); 
     SQLFunction function = (SQLFunction)dialect.getFunctions().get(this.aggregateName); 
     if(function == null) { 
      throw new HibernateException("Couldnt find function for aggregate: " + aggregateName + " in Dialect: " + dialect); 
     } 
    //create function argument array 
     List functionArgs = new ArrayList(1); 
     functionArgs.add(criteriaQuery.getColumn(criteria, propertyName)); 

     return new StringBuffer() 
      .append(function.render(functionArgs, criteriaQuery.getFactory())) 
      .append(" as y").append(loc).append('_') 
      .toString(); 


    } 


} 

,這是方言的樣子

public class ExtendedHSQLDialect extends HSQLDialect { 
    public ExtendedHSQLDialect() { 
     super(); 
     registerFunction("stddev", new StandardSQLFunction("stddev_pop",Hibernate.DOUBLE)); 
     } 
} 

感謝ChssPly76 :)