2009-08-11 8 views
2

Je souhaite utiliser une projection d'écart-type dans une requête que je construis en utilisant l'API de critères. Je peux faire quelque chose simplement comme çaUtilisation de différentes fonctions de projection dans les critères Hibernate API basée sur le dialecte

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

}

et je peux l'utiliser avec mes critères:

myCriteriea.setProjection(new StdDevProjection(myproperty)); 

C'est tout bon. Mais mon problème est que j'utilise HSQLDB pour tous les tests unitaires db etc, alors que nous utilisons Oracle pour le déploiement. La fonction stddev fonctionne parfaitement dans Oracle, mais ce n'est pas le cas dans HSQLDB. HSQLDB a stddev_pop et stddev_samp. Donc est-il possible que je puisse utiliser une fonction différente basée sur le dialecte. Je peux peut-être étendre le dialecte HSQL pour enregistrer le "stddev" à la fonction HSQL appropriée, mais je ne sais pas comment utiliser une fonction hsql dans une requête construite en utilisant l'API Criteria.

Toute aide serait gret.

Merci

Répondre

1

En utilisant le dialecte est la bonne approche (même si je dois dire que l'utilisation de différents moteurs de base de données pour les tests contre le déploiement semble un peu hasardeux). Vous pouvez effectuer les opérations suivantes:

  1. Étendre le dialecte HSQL et utiliser registerFunction() pour enregistrer une implémentation stddev appropriée.
  2. Remplacez la méthode toSqlString() dans votre classe StdDevProjection et utilisez le nom de la fonction de rendu Dialect.

Quelque chose comme:

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


    } 


} 

et c'est ce que le dialecte ressemble

public class ExtendedHSQLDialect extends HSQLDialect { 
    public ExtendedHSQLDialect() { 
     super(); 
     registerFunction("stddev", new StandardSQLFunction("stddev_pop",Hibernate.DOUBLE)); 
     } 
} 

Merci :) ChssPly76

Questions connexes