Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alias for properties that exist only in subclasses (Hibernate Criteria)

Consider the class Operation, and its 3 subclasses:

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

Only OpB and OpC have a field called account.

I want to query for the account property:

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

This works. Hibernate ignores the fact that both Operation and OpA have no field called account, and returns the correct results for OpB and OpC.

However, now I also want to query for the account owner, and order by it. I then create the alias _account for 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();

This fails. There are 2 separate tables for the account (from OpB and OpC), so Hibernate complains:

Not unique table/alias: 'account1_'

My question: How can I query for both the account and the account owner, using only Criteria (no SQL, HQL) in the simplest possible way?

like image 239
MarcG Avatar asked Jan 16 '15 00:01

MarcG


1 Answers

This is my solution. It works only partially:

 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();

It works as long as I don't add order: .addOrder(Order.asc("_account.owner")).

The order cannot be added to the Subqueries, because it would have no effect. And it cannot be added to the Criteria, because it doesn't accept the alias.

Maybe there is a way to tweak this, or maybe this solution is too complicated and there is an easier one?

like image 126
MarcG Avatar answered Sep 26 '22 03:09

MarcG