我有一个虚拟自助餐厅项目,其中我有三个域类:User
,Product
和Transaction
。
这里是如何定义类的:
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)
如何在投影块外部访问此别名numberOfPurchases
,以便在gt
中使用它?
答案 0 :(得分:3)
内部GORM
使用Hibernate,目前Hibernate在having clause
API中不支持Criteria
。您无法获得numberOfPurchases
外部投影块的原因是限制被添加到where子句,您不能在where
子句中使用聚合别名。
虽然JPA支持有条款。
但如果您仍想使用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)
}