仅存在于子类中的属性的别名(Hibernate Criteria)

时间:2015-01-16 00:39:19

标签: java hibernate subquery hibernate-criteria detachedcriteria

考虑类Operation及其3个子类:

 class Operation {}
 class OpA extends Operation { }
 class OpB extends Operation { Account account; }
 class OpC extends Operation { Account account; }

只有OpBOpC有一个名为account的字段。

我想查询account属性:

session.createCriteria(Operation.class)
       .add(Restrictions.eq("account", account))
       .list();

这很有效。 Hibernate忽略了OperationOpA都没有名为account的字段的事实,并返回 OpBOpC的正确结果。

但是,现在我还要查询帐户所有者,并按顺序排序。然后,我为_account创建了别名account

session.createCriteria(Operation.class)
       .add(Restrictions.eq("account", account))
       .createAlias("account", "_account")
       .add(Restrictions.eq("_account.owner", "John"))
       .addOrder(Order.asc("_account.owner"))
       .list();

这失败了。该帐户有2个单独的表格(来自OpBOpC),因此Hibernate抱怨:

Not unique table/alias: 'account1_'

我的问题:如何以最简单的方式仅使用Criteria(无SQL,HQL)查询帐户和帐户所有者?

3 个答案:

答案 0 :(得分:3)

这是我的解决方案。它仅适用于部分

 Criterion subQ1 = Subqueries.propertyIn("id",
                       DetachedCriteria.forClass(OpB.class)
                            .add(Restrictions.eq("account", account))
                            .createAlias("account", "_account")
                            .add(Restrictions.eq("_account.owner", "John"))
                            .setProjection(Projections.groupProperty("id")));

 Criterion subQ2 = Subqueries.propertyIn("id",
                       DetachedCriteria.forClass(OpC.class)
                            .add(Restrictions.eq("account", account))
                            .createAlias("account", "_account")
                            .add(Restrictions.eq("_account.owner", "John"))
                            .setProjection(Projections.groupProperty("id")));

 session.createCriteria(Operacao.class)
        .add(Restrictions.disjunction()
            .add(subQ1)
            .add(subQ2))
        .list();

只要我不添加订单,它就会起作用:.addOrder(Order.asc("_account.owner"))

订单无法添加到Subqueries,因为它无效。 它无法添加到Criteria,因为它不接受别名。

也许有一种方法可以调整这个,或者这个解决方案太复杂了,而且更简单?

答案 1 :(得分:3)

以下两种解决方案无效。两者都会产生Not unique table/alias: 'account1_'

我在这里张贴他们来记录什么是行不通的,或者可能是为了给其他人提供想法,而不会使问题本身复杂化:

session.createCriteria(Operation.class)
       .createAlias("account", "_account")
       .add(
           Restrictions.and(
               Restrictions.or(
                   Property.forName("class").eq(OpB.class),
                   Property.forName("class").eq(OpC.class)),
               Restrictions.eq("account", account)
               Restrictions.eq("_account.owner", "John"))
               )
           )
       .list();

没有别名:

session.createCriteria(Operacao.class)
       .add(Restrictions.eq("account", account))
       .createCriteria("account")
       .add(Restrictions.eq("owner", "John"))
       .list();

答案 2 :(得分:1)

尝试将AccountOperation抽象类添加为:

public abstract class AccountOperation extends Operation {
    public abstract Account getAccount();    
}

现在,OpBOpC都会延长AccountOperation

您的查询将变为:

Criteria c = session.createCriteria(AccountOperation.class, "op")
    .createAlias("op.account", "ac")
    .add(Restrictions.eq("ac", account))
    .addOrder(Order.asc("ac.owner"))
    .list();