2009-08-11 23 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 :)