Querying Mapped Superclasses or Equivalent - java

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.

Related

Hibernate Embeddable: validate on post load

I have an #Embeddable class with two fields: type and value. Both fields map to the corresponding database columns. The first one is enum and the latter one is an interface that has multiple implementations.
Only certain combinations of type and value are considered valid even if type and value are correct in isolation. How can I perform such validation, when I retrieve the entity that owns the #Embeddable from the database?
I could perform validation inside no-args-constructor of embeddable, but as far as I'm concerned, Hibernate creates new #Embeddable instance with no-args-constructor and then injects the values with Java Reflection API. Therefore, if I access these two fields inside the constructor they will be null.
Is there an approach to register some PostLoad hook for the #Embeddable classes that Hibernate will trigger? I though about declaring PostLoad inside the entity itself and then calling MyEmbeddable.validate directly. But I think it's a dirty approach.
I added the class-level annotation to validate the whole object. It did work. Check out this question for more details.

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 = ?

Do I need #Transient annotation on un-mapped super-class attributes?

OK, here's the simple example:
I have an abstract super class defined thus:
abstract public class AbstractSuperEntity {
private char someFlag;
public void setSomeFlag(char flagValue) {
this.someFlag = flagValue;
}
public char getSomeFlag() {
return this.someFlag;
}
}
which all my #Entity classes inherit from. An example might be:
#Entity
#Table("SOME_ENTITY")
public class SomeEntity extends AbstractSuperEntity {
#Column(name="ID");
private Long id;
etc.
}
Does the someFlag attribute in AbstractSuperEntity need to have the #Transient?
I've tried it with and without, and it doesn't seem to make any difference. But I'm just scared I'm missing something.
EDIT Thanks for all the quick answers.
A colleague has also pointed me to the JPA Tutorial at JPalace.org, and in particular the page on ORM and JPA Concepts which has the following section:
Non-Entity Superclasses
Entities may also extend non-entity superclasses. These superclasses can be either abstract or concrete. The state of non-entity superclasses is always non-persistent. Thus, any state inherited from the non-entity superclass by an entity class is non-persistent.
Similarly to mapped superclasses, non-entity superclasses may not be used subject to queries. Mapping and relationship annotation present in a non-entity superclasses are ignored. Again, this is beacause there is no correponding database table to which the querying operations or relationships can be applied.
No, the #Transient annotation is not needed, as your AbstractSuperEntity is neither a MappedSuperClass, nor an Entity. You have to annotate it with one of those annotations if you want it to contain mapping information (that is inherited).
I'm going to disagree with Jukka and say that you don't need the annotation. It should be obvious from your configuration that the superclass isn't mapped by Hibernate, and that as far as Hibernate is concerned, your superclass doesn't even exist.
If you then go and start marking fields on the superclass as #Transient I would infer that the superclass as a whole is mapped by Hibernate but this particular field isn't. If its the only field on the superclass, I start to wonder why this class is mapped by Hibernate, go looking for the superclass mapping, get confused when I can't find it etc etc etc...
More broadly speaking, if I notice the presence of any JPA/Hibernate annotations I automatically assume that the class is mapped by your persistence provider, but at the end of the day, its your project and your decision as to what makes the code clearer.
If that property is globally not persistent, then adding the #Transient annotation will not hurt and will in fact make it explicitly transient for future readers of your code.

Play! Framework generate the CRUD from existing Entity

I have an existing Entity class that already inherits from another class, not model.
The existing entity class comes from libraries (jar), that means that I can not change them.
Can I still use the CRUD approach of Play! Framework?
how can i do it?
thank you
from http://docs.oracle.com/javaee/5/tutorial/doc/bnbqa.html#bnbqr
Non-Entity Superclasses
Entities may have non-entity superclasses, and these superclasses can
be either abstract or concrete. The state of non-entity superclasses
is non-persistent, and any state inherited from the non-entity
superclass by an entity class is non-persistent. Non-entity
superclasses may not be used in EntityManager or Query operations. Any
mapping or relationship annotations in non-entity superclasses are
ignored.
I believe the only way is too have you super class annotated with #MappedSuperClass

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