grails - GORM 创建条件 - 使用 SQL 的 'having' 子句

标签 grails grails-orm createcriteria

我有一个虚拟自助餐厅项目,其中有三个域类:UserProductTransaction

以下是类的定义方式:

class User {

    String name
    int employeeId
    long balance = 800
    static constraints = {
        balance(max: 800L)
    }   
}

class Product {

    String type 
    int quantityInStock
    float price
    static constraints = {
    }
}

class Transaction {

    int quantityBought
    static belongsTo = [user: User, product: Product]
    static constraints = {
    }
}

现在我想找出购买了 2 种以上产品的用户数量/列表。 如何使用 Grails createCriteria 来做到这一点?

这是我尝试过的:

Transaction.createCriteria().list(){
    projections {
        groupProperty('user')
        'product' {
            count('id','numberOfPurchases')
        }
    }
    gt('numberOfPurchases',2)
}

但它给出了以下错误:

Stacktrace:

org.hibernate.QueryException: could not resolve property: numberOfPurchases of: cafeteria.dummy.Transaction 
at grails.orm.HibernateCriteriaBuilder.invokeMethod(HibernateCriteriaBuilder.java:1618)                    
at Script1.run(Script1.groovy:4)                                                                           
at org.grails.plugins.console.ConsoleService.eval(ConsoleService.groovy:37)                                
at org.grails.plugins.console.ConsoleController.execute(ConsoleController.groovy:59)                       
at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:195)   
at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)                          
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)                         
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)                         
at java.lang.Thread.run(Thread.java:745)                                                                   

如何在投影 block 外部访问此别名 numberOfPurchases 以便在 gt 中使用它?

最佳答案

内部 GORM 使用 Hibernate,目前 Hibernate 不支持 Criteria API 中的 having 子句。您无法在投影 block 之外获取 numberOfPurchases 的原因是,限制已添加到 where 子句中,并且您无法在 where 子句中使用聚合别名。 虽然JPA支持having子句。

但如果您仍然想使用 GORM Criteria 来实现这一目标,您也可以。但是您必须稍微修改您的查询,并且它不会涉及使用having 子句,并且需要子查询。

修改后的查询将是:

SELECT DISTINCT this_.user_id FROM transaction this_ where 2 < (SELECT count(sub_.id) FROM transaction sub_ WHERE sub_.user_id=this_.user_id)

GORM 的答案是:

import org.hibernate.criterion.DetachedCriteria
import org.hibernate.criterion.Projections
import org.hibernate.criterion.Restrictions
import org.hibernate.criterion.Subqueries

DetachedCriteria subQuery = DetachedCriteria.forClass(Transaction, 'sub').with {
    setProjection Projections.count('sub.id')
    add Restrictions.eqProperty('sub.user', 'this.user')
}

List<User> users = Transaction.createCriteria().list() {
    projections {
        distinct("user")
    }
    add Subqueries.lt(2l, subQuery)
} 

关于grails - GORM 创建条件 - 使用 SQL 的 'having' 子句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38007486/

相关文章:

grails - 在 Grails/GORM 中定义默认排序顺序

尝试运行 Grails 时出现 Java 异常

mysql - Grails GORM 如何在我的应用程序中加载现有的远程数据库表

grails - 实现独立 Grails 批处理的正确方法?

nhibernate CreateCriteria 通配符 就像当

grails - CreateCriteria-在hasMany关联中使用逻辑或

java - Bootstrap 中的数据导致Grails错误

logging - 集成测试期间的 Grails 日志记录

grails - 抽象域类和命名查询继承?