Where do i put my hibernate annotations?
Is it the line above my instance variable? Or before the getter? Or before the setter? Or doesn't it really matter?
Thanks a lot
You place them either on the field or on the getter. From the Hibernate Annotations Reference Guide:
2.2.1. Marking a POJO as persistent entity
(...)
Depending on whether you annotate
fields or methods, the access type
used by Hibernate will be field or
property. The EJB3 spec requires that
you declare annotations on the element
type that will be accessed, i.e. the
getter method if you use property
access, the field if you use field
access. Mixing annotations in both
fields and methods should be avoided.
Hibernate will guess the access type
from the position of #Id or
#EmbeddedId.
You might also want to read about the #Access annotation that allows to force/override the access type (prior to Hibernate Annotations 3.5 and JPA 2.0, it was part of Hibernate Annotation Extensions):
2.2.2.2. Access type
By default the access type of a class
hierarchy is defined by the position
of the #Id or #EmbeddedId annotations.
If these annotations are on a field,
then only fields are considered for
persistence and the state is accessed
via the field. If there annotations
are on a getter, then only the getters
are considered for persistence and the
state is accessed via the
getter/setter. That works well in
practice and is the recommended
approach.
Note
The placement of annotations within a class hierarchy has to be consistent
(either field or on property) to be
able to determine the default access
type. It is recommended to stick to
one single annotation placement
strategy throughout your whole
application.
However in some situations, you need
to:
force the access type of the entity hierarchy
override the access type of a specific entity in the class hierarchy
override the access type of an embeddable type
The best use case is an embeddable
class used by several entities that
might not use the same access type. In
this case it is better to force the
access type at the embeddable class
level.
(...)
Regarding the pros and cons of both styles, I suggest to read the following questions:
Hibernate/JPA - annotating bean methods vs fields
Hibernate Annotations - Which is better, field or property access?
Performance difference between annotating fields or getter methods in Hibernate / JPA
It's up to your style. You may put it before the field or before getter. In strict JPA, the annotations on setters are ignored, but I'm not sure if Hibernate follows that.
You either need to be consistent throughout your Entity, or you need to provide an #Access annotation at the top of the class with a default mode, and another #Access before each field/property you wish to deviate from the current class mode.
Hibernate is known to use Java reflection. So it really doesn't matter whether you put it above the filed or above the getter.
Here is the description of some important annotation used in Hibernate.
#Entity: declares the class as an entity (i.e. a persistent POJO class)
#Table: is set at the class level; it allows you to define the table, catalog, and schema names for your entity mapping. If no #Table is defined the default values are used: the unqualified class name of the entity.
#Id: declares the identifier property of this entity.
#Generated Value: annotation is used to specify the primary key generation strategy to use. If the strategy is not specified by default AUTO will be used.
#Column: annotation is used to specify the details of the column to which a field or property will be mapped. If the #Column annotation is not specified by default the property name will be used as the column name.
Annotations based Inheritance mapping in Hibernate:
There are three kinds os inheritance mappings in hibernate.
They are
1.Table per Class hierarchy:
#Inheritance – Defines the inheritance strategy to be used for an entity class hierarchy. It is specified on the entity class that is the root of the entity class hierarchy.
#DiscriminatorColumn – Is used to define the discriminator column for the SINGLE_TABLE inheritance mapping strategies. The strategy and the discriminator column are only specified in the root of an entity class hierarchy or sub hierarchy in which a different inheritance strategy is applied
If the #DiscriminatorColumn annotation is missing, and a discriminator column is required, the name of the discriminator column defaults to "DTYPE" and the discriminator type to DiscriminatorType.STRING.
#DiscriminatorValue – Is used to specify the value of the discriminator column for entities of the given type. The DiscriminatorValue annotation can only be specified on a concrete entity class. If the DiscriminatorValue annotation is not specified and a discriminator column is used, a provider-specific function will be used to generate a value representing the entity type. If the DiscriminatorType is STRING, the discriminator value default is the entity name.
2.Table per sub Class hierarchy:
#InheritanceType – Defines inheritance strategy options. JOINED is a strategy in which fields that are specific to a subclass are mapped to a separate table than the fields that are common to the parent class, and a join is performed to instantiate the subclass.
#PrimaryKeyJoinColumn – This annotation specifies a primary key column that is used as a foreign key to join to another table.
3.Table per Concrete class hierarchy:
#InheritanceType – Defines inheritance strategy options. TABLE_PER_CLASS is a strategy to map table per concrete class.
#AttributeOverrides – This annotation is used to override mappings of multiple properties or fields.
#AttributeOverride – The AttributeOverride annotation is used to override the mapping of a Basic (whether explicit or default) property or field or Id property or field.
Hope it help's to get idea on basic annotation used in hibenate.
Related
I am trying to persist objects in a database using hibernate JPA.
The objects already have a type hierarchy, and I'm trying to make it work with hibernate.
A CatalogPackage object has all the important properties and all the getters.
A CatalogPackageImpl (extends CatalogPackage) object has no properties, but most of the setters.
Both classes are non-abstract.
We want code to refer to CatalogPackage objects. But when initializing hibernate, it complains about the setters missing from the CatalogPackage class.
How do I suggest to hibernate that it use the subclass when building the objects?
I don't want to move all the setters to the superclass, and I don't want to use CatalogPackageImpl as the entity.
Even though I can't see the problem with defining the setter methods in your CatalogPackage since they can be marked private to avoid using them from external world.
Since you didn't paste your entities configuration and that you say Hibernate is complaining about the setter methods I can conclude you are using your getters to describe your entity mapping, right?
In such a case Hibernate will always still complaining because it assumes anything mapped to the database should be done in both directions, if it can read from the datastorage so it should be allowed to write in there.
SO you have either of below solutions:
Add the setters modifiers.
Move the mapping from getter methods to fields and set the acces type to field on top of your entity:
#Access(AccessType.Field)
class CatalogPackage {
...
}
Is it possible to use #Inheritence Annotation and different strategy at different hierarchy ?
The inheritance strategy and the discriminator column are only specified in the root of an entity class
hierarchy or subhierarchy .
But different strategy allowed ?
Mixing inheritance strategies within a single entity inheritance hierarchy is not a supported JPA configuration. The JPA specification states:
The combination of inheritance strategies within a single entity inheritance hierarchy is not defined by this specification.
I do not think so, please correct me if I am wrong. You can use mixed-inheritance with same hierarchy applying different strategies. Use
#SecondaryTable(
name = "SUBTABLE",
pkJoinColumns = #PrimaryKeyJoinColumn(name = "SUB_TABLE_ID");
before your sub-class definition. Using this, you apply for example SINGLE_TABLE strategy and have separated sub-class table.
I want to specify via standard JPA Persistence.createEntityManagerFactory(String,Map<String,String>) to hibernate to use "hibernate-mapping" to "field" rather than "property".
How can I do this, the clean way?
JPA determines which mapping type to use based on where you put your #Id annotation. So if you put your #Id annotation on a field then the mapping will be field-based.
UPDATE:
In JPA 2.0 You can also use the #Access annotation. You can apply it to the class to specify the access type for the entire entity and you can apply it to individual fields/methods to override the default for a single field/property.
I have a base Entity class which will be derived in more than a hundred of a subclasses.
In order to be sure that persisted fields will be the ones I want (and not the users of that base class), I want to declare this JPA entity as setting all fields as transient by default.
How is it possible ?
If you don't put #MappedSuperclass on your class you are extending from, the class properties will never by persisted.
You can provide getter methods for certain properties, and place the annotations on the properties instead of the fields. The #Id annotation determines if you want the fields or the properties. In JPA 2 you can also use the #Access annotation.
I got the impression that if we use persistent fields, there is no need for getter methods since the entity manager references the instance variables directly. However, when I removed the getter and setter methods from an entity to have persistent fields, the values for the corresponding instance variable was not retrieved from the database!
Does that mean we must have getter and setter methods even though we have persistent fields?
If the entity class uses persistence, fields Persistence accesses the entity class instance variables directly at runtime.
While on persistence property, there is a getter and a setter method for each property.
What you said should have worked on hibernate.
A link about it
You don't mention what JPA implementation you are using. Hibernate certainly allows you to access fields directly. However, it is not the default setting, so you have to specify this behavior in the mapping files with access=field. (with annotation based configuration, I would imagine you just need to annotate the fields directly ...)
What provider is that? I'd expect it to work. Anyway, just create protected getter and setter methods as a workaround if your provider needs that.