Hibernate条件子查询引用来自" root"的值。询问

时间:2014-04-08 23:01:08

标签: hibernate groovy hibernate-criteria

我在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'。

进行比较

我在这里缺少什么?

2 个答案:

答案 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