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
Related
As entity class field can be mark as private when #Entity access mode is "Field" access , just wanted to understand how provider will able to access entity state in this case as fields are marked as Private and will not be visible outside class ?
Edit #1 - As you know , for field access , getter and setter method are optional. So I wanted to understand how provider will access the field when no getter/setter method are provided. Hope this clarify my question .
Referring to the official JPA specification (final version, JPA 2.1) in Section 2.2 (page 24) we find:
The persistent state of an entity is accessed by the persistence provider runtime either via JavaBeans
style property accessors (“property access”) or via instance variables (“field access”). Whether persistent
properties or persistent fields or a combination of the two is used for the provider’s access to a
given class or entity hierarchy is determined as described in Section 2.3, “Access Type”.
In Section 2.3.1 (page 27) this definition is made more concrete - with respect to your question:
By default, a single access type (field or property access) applies to an entity hierarchy. The default
access type of an entity hierarchy is determined by the placement of mapping annotations on the
attributes of the entity classes and mapped superclasses of the entity hierarchy that do not explicitly
specify an access type. [...]
• When field-based access is used, the object/relational mapping annotations for the entity class
annotate the instance variables, and the persistence provider runtime accesses instance variables
directly. All non-transient instance variables that are not annotated with the Transient
annotation are persistent.
• When property-based access is used, the object/relational mapping annotations for the entity
class annotate the getter property accessors, and the persistence provider runtime accesses persistent state via the property accessor methods. All properties not annotated with the Transient annotation are persistent.
The term directly refers to an access strategy which allows the manipulation of an object's field (value) without the need to use getter/setter methods. In Java and for most OR-mappers (at least the ones I know of) this is achieved via Introspection - using the Java Reflection API. This way, classes' fields can be inspected for and manipulated to hold/represent data values from the (relational) database entries (i.e., their respective columns).
For instance, the provider Hibernate gives the following explanation in their User Guide:
2.5.9. Access strategies
As a JPA provider, Hibernate can introspect both the entity attributes
(instance fields) or the accessors (instance properties). By default,
the placement of the #Id annotation gives the default access strategy.
Important note:
Be careful when experimenting with different access strategies! The following requirement must hold (JPA specification, p. 28):
All such classes in the entity hierarchy whose access type is defaulted in this way must be consistent in
their placement of annotations on either fields or properties, such that a single, consistent default access
type applies within the hierarchy.
Hope it helps.
The provider can use reflection to access a private field on a class instance.
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.
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.
I will implement an entity class, something like:
#Entity
public class XXXEntity {
#Id
private Long id;
private Object entity;
}
But I am not sure how to map the Object type field?
Actually, in my project the object types contain several other entities, like A, B, C. (all A,B, and C implement Serilizable interface)
I want to annotate it as #Lob, but I am not sure it is correct? Because Object doesn't implement Serilizable interface.
Any ideas about that? Thanks.
You can not annotate Object field as #Lob. According to spec: "A Lob may be either a binary or character type."
You should decide whether A, B and C are entities or state field values. If they are entities and they can be referenced, queried by their properties, create a common super class a go with the inheritance.
If they are just an object then using Lob and implementing Serializable should suffice. If the JPA provider requires you to replace Object with something else, as you have stated you can use Serializable interface, if that does not work then a common super class which implements Serializable.
It seems to me you want to use it as "ValueObject" (as u mentioned serializable) instead of "Entity".
It is fine if you treat the field as ValueObject. Using Lob should be fine (and you can always find workaround by manually serializing it).
But if you want to treat them as "Entity ", it will never be reasonable to declare it as ref to "Object". One of the most obvious argument is Object is NOT an Entity, as it doesn't contains any entity identity.
No, it is not correct to annotate it with #Lob. You cannot directly annotate arbitrary Object as a persistent attribute. JPA provider have no way to know how to persist it.
According JPA 2.0 specification persistent attribute must be one of following:
Java primitive types; java.lang.String; other Java serializable types
(including wrappers of the primitive types,
java.math.BigInteger,java.math.BigDecimal,java.util.Date,java.util.Calendar[5],
java.sql.Date, java.sql.Time, java.sql.Timestamp, byte[], Byte[],
char[], Character[], and user-defined types that implement the
Serializable interface); enums; entity types; collections of entity
types; embeddable classes; collections of basic and embeddable types.
You should redesign model such a way that there is no need to persist basically typeless data.
I have an abstract superclass that has JPA annotations on it mapping some of its fields. The class itself has the #MappedSuperclass annotation.
Can I specialize/add or change just one element of an inherited annotation without re-specifying the entire annotation?
The only thing you can do with Annotations is to place an Annotation on an Annotation and have a library which understands this as a form of inheritance.
The problem is that if you re-specify the entire annotation, any library which expects MappedSuperclass will ignore it.