JPA Native Query for Entity with Inheritance - java

I have an entity class and a subclass based on that entity:
#Entity
#Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class A
and
#Entity
public class B extends A
I need to issue a native query that uses a stored procedure on the base class (A) only. If I attempt it as follows:
entityManager.createNativeQuery("select * from A a where procedure(f)",A.class).getResultList()
I get an error regarding "The column clazz_ was not found in the ResultSet". I assume that the JPA provider adds this column in order to discriminate between the base class and the extended class. I can work around this problem by explicitly adding the clazz column and all of the fields from the subclass:
entityManager.createNativeQuery("select *,1 as clazz_,null as prop1,null as prop2 from A a where procedure(f)",A.class).getResultList()
where "prop1" and "prop2" are properties of the subclass B. However, this seems like an unnecessary hack and is prone to maintenance problems if the subclass B changes.
My question is: How can I query using a stored procedure on an entity that has inheritance defined on it?

As you've probably seen, the Hibernate team hasn't put a lot of work into defining how you do this.. the documentation simply states:
16.1.6. Handling inheritance
Native SQL queries which query for
entities that are mapped as part of an
inheritance must include all
properties for the baseclass and all
its subclasses.
So if you want to use Native queries it looks like you're stuck doing something like this. Regarding the concern about the subclass B changing, perhaps a slightly less onerous way of implementing this would be to try using LEFT OUTER JOIN syntax on the shared ID property:
entityManager.createNativeQuery("select a.*, b*, 1 as clazz_, from A a LEFT OUTER JOIN B b on id = a.id where procedure(f)",A.class).getResultList()
That way you'll always get all of the properties from B if you add or remove some.

You need to distinguish instances of A from instances of B, using a discriminator.
Use one of the following annotations:
#DiscriminatorValue
http://docs.oracle.com/javaee/5/api/javax/persistence/DiscriminatorValue.html
#DiscriminatorColumn
https://docs.oracle.com/javaee/5/api/javax/persistence/DiscriminatorColumn.html
#DiscriminatorFormula
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html#d0e1168

Related

I can't downcast in JPQL/Hibernate - Unable to find domain.Scoreable with id 16

I have an abstract class called Scoreable and it's extended by two classes named Idea and Solution. That is, both subclasses may have a set of scores. Every Score has a field scoreable that is a FK.
What I want to get is a collection of Scores given, for example, an Idea. So I've tried the following query:
select s from Score s join s.scoreable idea where idea.id = 16;
But it returns Unable to find domain.Scoreable with id 16, maybe because the Scoreable table doesn't exist in the database. Also I tried a downcast with this query select s from Score s join TREAT(s.scoreable AS Idea) idea where idea.id = 16;. In this case, I get the same response.
Your problem may be because you mapped the Scorable with #MapedSuperclass and now you want to include the base type in a query. For this you need the base class to be an actual #Entity instead.
According to the JPA documentation:
A mapped superclass is a non-entity class that can define persistent state and mapping information for entity subclasses. Mapped
superclasses are usually abstract. Unlike true entities, you cannot
query a mapped superclass, pass a mapped superclass instance to any
EntityManager or Query methods, or declare a persistent relation with
a mapped superclass target. You denote a mapped superclass with the
MappedSuperclass marker annotation.
So you can have Scorable as both the base class and an #Entity, while its subclases idea dn Solution are #Entities too.For more about this inheritance model, check this JPA example from Oracle.
If you only need Idea's scores you can issue the following query:
select distinct s
from Idea i
join i.scores s
where i.id = ?

Querying Mapped Superclasses or Equivalent

I have three classes that are subclasses of the abstract superclass Automobile. I'm using the single table inheritance model and a #MappedSuperclass for the automobile class. The subclasses are Car, Truck, and Van.
I want to query the automobile class, but have the different subclasses returned. I've written a couple queries and done some research, but it seems like it is not possible to query against MappedSuperclasses. I have also tried to do NativeSqlQueries, but I can't seem to be able to figure out how to specifiy multiple ResultSetMappings.
Is there anyway to accomplish this?
You cannot use a mapped-superclass in the query. If you want to use Automobile in the query, don't mark it as mapped-superclass, instead mark it as an entity.
Following is from the JPA 2.0 Spec, second paragraph is what's relevant in your case -
2.11.2 Mapped Superclasses
An entity may inherit from a superclass that provides persistent entity state and mapping information, but which is not itself an entity. Typically, the purpose of such a mapped superclass is to define state and mapping information that is common to multiple entity classes.
A mapped superclass, unlike an entity, is not queryable and must not be passed as an argument to EntityManager or Query operations. Persistent relationships defined by a mapped superclass must
be unidirectional.

Is it possible to fetch all child entities from a parent abstract entity?

I'm trying to figure out if I can make a method that fetches or finds all the entries in a central database I have.
My entities are as follows:
Nomination(Abstract) -> Type1Nomination, Type2Nomination, Type3Nomination, so on.
Nomination has a table is mapped to the DB also, and has the common properties/columns of every type of nomination. The rest is self-explanatory.
The way I see it, I would have to cast the types of nominations to the base class? And this would be done in a Service class (because you cannot make a DAO of an abstract class), am I correct?
You can do this in JPA/Hibernate and JPA inheritance. It should be as simple as querying the Nomination entity.
Select n From Nomination n
should return a list of abstract nomination objects.
I've seen folks using a type column in conjunction with the in keyword to get certain subgroups in your case something like
Select n from nomination where n.type in :types
where types was a collection of "Type1Nomination" "Type2Nomination" but because these are sibling queries it can lead to some nasty LEFT OUTER JOIN queries

Is nesting of different types of inheritance allowed in hibernate.?

I have a situation like this...
I have four different tables namely btech_ece, btech_cse, btech_it, btech_eee all these tables have the same columns. Its just that the name differs and everything else is same. Their columns are:
Id
Year
Semister
Section
Period
SubjectCode
Date
Status
now i have four different tables under each division ece, cse, it and eee. btech_cse_1, bteh_cse_2, btech_cse_3, btech_cse_4, btech_ece_1, btech_ece_2 and so on..
the columns of these tables are like this:
Roll_Number
Id
Present
the id column above is a foreign key from the tables btech_cse. My idea was that if i can use a nesting of hibernate's inheritance hierarchy. I could have a class named btech and all the classes btech_cse, btech_ece, btech_eee, btech_it can be its union-subclasses and i can have another class that says btech_cse_num which is a joined subclass of the above union subclass and each class of the form btech_cse_1 could be again a union-subclass of the btech_cse_num class. Is such nesting allowed in hibernate?
How do i best exploit the hibernate's inheritance feature to suit my situation.?
If feasibility is the only concern, then I suggest you look at the hibernate reference documentation. The chapter on "Inheritance Mapping" gives some useful pointers, this is from version 3.3 docs:
Hibernate does not support mixing subclass, joined-subclass and union-subclass mappings under the same root class element. It is possible to mix together the table per hierarchy and table per subclass strategies under the the same class element, by combining the subclass and join elements. It is possible to define subclass, union-subclass, and joined-subclass mappings in separate mapping documents directly beneath hibernate-mapping. This allows you to extend a class hierarchy by adding a new mapping file.

How to perform a non-polymorphic HQL query in Hibernate?

I'm using Hibernate 3.1.1, and in particular, I'm using HQL queries.
According to the documentation, Hibernate's queries are polymorphic:
A query like: from Cat as cat returns instances not only of Cat, but also of subclasses like DomesticCat.
How can I query for instances of Cat, but not of any of its subclasses?
I'd like to be able to do it without having to explicitly mention each subclass.
I'm aware of the following options, and don't find them satisfactory:
Manually filtering the instances after the query, OR:
Manually adding a WHERE clause on the discriminator column.
It would make sense for Hibernate to allow the user to decide whether a query should be polymorphic or not, but I can't find such an option.
Thanks in advance!
Use polymorphism="explicit" in the class mapping. This will cause queries to return only instances of the named class and not its subclasses.
Implicit polymorphism means that
instances of the class will be
returned by a query that names any
superclass or implemented interface or
class, and that instances of any
subclass of the class will be returned
by a query that names the class
itself. Explicit polymorphism means
that class instances will be returned
only by queries that explicitly name
that class.
SELECT cat FROM Cat cat WHERE cat.class='cat'
where the value 'cat' is the discriminator value of the Cat class.
If you are using TABLE_PER_CLASS, then try cat.class='Cat') (the name of the class)
This is not exactly a where clause on the discriminator column, because such a query will fail (the discriminator column is available only in native queries).
JPA 2 (Hibernate 3.5) adds support for non-polymorphic queries, this is very similar to Hibernates .class property (as Bozho answered above) but it is not Hibernate specific. This is done using the TYPE operator. As in
Select b from Book b where TYPE(b) = Book
You can read more about here it in my blog
Eyal
The ORM mimics the Java Model: if an object is an instance of another type (if an instance of PersianCat is an instance of Cat also), any query on Cat will have to be polymorphic (imagine you querying a List and asking if the entries match instanceof Cat.
Even Bozho's solution is somewhat impure, since the 'class' column is supposedly opaque to your hibernate mapping, although I admit its a very good compromise. You can simply get the discriminator through the classe's simple name.
If you're comfy and are using table per class you can always do a native query to the Cat table to get the ids and then get the entries through hibernate.
Look at BaseQueryReturnFieldsCalculatorGC; it dynamically adds a condition to the 'where' which selects only where class=XXX; you can duplicate this logic to the HQLQueryTemplate and have the user define 'isNonPolymorphic'.
Note that it will only work with table-per-hierarchy, cos only then does the implicit class column exist and is selectable.

Categories

Resources