Usando diferentes funções de projecção em hibernação critérios API baseada em Dialeto

StackOverflow https://stackoverflow.com/questions/1258016

  •  12-09-2019
  •  | 
  •  

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

Foi útil?

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:

  1. Estender HSQL dialeto e uso registerFunction() a registar uma implementação stddev apropriada.
  2. método toSqlString() Override em sua classe StdDevProjection 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:)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top