Usando diferentes funções de projecção em hibernação critérios API baseada em Dialeto
Pergunta
Eu quero usar uma projeção desvio padrão em uma consulta que estou construindo usando o API critérios. Eu posso fazer algo simplesmente como este
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 };
}
}
e então eu posso usá-lo com os meus critérios como:
myCriteriea.setProjection(new StdDevProjection(myproperty));
Isso é tudo de bom. Mas o meu problema é que eu uso HSQLDB para quaisquer testes de unidade db etc, enquanto nós usamos Oracle para implantação. A função stddev funciona perfeitamente no oráculo, mas não é lá em HSQLDB. HSQLDB tem stddev_pop e stddev_samp. Então, há alguma maneira eu posso usar uma função diferente baseada no dialeto.
Eu talvez pode estender o dialeto HSQL para registrar o "stddev" para a função HSQL adequado, mas então eu não tenho certeza como usar uma função HSQL em uma consulta construído usando a API Criteria.
Qualquer ajuda seria gret.
Graças
Solução
Usando o dialeto é a abordagem correta (embora eu tenho que dizer que o uso de bancos de dados diferentes para testar vs implantação parece um pouco duvidoso). Você pode fazer o seguinte:
- Estender HSQL dialeto e uso
registerFunction()
a registar uma implementaçãostddev
apropriada. - método
toSqlString()
Override em sua classeStdDevProjection
e ter Dialect tornar nome da função.
Algo como:
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();
}
Outras dicas
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();
}
}
e isso é o que os olhares dialeto como
public class ExtendedHSQLDialect extends HSQLDialect {
public ExtendedHSQLDialect() {
super();
registerFunction("stddev", new StandardSQLFunction("stddev_pop",Hibernate.DOUBLE));
}
}
Graças ChssPly76:)