在基于方言的 Hibernate 标准 API 中使用不同的投影函数

Posted

技术标签:

【中文标题】在基于方言的 Hibernate 标准 API 中使用不同的投影函数【英文标题】:Using different projection functions in Hibernate criteria API based in Dialect 【发布时间】:2009-08-11 01:07:33 【问题描述】:

我想在我使用标准 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 函数,但是我不确定如何在使用 Criteria API 构造的查询中使用 hsql 函数。

任何帮助都会很高兴。

谢谢

【问题讨论】:

【参考方案1】:

使用方言是正确的方法(尽管我不得不说使用不同的数据库引擎进行测试和部署似乎有点不确定)。您可以执行以下操作:

    扩展 HSQL 方言并使用 registerFunction() 注册适当的 stddev 实现。 覆盖 StdDevProjection 类中的 toSqlString() 方法并使用 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();
  

【讨论】:

【参考方案2】:
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 :)

【讨论】:

以上是关于在基于方言的 Hibernate 标准 API 中使用不同的投影函数的主要内容,如果未能解决你的问题,请参考以下文章

hibernate中的dialect解释

hibernate中数据库方言

Hibernate 的 MariaDB 方言类名称是啥?

Microsoft SQL Server 2014 的 Hibernate 方言是啥?

SQL 方言如何在 hibernate 和 JOOQ 等框架内部实际工作

Hibernate 数据库方言配置;no dialect mapping for jdbc type:-9;生僻字