【问题标题】:Grails with Criteria有条件的圣杯
【发布时间】:2016-01-13 14:39:42
【问题描述】:

我想在 Grails Criteria 中为 orderBy 子句使用 NVL 函数。我该怎么用?我尝试了多种方法。谁能帮帮我?

要转换为 Grails Criteria 的 SQL 查询: Select * forom Domain_Table order by NVL(field1,field2) ASC

尝试的方法1:

Domain.createCriteria().list(max:10,offset:10){
   order(field1,'ASC')
   order(field2,'ASC')
}

工作正常,但生成类似 SQL 查询

Select * forom Domain_Table order by field1 ASC,field2 ASC

这不符合我的要求

方法二:

 Domain.createCriteria().list(max:10,offset:10){
       order(nvl(field1,field2),'ASC')
    }

错误:Nvl 不是域类的属性

方法三:

Domain.createCriteria().list(max:10,offset:10){
   projections{
  addProjectionToList(Projections.sqlProjection("nvl(field1,field2) as description", ['description'] as String[], [Hibernate.STRING] as Type[]), 'description'))
           order('description,'ASC')
        }

问题: 我正在根据确切的顺序获取记录。但是,我再次使用描述访问数据库以获得我不想要的域。 还有一个选择,我可以输入属性(名称,别名),我会得到回应。但是,我需要查询整个域。

请帮帮我。

【问题讨论】:

  • 您尝试过 HQL 查询吗?我不确定它是否处理 NVL,但它会是这样的:Domain.executeQuery('select d from Domain as d order by NVL(d.field1, d.field2)。与标准查询投影不同,使用 HQL 您可以投影根实体(域)。
  • @EmmanuelRosa :我可以使用 HQL 并且可以执行。但是,我有一个不使用 HQL 的限制。我只需要使用标准...

标签: hibernate grails grails-orm grails-domain-class


【解决方案1】:

您可以将@Formula 用于实体上的人工字段(我们将其命名为nvl),然后在排序中使用它。

或者您可以使用 Order 的自定义实现

public class OrderBySqlFormula extends Order {
    private String sqlFormula;

    /**
     * Constructor for Order.
     * @param sqlFormula an SQL formula that will be appended to the resulting SQL query
     */
    protected OrderBySqlFormula(String sqlFormula) {
        super(sqlFormula, true);
        this.sqlFormula = sqlFormula;
    }

    public String toString() {
        return sqlFormula;
    }

    public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
        return sqlFormula;
    }

    /**
     * Custom order
     *
     * @param sqlFormula an SQL formula that will be appended to the resulting SQL query
     * @return Order
     */
    public static Order sqlFormula(String sqlFormula) {
        return new OrderBySqlFormula(sqlFormula);
    }
}

并使用criteria.addOrder(OrderBySqlFormula.sqlFormula("(a + b) desc"));

从这里

http://blog.tremend.ro/2008/06/10/how-to-order-by-a-custom-sql-formulaexpression-when-using-hibernate-criteria-api/

【讨论】:

  • 这是非常好的方法之一。你能建议一些其他的方法吗? @StanislavL
【解决方案2】:

由于您必须使用标准,因此无需修改域类,您的第三种方法是最接近解决方案的方法。

您可以将域类 id 添加到投影中,获取所有 ID,最后调用 Domain.getAll() 以返回实例。您将需要两个查询,但第二个使用主键,因此它会尽可能快地运行。

def ids = Domain.createCriteria().list(max:10,offset:10){
   projections{
      property('id')
      sqlProjection("nvl(field1,field2) as description", 'description', Hibernate.STRING)           
   }
   order('description','ASC')
}*.getAt(0) // Only selects the first column: the ID.

def instances = Domain.getAll(ids)

【讨论】:

  • 同意...但是,正如我所提到的,它还需要一个数据库调用,这让我花费更多...?
猜你喜欢
  • 1970-01-01
  • 2011-11-03
  • 1970-01-01
  • 2013-12-09
  • 1970-01-01
  • 2011-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多