我在Grails& amp; Groovy但这是一个休眠问题。这是我的Grails域类:
public Card {
// implicit Long id
String name
// ... and over a dozen other fields with various types.
}
我目前有这个Hibernate查询:
def name = "foo"
def result = session.createQuery("from Card as c where lower(c.name) like ? and c.id in (select max(c2.id) from Card as c2 where c.name = c2.name)")
.setString(0, "%${name}%")
.list()
这将获取名称中包含子字符串" foo"的所有卡片,跳过任何具有重复名称的卡片,除了"最新" (我假设更高的ID意味着更新的')。 我必须避免返回名称重复的卡片。
除了过滤名称和避免重复名称问题之外,我还需要对Card中的其他字段进行过滤和/或排序。我还需要分页。我想使用Criteria API来实现这一点,因为生成SQL / HQL的方法会导致可维护性的噩梦。
我无法通过Criteria API了解如何进行此类查询。可以通过Criteria API将分离的查询用作子查询。然而,这些子查询似乎完全独立于主要查询 - 我无法获得' c.name'将它与' c2.name'。
进行比较我在这里缺少什么?
答案 0 :(得分:0)
我自己想出来 - 通过Restrictions.sqlRestriction提供了一个Criterion,它允许在标准中使用自定义SQL。这里的问题等同于我在问题中的HQL:
def name = 'foo'
def crit = session.createCriteria(Card.class)
def subcrit = DetachedCriteria.forClass(Card.class, 'c2')
subcrit.add(Restrictions.sqlRestriction('this_.name = c2_.name'))
subcrit.setProjection(Projections.max('id'))
crit.add(Restrictions.ilike('name', "%${name}%"))
.add(Subqueries.propertyIn('id', subcrit))
def result = crit.list()
sqlRestriction()中的别名解析存在某种错误 - 据说我可以在表达式中使用{c2}.name
并让Hibernate生成正确的SQL,但我发现我必须手动写出来this_
和c2_
用于生成正确的SQL。
查看How to log SQL statements in Grails以了解如何记录生成的SQL并发现用于您自己的数据库的正确名称。
答案 1 :(得分:0)
还有另一种可能性,即在子标准中使用您的标准值(我认为更清楚):
def name = 'foo'
def crit = session.createCriteria(Card.class, 'c1')
def subcrit = DetachedCriteria.forClass(Card.class, 'c2')
subcrit.add(Restrictions.eqProperty('c1.name', 'c2.name'))
subcrit.setProjection(Projections.max('c1.id'))
crit.add(Restrictions.ilike('c1.name', "%${name}%"))
.add(Subqueries.propertyIn('c1.id', subcrit))
def result = crit.list()
请确保放置别名,例如c1
代表您的主要标准,并使用限制函数eqProperty()
来比较两个值。
另请参阅:Hibernate Java Doc