5

Suppose I have some classes, like this:

OpA extends Operation OpA1 extends OpA OpA2 extends OpA OpB extends Operation OpB1 extends OpB OpB2 extends OpB OpB3 extends OpB OpC extends Operation Operation | /-----------------------------\ / | \ OpA OpB OpC / | / | /------\ /-----------\ / \ / | \ OpA1 OpA2 OpB1 OpB2 OpB3 

If I want to find some operations, I can do this:

session.createCriteria(Operation.class) .add(...) .add(...) .addOrder(...) .setFirstResult(...) .setMaxResults(...) .list(); 

But what if I want to apply these criteria not to all operations of type Operation.class, but only to those of types: OpA2 + OpB1 + OpB3 + OpC?

My Question: How can I do it using Hibernate Criteria only? No HQL, please.

Note: I don't know if I should view this problem as "querying more than one class" (where all of them have fields with the same names as the ones I am querying), or if I view it as "restricting a query by a list of subclasses".

Edit: If I could create an interface TheOnesIWant, and then make classes OpA2, OpB1, OpB3 and OpC implement this interface, this would yield the result I want: session.createCriteria(TheOnesIWant.class) But I can't do this, because I only know the classes I want to query at runtime. The above class hierarchy is just an example.

6
  • Can you write a simple sql depicting what you want considering these classes as table. Commented Jan 7, 2015 at 4:42
  • Sorry, I don't know how. Commented Jan 7, 2015 at 4:50
  • Could you create an interface, "Criteriable", which only those classes you want to apply the criteria to implement? Then session.createCriteria(Criteriable.class)? I've never tried this, but its the first thing that springs to mind :) Commented Jan 7, 2015 at 9:48
  • I can't, because the classes I need change all the time, at runtime. Commented Jan 7, 2015 at 18:07
  • You want to create this criteria in only 1 command? Considering that all the classes implements Operation, you could create one criteria for every class, and put all lists together for return. Commented Jan 9, 2015 at 17:38

1 Answer 1

8
+150

In general, Hibernate has very limited support for joining unrelated entities. By "unrelated" I mean entities that don't have references to each other. Critera API doesn't support it at all, and HSQL can do only cross join. Don't get me wrong, the underlying Criteria/HQL implementation is capable of joining unrelated entities, but the API do not expose this functionality. (You can do all kinds of joins (inner, left, right, full) on related entities.) The only way to do inner/left/right/full join on unrelated entities, is native sql. However, if the unrelated entities have common parent, you can use a hibernate feature called "implicit polymorphism": selecting the parent, will return parent and all its sub-classes. And then you can restrict the result to list of sub-classes.
So try this:

List<Operation> list = session.createCriteria(Operation.class) .add(Restrictions.or( Property.forName("class").eq(OpA2.class) ,Property.forName("class").eq(OpB1.class) ,Property.forName("class").eq(OpB3.class) ,Property.forName("class").eq(OpC.class))) .list(); 

EDIT:
Here is a example how to query properties that do not exist in the parent class: In this example properties "f" and "value" don't exist in the Operation class, they only exist in OpA2 abd OpC classes.

List<Operation> list = session.createCriteria(Operation.class) .add(Restrictions.or( Restrictions.and(Property.forName("class").eq(OpA2.class), Restrictions.eq("f", 1)) , Property.forName("class").eq(OpB1.class) , Property.forName("class").eq(OpB3.class) , Restrictions.and(Property.forName("class").eq(OpC.class), Restrictions.eq("value", "b")))) .list(); 
Sign up to request clarification or add additional context in comments.

2 Comments

OK, nice, all the classes I have are indeed related by the common parent Operation.class. But then it only seems to work if I am querying for some field that actually exists in the Operation class itself. If I query for some field that exists in all subclasses (OpA2, OpB1, OpB3 and OpC) but NOT in Operation, then I get this exception: MySQLSyntaxErrorException: Not unique table/alias.
See the EDIT section.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.