I am trying to convert a native SQL query to use the Criteria API in JPA 2.0. I have found a lot of Criteria API examples on Google, but I am having a really hard time putting
JPA does not support UNION, either use a native SQL query, or execute two queries.
If you need Union All, then two entities are candidates to apply inheritance to them in my mind.
As Marcin noted it is possible with inheritance, at least in special cases.
If you can make queried entities inherit one from another using TABLE_PER_CLASS inheritance strategy (provided optionally, possible in hibernate, but has limitations there - you cannot use IDENTITY and AUTO) and if the field to be present in the query has the same name in both entities then you can unite both entities by querying the parent one.
For instance, if entity class Child extends from entity class Parent both having field "name", query would be :
select p.name from Parent p
To select only names of Parent entities add condition with TYPE.
select p.name from Parent p where TYPE(p) = Parent
If modifying entities to inherit one from another is inappropriate, you can create special ones (with inheritance, of cause) for this query, since it is possible to create several entities for the same table. But you likely don't find that effort reasonable.
Sorry the below example is not union, it is rather a join.
I would consider using query with multiple roots.
Here is an exerpt from Hiberante developer guide, the code is JPA 2.0-compatible.
Criteria queries may define multiple roots, the effect of which is to create a cartesian product between the newly added root and the others. Here is an example matching all single men and all single women:
CriteriaQuery query = builder.createQuery();
Root<Person> men = query.from( Person.class );
Root<Person> women = query.from( Person.class );
Predicate menRestriction = builder.and(
builder.equal( men.get( Person_.gender ), Gender.MALE ),
builder.equal( men.get( Person_.relationshipStatus ), RelationshipStatus.SINGLE )
);
Predicate womenRestriction = builder.and(
builder.equal( women.get( Person_.gender ), Gender.FEMALE ),
builder.equal( women.get( Person_.relationshipStatus ), RelationshipStatus.SINGLE )
);
query.where( builder.and( menRestriction, womenRestriction ) )