在基于Dialect的Hibernate标准API中使用不同的投影函数

时间:2009-08-11 01:07:34

标签: java hibernate hsqldb

我想在使用条件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进行任何数据库单元测试等,而我们使用Oracle进行部署。 stddev函数在oracle中完美运行,但在HSQLDB中不存在。 HSQLDB有stddev_pop和stddev_samp。所以,我可以使用基于方言的不同功能。

我可以扩展HSQL方言以将“stddev”注册到适当的HSQL函数,但是我不知道如何在使用Criteria API构造的查询中使用hsql函数。

任何帮助都会很好。

由于

2 个答案:

答案 0 :(得分:1)

使用方言是正确的方法(虽然我必须说使用不同的数据库引擎进行测试与部署似乎有点不确定)。您可以执行以下操作:

  1. 扩展HSQL方言并使用registerFunction()注册适当的stddev实施。
  2. 覆盖toSqlString()类中的StdDevProjection方法,并使用Dialect渲染函数名称。
  3. 类似的东西:

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

答案 1 :(得分: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:)