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

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.

Related

Is it possible to map custom final classes in hibernate?

Suppose I have already made class which I wish to persist. I can't change it's code, i.e. can't put any annotations inside. Also, class is not following bean convention.
I.e. it is arbitrary complex class I wish to persist.
Is it possible to write some sort of custom serializer and deserializer (don't know how to name it) in Hibernate, so that I be able to read these classes as usual POJOs?
Hello the first question is can I map a "fina class" the answer to this question is YES as long as you dont use Hibernate Enchancing or some sort of instrumentation.
Now second question. Bean not following Bean Conventions. I guess this means no getters and setters. You can have Attribute level access so this is again not a problem.
Is it possible to write custom serializer in Hibernate. The answer here is NO. Why ? Because Hibernate is not about Serialization hibernate is about SQL. There is no strict requirement that a Hibernate Entity should be serialize-able.
Even though Hibernate does not enforce serialization. Can I still make my final class serialize-able even though it does not implement Serializable or Eternalizeable. Yes you need to wrap it into class implementing Serializable or Externalizeable and implement the doRead doWrite methods yourself.
Serialization to JSON or XML - this is not part of Hibernate neither is part of JPA. Serialization to these two formats is defined as part of the Jaxb and Jax-rs specifications.
Have a look at hibernate UserType and CompositeUserType, with the well known EnumUserType example
Enums are a bit like your needs : final class, no getters nor setters. They are not complex though, so you might need a CompositeUserType that allows to map several columns for one Type, rather that a UserType.
Then you would use it like that in your class :
public class MyClass {
#Id
private Long id;
#Type(type = "com...MyCompositeUserType")
private ComplexFinalClassNotPojo complexObject;
}

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 there any reason to not generate setters and getters for #Id fields in JPA?

Assuming a JPA entity with (for example) an long id generated automatically:
#Entity
#AutoProperty
public class SomeItem {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long Id;
...
}
Is there any reason to not generate setter and getters for this Id? One might be tempted to not generate a setter for example, since it is the responsibility of JPA to generate the ID.
I see that other comments has misguided you so I feel myself obliged to elaborate on this issue a bit, even though I can't give you a scientific and complete answer. #vcetinick wrote the current accepted answer:
You may find that you may be able to get away [..] from the persistence side of things.
This quote in particular is wrong. All depends on where you put your #Id annotation. The specification says:
If the entity has field-based access, the persistence provider runtime
accesses instance variables directly.
Thus you are not required in any way to provide a setter or getter. Because you annotated your field and not a getter method (annotating the setter method will be ignored and have no bearing).
However, if you write a getter method, and annotated this method with your #Id annotation instead of your field, then we would tell our persistence provider to access our field through the accessor (getter) and mutator (setter) methods and not use reflection. In that case, both a getter and a setter should be present. The book Pro JPA 2: Mastering the Java™ Persistence API writes on page 71 (bold markup by me!):
When property access mode is used, the same contract as for JavaBeans applies, and there must be getter and setter methods for the persistent properties. The type of property is determined by the return type of the getter method and must be the same as the type of the single parameter passed into the setter method. Both methods must be either public or protected visibility.
Therefore, I usually annotate my id field, and write both a setter and getter method, but the setter method I give protected access. I just don't want any other pieces of code to have easy write access to such an important field. I don't know if this would cause problems in other domains. I'm no expert. But I don't find any rationale either as to why not setup an id attribute in this way. See also the Netbeans forums.
You may find that you may be able to get away without putting a getter/setter on the JPA Entity from the persistence side of things. But if you start dealing with entities that are serialized from other sources, even from your view in some cases, you will need a way to set the ID of the entity to let JPA know that it is dealing with an existing entity, if you cant set the id, then the persistence layer will just treat it as a new Object.
Id is your primary key without it you will never able to insert records in the database.
In your case #GeneratedValue(strategy=GenerationType.AUTO) it ensures that id will be generated for each persist but then also you will need a method to access it since it is primary identification of entity you should provide access to it .
Its like you asking some person his name and he doesn't provide it to you and you would thing he is just being rude .

JPA mapping annotations for Object type

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.

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

Categories

Resources