Использование различных функций проекции в API критериев Hibernate на основе диалекта - PullRequest
2 голосов
/ 11 августа 2009

Я хочу использовать проекцию стандартного отклонения в запросе, который я создаю с использованием 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, но затем я не уверен, как использовать функцию hsql в запросе, созданном с использованием API Criteria.

Любая помощь будет очень кстати.

Спасибо

Ответы [ 2 ]

1 голос
/ 11 августа 2009

Использование диалекта - правильный подход (хотя я должен сказать, что использование различных механизмов баз данных для тестирования против развертывания кажется немного сомнительным) Вы можете сделать следующее:

  1. Расширьте диалект HSQL и используйте registerFunction() для регистрации соответствующей реализации stddev.
  2. Переопределите toSqlString() метод в вашем StdDevProjection классе и получите имя функции рендеринга Dialect.

Что-то вроде:

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 голосов
/ 11 августа 2009
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:)

...