2009-08-11 7 views
2

Ich möchte eine Standardabweichungsprojektion in einer Abfrage verwenden, die Im unter Verwendung der Kriterien API konstruiert. Ich kann einfach etwas tun, wie dieseVerwenden unterschiedlicher Projektionsfunktionen in Hibernate-Kriterien-API basierend auf Dialekt

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

}

und dann kann ich es mit meinen Kriterien wie:

myCriteriea.setProjection(new StdDevProjection(myproperty)); 

Das ist alles gut. Aber mein Problem ist, dass ich HSQLDB für alle db Unit Tests usw. verwende, während wir Oracle für die Bereitstellung verwenden. Die stddev-Funktion funktioniert perfekt in Oracle, aber nicht in HSQLDB. HSQLDB hat Stddev_pop und Stddev_samp. Gibt es also eine andere Funktion, die auf dem Dialekt basiert?

Ich kann vielleicht den HSQL-Dialekt erweitern, um "stddev" auf die entsprechende HSQL-Funktion zu registrieren, aber dann bin ich nicht sicher, wie eine hsql-Funktion in einer Abfrage mit der Criteria-API verwendet wird.

Jede Hilfe wäre gret.

Dank

Antwort

1

den Dialekt zu verwenden ist der richtige Ansatz (obwohl ich habe zu sagen, dass für die Prüfung vs Bereitstellung verschiedenen Datenbank-Engines mit einem wenig zweifelhaft scheint). Sie können folgendes tun:

  1. Extend HSQL Dialekt und verwenden registerFunction() eine entsprechende stddev Implementierung zu registrieren.
  2. Override toSqlString() Methode in Ihrer StdDevProjection Klasse und Dialekt Render Funktion Name haben.

Etwas wie:

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


    } 


} 

und das ist, was der Dialekt sieht aus wie

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

Dank ChssPly76 :)

Verwandte Themen