Hibernate.org Community Documentation

Hibernate Annotations

Reference Guide


Preface
1. Setting up an annotations project
1.1. Requirements
1.2. Configuration
1.3. Properties
1.4. Logging
2. Mapping Entities
2.1. Intro
2.2. Mapping with JPA (Java Persistence Annotations)
2.2.1. Marking a POJO as persistent entity
2.2.2. Mapping simple properties
2.2.3. Mapping identifier properties
2.2.4. Mapping inheritance
2.2.5. Mapping entity associations/relationships
2.2.6. Mapping composite primary keys and foreign keys to composite primary keys
2.2.7. Mapping secondary tables
2.2.8. Caching entities
2.3. Mapping Queries
2.3.1. Mapping JP-QL/HQL queries
2.3.2. Mapping native queries
2.4. Hibernate Annotation Extensions
2.4.1. Entity
2.4.2. Identifier
2.4.3. Property
2.4.4. Inheritance
2.4.5. Single Association related annotations
2.4.6. Collection related annotations
2.4.7. Cascade
2.4.8. Filters
2.4.9. Queries
2.4.10. Custom SQL for CRUD operations
2.4.11. Tuplizer
2.4.12. Fetch profiles
3. Overriding metadata through XML
3.1. Principles
3.1.1. Global level metadata
3.1.2. Entity level metadata
3.1.3. Property level metadata
3.1.4. Association level metadata
4. Additional modules
4.1. Bean Validation
4.1.1. Adding Bean Validation
4.1.2. Configuration
4.1.3. Catching violations
4.1.4. Database schema
4.2. Hibernate Validator 3
4.2.1. Description
4.2.2. Integration with Hibernate Annotations
4.3. Hibernate Search
4.3.1. Description
4.3.2. Integration with Hibernate Annotations

Hibernate, like all other object/relational mapping tools, requires metadata that governs the transformation of data from one representation to the other. Hibernate Annotations provides annotation-based mapping metadata.

The JPA specification recognizes the interest and the success of the transparent object/relational mapping paradigm. It standardizes the basic APIs and the metadata needed for any object/relational persistence mechanism. Hibernate EntityManager implements the programming interfaces and lifecycle rules as defined by the JPA persistence specification and together with Hibernate Annotations offers a complete (and standalone) JPA persistence solution on top of the mature Hibernate Core. You may use a combination of all three together, annotations without JPA programming interfaces and lifecycle, or even pure native Hibernate Core, depending on the business and technical needs of your project. At all time you can fall back to Hibernate native APIs, or if required, even to native JDBC and SQL.

This release of Hibernate Annotations is based on the final release of the JPA 2 specification (aka JSR-317) and supports all its features (including the optional ones). Hibernate specific features and extensions are also available through unstandardized, Hibernate specific annotations.

If you are moving from previous Hibernate Annotations versions, please have a look at Java Persistence migration guide.

First, set up your classpath (after you have created a new project in your favorite IDE):

Alternatively, import your pom.xml in your favorite IDE and let the dependencies be resolved automatically,

We recommend you use Hibernate Validator and the Bean Validation specification capabilities as its integration with Java Persistence 2 has been standardized. Download Hibernate Validator 4 or above from the Hibernate website and add hibernate-validator.jar and validation-api.jar in your classpath. Alternatively add the following dependency in your pom.xml.

<project>
...
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate-validator-version}</version>
</dependency>
...
</dependencies>
...
</project>

If you wish to use Hibernate Search, download it from the Hibernate website and add hibernate-search.jar and its dependencies in your classpath. Alternatively add the following dependency in your pom.xml.

<project>
...
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search</artifactId>
<version>${hibernate-search-version}</version>
</dependency>
...
</dependencies>
...
</project>

We recommend you use the JPA 2 APIs to bootstrap Hibernate (see the Hibernate EntityManager documentation for more information). If you use Hibernate Core and its native APIs read on.

If you boot Hibernate yourself, make sure to use the AnnotationConfiguration class instead of the Configuration class. Here is an example using the (legacy) HibernateUtil approach:

package hello;


import org.hibernate.*;
import org.hibernate.cfg.*;
import test.*;
import test.animals.Dog;
publicclassHibernateUtil{
privatestaticfinalSessionFactory sessionFactory;
static{
try{
sessionFactory =newAnnotationConfiguration()
.configure().buildSessionFactory();
}catch(Throwable ex){
//Log exception!
thrownewExceptionInInitializerError(ex);
}
}
publicstaticSession getSession()
throwsHibernateException{
return sessionFactory.openSession();
}
}

Interesting here is the use of AnnotationConfiguration. The packages and annotated classes are declared in your regular XML configuration file (usually hibernate.cfg.xml). Here is the equivalent of the above declaration:

<!DOCTYPEhibernate-configurationPUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<mappingpackage="test.animals"/>
<mappingclass="test.Flight"/>
<mappingclass="test.Sky"/>
<mappingclass="test.Person"/>
<mappingclass="test.animals.Dog"/>

<mappingresource="test/animals/orm.xml"/>
</session-factory>
</hibernate-configuration>

Note that you can mix the legacy hbm.xml use and the annotation approach. The resource element can be either an hbm file or an EJB3 XML deployment descriptor. The distinction is transparent for your configuration process.

Alternatively, you can define the annotated classes and packages using the programmatic API

sessionFactory =newAnnotationConfiguration()
 .addPackage("test.animals") //the fully qualified package name
 .addAnnotatedClass(Flight.class)
 .addAnnotatedClass(Sky.class)
 .addAnnotatedClass(Person.class)
 .addAnnotatedClass(Dog.class)
 .addResource("test/animals/orm.xml")

.configure()
.buildSessionFactory();

There is no other difference in the way you use Hibernate APIs with annotations, except for this startup routine change or in the configuration file. You can use your favorite configuration method for other properties ( hibernate.properties, hibernate.cfg.xml, programmatic APIs, etc).

Note

You can mix annotated persistent classes and classic hbm.cfg.xml declarations with the same SessionFactory. You can however not declare a class several times (whether annotated or through hbm.xml). You cannot mix configuration strategies (hbm vs annotations) in an entity hierarchy either.

To ease the migration process from hbm files to annotations, the configuration mechanism detects the mapping duplication between annotations and hbm files. HBM files are then prioritized over annotated metadata on a class to class basis. You can change the priority using hibernate.mapping.precedence property. The default is hbm, class, changing it to class, hbm will prioritize the annotated classes over hbm files when a conflict occurs.

On top of the Hibernate Core properties, Hibernate Annotations reacts to the following one.


Hibernate Annotations utilizes Simple Logging Facade for Java (SLF4J) in order to log various system events. SLF4J can direct your logging output to several logging frameworks (NOP, Simple, log4j version 1.2, JDK 1.4 logging, JCL or logback) depending on your chosen binding. In order to setup logging properly you will need slf4j-api.jar in your classpath together with the jar file for your preferred binding - slf4j-log4j12.jar in the case of Log4J. See the SLF4J documentation for more detail.

The logging categories interesting for Hibernate Annotations are:


For further category configuration refer to the Logging in the Hibernate Core documentation.

JPA entities are plain POJOs. Actually, they are Hibernate persistent entities. Their mappings are defined through JDK 5.0 annotations instead of hbm.xml files. A JPA 2 XML descriptor syntax for overriding is defined as well). Annotations can be split in two categories, the logical mapping annotations (describing the object model, the association between two entities etc.) and the physical mapping annotations (describing the physical schema, tables, columns, indexes, etc). We will mix annotations from both categories in the following code examples.

JPA annotations are in the javax.persistence.* package. You favorite IDE can auto-complete annotations and their attributes for you (even without a specific "JPA" module, since JPA annotations are plain JDK 5 annotations).

A good an complete set of working examples can be found in the Hibernate Annotations test suite itself: most of the unit tests have been designed to represent a concrete example and be a source of inspiration for you. You can get the test suite sources in the distribution.

Every persistent POJO class is an entity and is declared using the @Entity annotation (at the class level):

@Entity

publicclassFlightimplementsSerializable{
Long id;
@Id
publicLong getId(){return id;}
publicvoid setId(Long id){this.id = id;}
}

@Entity declares the class as an entity (i.e. a persistent POJO class), @Id declares the identifier property of this entity. The other mapping declarations are implicit. The class Flight is mapped to the Flight table, using the column id as its primary key column.

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.

@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.

@Entity

@Table(name="tbl_sky")
publicclassSkyimplementsSerializable{
...
}

The @Table element contains a schema and catalog attributes, if they need to be defined. You can also define unique constraints to the table using the @UniqueConstraint annotation in conjunction with @Table (for a unique constraint bound to a single column, it is recommended to use the @Column.unique approach (refer to @Column for more information).

@Table(name="tbl_sky",

uniqueConstraints ={@UniqueConstraint(columnNames={"month","day"})}
)

A unique constraint is applied to the tuple month, day. Note that the columnNames array refers to the logical column names.

The logical column name is defined by the Hibernate NamingStrategy implementation. The default JPA naming strategy uses the physical column name as the logical column name but it could be different if for example you append fld_ to all your columns using a custom NamingStrategy implementation. Note that the logical column name is not necessarily equals to the property name esp when the column name is explicitly set. Unless you override the NamingStrategy, you shouldn't worry about that.

You can add optimistic locking capability to an entity using the @Version annotation:

@Entity

publicclassFlightimplementsSerializable{
...
@Version
@Column(name="OPTLOCK")
publicInteger getVersion(){...}
}

The version property will be mapped to the OPTLOCK column, and the entity manager will use it to detect conflicting updates (preventing lost updates you might otherwise see with the last-commit-wins strategy).

The version column may be a numeric (the recommended solution) or a timestamp. Hibernate supports any kind of type provided that you define and implement the appropriate UserVersionType.

The application must not alter the version number set up by Hibernate in any way. To artificially increase the version number, check in Hibernate Entity Manager's reference documentation LockModeType.OPTIMISTIC_FORCE_INCREMENT or LockModeType.PESSIMISTIC_FORCE_INCREMENT.

Every non static non transient property (field or method depending on the access type) of an entity is considered persistent, unless you annotate it as @Transient. Not having an annotation for your property is equivalent to the appropriate @Basic annotation. The @Basic annotation allows you to declare the fetching strategy for a property:

publictransientint counter;//transient property


privateString firstname;//persistent property
@Transient
String getLengthInMeter(){...}//transient property
String getName(){...}// persistent property
@Basic
int getLength(){...}// persistent property
@Basic(fetch =FetchType.LAZY)
String getDetailedComment(){...}// persistent property
@Temporal(TemporalType.TIME)
java.util.Date getDepartureTime(){...}// persistent property
@Enumerated(EnumType.STRING)
Starred getNote(){...}//enum persisted as String in database

counter, a transient field, and lengthInMeter, a method annotated as @Transient, and will be ignored by the entity manager. name, length, and firstname properties are mapped persistent and eagerly fetched (the default for simple properties). The detailedComment property value will be lazily fetched from the database once a lazy property of the entity is accessed for the first time. Usually you don't need to lazy simple properties (not to be confused with lazy association fetching).

The recommended alternative is to use the projection capability of JP-QL (Java Persistence Query Language) or Criteria queries.

JPA support property mapping of all basic types supported by Hibernate (all basic Java types , their respective wrappers and serializable classes). Hibernate Annotations support out of the box enum type mapping either into a ordinal column (saving the enum ordinal) or a string based column (saving the enum string representation): the persistence representation, defaulted to ordinal, can be overridden through the @Enumerated annotation as shown in the note property example.

In plain Java APIs, the temporal precision of time is not defined. When dealing with temporal data you might want to describe the expected precision in database. Temporal data can have DATE, TIME, or TIMESTAMP precision (ie the actual date, only the time, or both). Use the @Temporal annotation to fine tune that.

@Lob indicates that the property should be persisted in a Blob or a Clob depending on the property type: java.sql.Clob, Character[], char[] and java.lang.String will be persisted in a Clob. java.sql.Blob, Byte[], byte[] and serializable type will be persisted in a Blob.



@Lob
publicString getFullText(){
return fullText;
}
@Lob
publicbyte[] getFullCode(){
return fullCode;
}

If the property type implements java.io.Serializable and is not a basic type, and if the property is not annotated with @Lob, then the Hibernate serializable type is used.

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.

However in some situations, you need to:

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.

To force the access type on a given class, use the @Access annotation as showed below:

@Entity

publicclassOrder{
@IdprivateLong id;
publicLong getId(){return id;}
publicvoid setId(Long id){this.id = id;}
@EmbeddedprivateAddress address;
publicAddress getAddress(){return address;}
publicvoid setAddress(){this.address = address;}
}
@Entity
publicclassUser{
privateLong id;
@IdpublicLong getId(){return id;}
publicvoid setId(Long id){this.id = id;}
privateAddress address;
@EmbeddedpublicAddress getAddress(){return address;}
publicvoid setAddress(){this.address = address;}
}
@Embeddable
@Access(AcessType.PROPERTY)
publicclassAddress{
privateString street1;
publicString getStreet1(){return street1;}
publicvoid setStreet1(){this.street1 = street1;}
private hashCode;//not persistent
}

You can also override the access type of a single property while keeping the other properties standard.

@Entity

publicclassOrder{
@IdprivateLong id;
publicLong getId(){return id;}
publicvoid setId(Long id){this.id = id;}
@TransientprivateString userId;
@TransientprivateString orderId;
@Access(AccessType.PROPERTY)
publicString getOrderNumber(){return userId +":"+ orderId;}
publicvoid setOrderNumber(){this.userId =...;this.orderId =...;}
}

In this example, the default access type is FIELD except for the orderNumber property. Note that the corresponding field, if any must be marked as @Transient or transient.

The column(s) used for a property mapping can be defined using the @Column annotation. Use it to override default values (see the EJB3 specification for more information on the defaults). You can use this annotation at the property level for properties that are:



@Entity
publicclassFlightimplementsSerializable{
...
@Column(updatable =false, name ="flight_name", nullable =false, length=50)
publicString getName(){...}

The name property is mapped to the flight_name column, which is not nullable, has a length of 50 and is not updatable (making the property immutable).

This annotation can be applied to regular properties as well as @Id or @Version properties.

@Column(
 name="colu(1)mnName";
 boolean un(2)ique() default false;
 boolean nu(3)llable() default true;
 boolean in(4)sertable() default true;
 boolean up(5)datable() default true;
 String col(6)umnDefinition() default "";
 String tab(7)le() default "";
 int length(8)() default 255;
 int precis(9)ion() default 0; // decimal precision
 int scale((10)) default 0; // decimal scale

1

name (optional): the column name (default to the property name)

2

unique (optional): set a unique constraint on this column or not (default false)

3

nullable (optional): set the column as nullable (default true).

4

insertable (optional): whether or not the column will be part of the insert statement (default true)

5

updatable (optional): whether or not the column will be part of the update statement (default true)

6

columnDefinition (optional): override the sql DDL fragment for this particular column (non portable)

7

table (optional): define the targeted table (default primary table)

8

length (optional): column length (default 255)

8

precision (optional): column decimal precision (default 0)

10

scale (optional): column decimal scale if useful (default 0)

It is possible to declare an embedded component inside an entity and even override its column mapping. Component classes have to be annotated at the class level with the @Embeddable annotation. It is possible to override the column mapping of an embedded object for a particular entity using the @Embedded and @AttributeOverride annotation in the associated property:

@Entity

publicclassPersonimplementsSerializable{
//Persistent component using defaults
Address homeAddress;
@Embedded
@AttributeOverrides({
@AttributeOverride(name="iso2", column = @Column(name="bornIso2")),
@AttributeOverride(name="name", column = @Column(name="bornCountryName"))
})
Country bornIn;
...
}
@Embeddable

publicclassAddressimplementsSerializable{
String city;
Country nationality;//no overriding here
}
@Embeddable

publicclassCountryimplementsSerializable{
privateString iso2;
@Column(name="countryName")privateString name;
publicString getIso2(){return iso2;}
publicvoid setIso2(String iso2){this.iso2 = iso2;}

publicString getName(){return name;}
publicvoid setName(String name){this.name = name;}
...
}

An embeddable object inherits the access type of its owning entity (note that you can override that using the @Access annotation).

The Person entity has two component properties, homeAddress and bornIn. homeAddress property has not been annotated, but Hibernate will guess that it is a persistent component by looking for the @Embeddable annotation in the Address class. We also override the mapping of a column name (to bornCountryName) with the @Embedded and @AttributeOverride annotations for each mapped attribute of Country. As you can see, Country is also a nested component of Address, again using auto-detection by Hibernate and JPA defaults. Overriding columns of embedded objects of embedded objects is through dotted expressions.

  @Embedded

@AttributeOverrides({
@AttributeOverride(name="city", column = @Column(name="fld_city")),
@AttributeOverride(name="nationality.iso2", column = @Column(name="nat_Iso2")),
@AttributeOverride(name="nationality.name", column = @Column(name="nat_CountryName"))
//nationality columns in homeAddress are overridden
})
Address homeAddress;

Hibernate Annotations supports something that is not explicitly supported by the JPA specification. You can annotate a embedded object with the @MappedSuperclass annotation to make the superclass properties persistent (see @MappedSuperclass for more informations).

You can also use association annotations in an embeddable object (ie @OneToOne, @ManyToOne, @OneToMany or @ManyToMany). To override the association columns you can use @AssociationOverride.

If you want to have the same embeddable object type twice in the same entity, the column name defaulting will not work as several embedded objects would share the same set of columns. In plain JPA, you need to override at least one set of columns. Hibernate, however, allows you to enhance the default naming mechanism through the NamingStrategy interface. You can write a strategy that prevent name clashing in such a situation. DefaultComponentSafeNamingStrategy is an example of this.

The @Id annotation lets you define which property is the identifier of your entity. This property can be set by the application itself or be generated by Hibernate (preferred). You can define the identifier generation strategy thanks to the @GeneratedValue annotation.

JPA defines five types of identifier generation strategies:

Hibernate provides more id generators than the basic JPA ones. Check Section 2.4, "Hibernate Annotation Extensions" for more informations.

The following example shows a sequence generator using the SEQ_STORE configuration (see below)

@Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE")

publicInteger getId(){...}

The next example uses the identity generator:

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)

publicLong getId(){...}

The AUTO generator is the preferred type for portable applications (across several DB vendors). The identifier generation configuration can be shared for several @Id mappings with the generator attribute. There are several configurations available through @SequenceGenerator and @TableGenerator. The scope of a generator can be the application or the class. Class-defined generators are not visible outside the class and can override application level generators. Application level generators are defined at XML level (see Chapter 3, Overriding metadata through XML):

<table-generator name="EMP_GEN"

table="GENERATOR_TABLE"
pk-column-name="key"
value-column-name="hi"
pk-column-value="EMP"
allocation-size="20"/>
//and the annotation equivalent
@javax.persistence.TableGenerator(
name="EMP_GEN",
table="GENERATOR_TABLE",
pkColumnName ="key",
valueColumnName ="hi"
pkColumnValue="EMP",
allocationSize=20
)
<sequence-generator name="SEQ_GEN"
sequence-name="my_sequence"
allocation-size="20"/>
//and the annotation equivalent
@javax.persistence.SequenceGenerator(
name="SEQ_GEN",
sequenceName="my_sequence",
allocationSize=20
)

If JPA XML (like META-INF/orm.xml) is used to define the generators, EMP_GEN and SEQ_GEN are application level generators. EMP_GEN defines a table based id generator using the hilo algorithm with a max_lo of 20. The hi value is kept in a table "GENERATOR_TABLE". The information is kept in a row where pkColumnName "key" is equals to pkColumnValue "EMP" and column valueColumnName "hi" contains the the next high value used.

SEQ_GEN defines a sequence generator using a sequence named my_sequence. The allocation size used for this sequence based hilo algorithm is 20. Note that this version of Hibernate Annotations does not handle initialValue in the sequence generator. The default allocation size is 50, so if you want to use a sequence and pickup the value each time, you must set the allocation size to 1.

Important

We recommend all new projects to use hibernate.id.new_generator_mappings=true as the new generators are more efficient and closer to the JPA 2 specification semantic. However they are not backward compatible with existing databases (if a sequence or a table is used for id generation). See Section 1.3, "Properties" for more information on how to activate them.

Note

Package level definition is not supported by the JPA specification. However, you can use the @GenericGenerator at the package level (see Section 2.4.2, "Identifier").

The next example shows the definition of a sequence generator in a class scope:

@Entity

@javax.persistence.SequenceGenerator(
name="SEQ_STORE",
sequenceName="my_sequence"
)
publicclassStoreimplementsSerializable{
privateLong id;
@Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE")
publicLong getId(){return id;}
}

This class will use a sequence named my_sequence and the SEQ_STORE generator is not visible in other classes. Note that you can check the Hibernate Annotations tests in the org.hibernate.test.annotations.id package for more examples.

Finally, you can ask Hibernate to copy the identifier from another associated entity. In the Hibernate jargon, it is known as a foreign generator but the JPA mapping reads better and is encouraged.

@Entity

classMedicalHistoryimplementsSerializable{
@Id @OneToOne
@JoinColumn(name ="person_id")
Person patient;
}
@Entity
publicclassPersonimplementsSerializable{
@Id @GeneratedValueInteger id;
}

Or alternatively

@Entity

classMedicalHistoryimplementsSerializable{
@IdInteger id;
@MapsId @OneToOne
@JoinColumn(name ="patient_id")
Person patient;
}
@Entity
classPerson{
@Id @GeneratedValueInteger id;
}

If you are interested in more examples of "derived identities", the JPA 2 specification has a great set of them in chapter 2.4.1.3.

But an identifier does not have to be a single property, it can be composed of several properties.

You can define a composite primary key through several syntaxes:

As you can see the last case is far from obvious. It has been inherited from the dark ages of EJB 2 for backward compatibilities and we recommend you not to use it (for simplicity sake).

Let's explore all three cases using examples.

Here is a simple example of @EmbeddedId.

@Entity

classUser{
@EmbeddedId
@AttributeOverride(name="firstName", column=@Column(name="fld_firstname")
UserId id;
Integer age;
}
@Embeddable
classUserIdimplementsSerializable{
String firstName;
String lastName;
}

You can notice that the UserId class is serializable. To override the column mapping, use @AttributeOverride.

An embedded id can itself contains the primary key of an associated entity.

@Entity

classCustomer{
@EmbeddedIdCustomerId id;
boolean preferredCustomer;
@MapsId("userId")
@JoinColumns({
@JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
@JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
})
@OneToOneUser user;
}
@Embeddable
classCustomerIdimplementsSerializable{
UserId userId;
String customerNumber;
}
@Entity
classUser{
@EmbeddedIdUserId id;
Integer age;
}
@Embeddable
classUserIdimplementsSerializable{
String firstName;
String lastName;
}

In the embedded id object, the association is represented as the identifier of the associated entity. But you can link its value to a regular association in the entity via the @MapsId annotation. The @MapsId value correspond to the property name of the embedded id object containing the associated entity's identifier. In the database, it means that the Customer.user and the CustomerId.userId properties share the same underlying column (user_fk in this case).

In practice, your code only sets the Customer.user property and the user id value is copied by Hibernate into the CustomerId.userId property.

While not supported in JPA, Hibernate lets you place your association directly in the embedded id component (instead of having to use the @MapsId annotation).

@Entity

classCustomer{
@EmbeddedIdCustomerId id;
boolean preferredCustomer;
}
@Embeddable
classCustomerIdimplementsSerializable{
@OneToOne
@JoinColumns({
@JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
@JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
})
User user;
String customerNumber;
}
@Entity
classUser{
@EmbeddedIdUserId id;
Integer age;
}
@Embeddable
classUserIdimplementsSerializable{
String firstName;
String lastName;
}

@IdClass on an entity points to the class (component) representing the identifier of the class. The properties marked @Id on the entity must have their corresponding property on the @IdClass. The return type of search twin property must be either identical for basic properties or must correspond to the identifier class of the associated entity for an association.

@Entity

classCustomer{
@Id @OneToOne
@JoinColumns({
@JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
@JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
})
User user;

@IdString customerNumber;
boolean preferredCustomer;
}
classCustomerIdimplementsSerializable{
UserId user;
String customerNumber;
}
@Entity
classUser{
@EmbeddedIdUserId id;
Integer age;
}
@Embeddable
classUserIdimplementsSerializable{
String firstName;
String lastName;
}

Customer and CustomerId do have the same properties customerNumber as well as user.

While not JPA standard, Hibernate let's you declare the vanilla associated property in the @IdClass.

@Entity

classCustomer{
@Id @OneToOne
@JoinColumns({
@JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),
@JoinColumn(name="userlastname_fk", referencedColumnName="lastName")
})
User user;

@IdString customerNumber;
boolean preferredCustomer;
}
classCustomerIdimplementsSerializable{
@OneToOneUser user;
String customerNumber;
}
@Entity
classUser{
@EmbeddedIdUserId id;
Integer age;
}
@Embeddable
classUserIdimplementsSerializable{
String firstName;
String lastName;
}

Hibernate supports the automatic generation of some of the identifier properties. Simply use the @GeneratedValue annotation on one or several id properties.

@Entity

publicclassCustomerInventoryimplementsSerializable{
@Id
@TableGenerator(name ="inventory",
table ="U_SEQUENCES",
pkColumnName ="S_ID",
valueColumnName ="S_NEXTNUM",
pkColumnValue ="inventory",
allocationSize =1000)
@GeneratedValue(strategy =GenerationType.TABLE, generator ="inventory")
Integer id;
@Id @ManyToOne(cascade =CascadeType.MERGE)
Customer customer;
}
@Entity
publicclassCustomerimplementsSerializable{
@Id
privateint id;
}

You can also generate properties inside an @EmbeddedId class.

EJB3 supports the three types of inheritance:

The chosen strategy is declared at the class level of the top level entity in the hierarchy using the @Inheritance annotation.

All properties of all super- and subclasses are mapped into the same table, instances are distinguished by a special discriminator column:

@Entity

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name="planetype",
discriminatorType=DiscriminatorType.STRING
)
@DiscriminatorValue("Plane")
publicclassPlane{...}
@Entity
@DiscriminatorValue("A320")
publicclass A320 extendsPlane{...}

Plane is the superclass, it defines the inheritance strategy InheritanceType.SINGLE_TABLE. It also defines the discriminator column through the @DiscriminatorColumn annotation, a discriminator column can also define the discriminator type. Finally, the @DiscriminatorValue annotation defines the value used to differentiate a class in the hierarchy. All of these attributes have sensible default values. The default name of the discriminator column is DTYPE. The default discriminator value is the entity name (as defined in @Entity.name) for DiscriminatorType.STRING. A320 is a subclass; you only have to define discriminator value if you don't want to use the default value. The strategy and the discriminator type are implicit.

@Inheritance and @DiscriminatorColumn should only be defined at the top of the entity hierarchy.

This is sometimes useful to share common properties through a technical or a business superclass without including it as a regular mapped entity (ie no specific table for this entity). For that purpose you can map them as @MappedSuperclass.

@MappedSuperclass

publicclassBaseEntity{
@Basic
@Temporal(TemporalType.TIMESTAMP)
publicDate getLastUpdate(){...}
publicString getLastUpdater(){...}
...
}
@EntityclassOrderextendsBaseEntity{
@IdpublicInteger getId(){...}
...
}

In database, this hierarchy will be represented as an Order table having the id, lastUpdate and lastUpdater columns. The embedded superclass property mappings are copied into their entity subclasses. Remember that the embeddable superclass is not the root of the hierarchy though.

You can override columns defined in entity superclasses at the root entity level using the @AttributeOverride annotation.

@MappedSuperclass

publicclassFlyingObjectimplementsSerializable{
publicint getAltitude(){
return altitude;
}
@Transient
publicint getMetricAltitude(){
return metricAltitude;
}
@ManyToOne
publicPropulsionType getPropulsion(){
return metricAltitude;
}
...
}
@Entity
@AttributeOverride( name="altitude", column = @Column(name="fld_altitude"))
@AssociationOverride(
name="propulsion",
joinColumns = @JoinColumn(name="fld_propulsion_fk")
)
publicclassPlaneextendsFlyingObject{
...
}

The altitude property will be persisted in an fld_altitude column of table Plane and the propulsion association will be materialized in a fld_propulsion_fk foreign key column.

You can define @AttributeOverride(s) and @AssociationOverride(s) on @Entity classes, @MappedSuperclass classes and properties pointing to an @Embeddable object.

You can associate entities through a one-to-one relationship using @OneToOne. There are three cases for one-to-one associations: either the associated entities share the same primary keys values, a foreign key is held by one of the entities (note that this FK column in the database should be constrained unique to simulate one-to-one multiplicity), or a association table is used to store the link between the 2 entities (a unique constraint has to be defined on each fk to ensure the one to one multiplicity).

First, we map a real one-to-one association using shared primary keys:

@Entity

publicclassBody{
@Id
publicLong getId(){return id;}
@OneToOne(cascade =CascadeType.ALL)
@PrimaryKeyJoinColumn
publicHeart getHeart(){
return heart;
}
...
}
@Entity

publicclassHeart{
@Id
publicLong getId(){...}
}

The @PrimaryKeyJoinColumn annotation does say that the primary key of the entity is used as the foreign key value to the associated entity.

In the following example, the associated entities are linked through an explicit foreign key column:

@Entity

publicclassCustomerimplementsSerializable{
@OneToOne(cascade =CascadeType.ALL)
@JoinColumn(name="passport_fk")
publicPassport getPassport(){
...
}
@Entity
publicclassPassportimplementsSerializable{
@OneToOne(mappedBy ="passport")
publicCustomer getOwner(){
...
}

A Customer is linked to a Passport, with a foreign key column named passport_fk in the Customer table. The join column is declared with the @JoinColumn annotation which looks like the @Column annotation. It has one more parameters named referencedColumnName. This parameter declares the column in the targeted entity that will be used to the join. Note that when using referencedColumnName to a non primary key column, the associated class has to be Serializable. Also note that the referencedColumnName to a non primary key column has to be mapped to a property having a single column (other cases might not work).

The association may be bidirectional. In a bidirectional relationship, one of the sides (and only one) has to be the owner: the owner is responsible for the association column(s) update. To declare a side as not responsible for the relationship, the attribute mappedBy is used. mappedBy refers to the property name of the association on the owner side. In our case, this is passport. As you can see, you don't have to (must not) declare the join column since it has already been declared on the owners side.

If no @JoinColumn is declared on the owner side, the defaults apply. A join column(s) will be created in the owner table and its name will be the concatenation of the name of the relationship in the owner side, _ (underscore), and the name of the primary key column(s) in the owned side. In this example passport_id because the property name is passport and the column id of Passport is id.

The third possibility (using an association table) is quite exotic.

@Entity

publicclassCustomerimplementsSerializable{
@OneToOne(cascade =CascadeType.ALL)
@JoinTable(name ="CustomerPassports",
joinColumns = @JoinColumn(name="customer_fk"),
inverseJoinColumns = @JoinColumn(name="passport_fk")
)
publicPassport getPassport(){
...
}
@Entity
publicclassPassportimplementsSerializable{
@OneToOne(mappedBy ="passport")
publicCustomer getOwner(){
...
}

A Customer is linked to a Passport through a association table named CustomerPassports ; this association table has a foreign key column named passport_fk pointing to the Passport table (materialized by the inverseJoinColumn, and a foreign key column named customer_fk pointing to the Customer table materialized by the joinColumns attribute.

You must declare the join table name and the join columns explicitly in such a mapping.

Many-to-one associations are declared at the property level with the annotation @ManyToOne:

@Entity()

publicclassFlightimplementsSerializable{
@ManyToOne( cascade ={CascadeType.PERSIST,CascadeType.MERGE})
@JoinColumn(name="COMP_ID")
publicCompany getCompany(){
return company;
}
...
}

The @JoinColumn attribute is optional, the default value(s) is like in one to one, the concatenation of the name of the relationship in the owner side, _ (underscore), and the name of the primary key column in the owned side. In this example company_id because the property name is company and the column id of Company is id.

@ManyToOne has a parameter named targetEntity which describes the target entity name. You usually don't need this parameter since the default value (the type of the property that stores the association) is good in almost all cases. However this is useful when you want to use interfaces as the return type instead of the regular entity.

@Entity

publicclassFlightimplementsSerializable{
@ManyToOne( cascade ={CascadeType.PERSIST,CascadeType.MERGE}, targetEntity=CompanyImpl.class)
@JoinColumn(name="COMP_ID")
publicCompany getCompany(){
return company;
}
...
}
publicinterfaceCompany{
...
}

You can also map a many-to-one association through an association table. This association table described by the @JoinTable annotation will contains a foreign key referencing back the entity table (through @JoinTable.joinColumns) and a a foreign key referencing the target entity table (through @JoinTable.inverseJoinColumns).

@Entity

publicclassFlightimplementsSerializable{
@ManyToOne( cascade ={CascadeType.PERSIST,CascadeType.MERGE})
@JoinTable(name="Flight_Company",
joinColumns = @JoinColumn(name="FLIGHT_ID"),
inverseJoinColumns = @JoinColumn(name="COMP_ID")
)
publicCompany getCompany(){
return company;
}
...
}

You can map Collection, List, Map and Set pointing to associated entities as one-to-many or many-to-many associations using the @OneToMany or @ManyToMany annotation respectively. If the collection is of a basic type or of an embeddable type, use @ElementCollection. We will describe that in more detail in the following subsections.

One-to-many associations are declared at the property level with the annotation @OneToMany. One to many associations may be bidirectional.

Since many to one are (almost) always the owner side of a bidirectional relationship in the JPA spec, the one to many association is annotated by @OneToMany(mappedBy=...)

@Entity

publicclassTroop{
@OneToMany(mappedBy="troop")
publicSet<Soldier> getSoldiers(){
...
}
@Entity
publicclassSoldier{
@ManyToOne
@JoinColumn(name="troop_fk")
publicTroop getTroop(){
...
}

Troop has a bidirectional one to many relationship with Soldier through the troop property. You don't have to (must not) define any physical mapping in the mappedBy side.

To map a bidirectional one to many, with the one-to-many side as the owning side, you have to remove the mappedBy element and set the many to one @JoinColumn as insertable and updatable to false. This solution is not optimized and will produce some additional UPDATE statements.

@Entity

publicclassTroop{
@OneToMany
@JoinColumn(name="troop_fk")//we need to duplicate the physical information
publicSet<Soldier> getSoldiers(){
...
}
@Entity
publicclassSoldier{
@ManyToOne
@JoinColumn(name="troop_fk", insertable=false, updatable=false)
publicTroop getTroop(){
...
}

Without describing any physical mapping, a unidirectional one to many with join table is used. The table name is the concatenation of the owner table name, _, and the other side table name. The foreign key name(s) referencing the owner table is the concatenation of the owner table, _, and the owner primary key column(s) name. The foreign key name(s) referencing the other side is the concatenation of the owner property name, _, and the other side primary key column(s) name. A unique constraint is added to the foreign key referencing the other side table to reflect the one to many.

@Entity

publicclassTrainer{
@OneToMany
publicSet<Tiger> getTrainedTigers(){
...
}
@Entity
publicclassTiger{
...//no bidir
}

Trainer describes a unidirectional relationship with Tiger using the join table Trainer_Tiger, with a foreign key trainer_id to Trainer (table name, _, trainer id) and a foreign key trainedTigers_id to Monkey (property name, _, Tiger primary column).

A many-to-many association is defined logically using the @ManyToMany annotation. You also have to describe the association table and the join conditions using the @JoinTable annotation. If the association is bidirectional, one side has to be the owner and one side has to be the inverse end (ie. it will be ignored when updating the relationship values in the association table):

@Entity

publicclassEmployerimplementsSerializable{
@ManyToMany(
targetEntity=org.hibernate.test.metadata.manytomany.Employee.class,
cascade={CascadeType.PERSIST,CascadeType.MERGE}
)
@JoinTable(
name="EMPLOYER_EMPLOYEE",
joinColumns=@JoinColumn(name="EMPER_ID"),
inverseJoinColumns=@JoinColumn(name="EMPEE_ID")
)
publicCollection getEmployees(){
return employees;
}
...
}
@Entity

publicclassEmployeeimplementsSerializable{
@ManyToMany(
cascade ={CascadeType.PERSIST,CascadeType.MERGE},
mappedBy ="employees",
targetEntity =Employer.class
)
publicCollection getEmployers(){
return employers;
}
}

We've already shown the many declarations and the detailed attributes for associations. We'll go deeper in the @JoinTable description, it defines a name, an array of join columns (an array in annotation is defined using { A, B, C }), and an array of inverse join columns. The latter ones are the columns of the association table which refer to the Employee primary key (the "other side").

As seen previously, the other side don't have to (must not) describe the physical mapping: a simple mappedBy argument containing the owner side property name bind the two.

As any other annotations, most values are guessed in a many to many relationship. Without describing any physical mapping in a unidirectional many to many the following rules applied. The table name is the concatenation of the owner table name, _ and the other side table name. The foreign key name(s) referencing the owner table is the concatenation of the owner table name, _ and the owner primary key column(s). The foreign key name(s) referencing the other side is the concatenation of the owner property name, _, and the other side primary key column(s). These are the same rules used for a unidirectional one to many relationship.



@Entity
publicclassStore{
@ManyToMany(cascade =CascadeType.PERSIST)
publicSet<City> getImplantedIn(){
...
}
}
@Entity
publicclassCity{
...//no bidirectional relationship
}

A Store_City is used as the join table. The Store_id column is a foreign key to the Store table. The implantedIn_id column is a foreign key to the City table.

Without describing any physical mapping in a bidirectional many to many the following rules applied. The table name is the concatenation of the owner table name, _ and the other side table name. The foreign key name(s) referencing the owner table is the concatenation of the other side property name, _, and the owner primary key column(s). The foreign key name(s) referencing the other side is the concatenation of the owner property name, _, and the other side primary key column(s). These are the same rules used for a unidirectional one to many relationship.

@Entity

publicclassStore{
@ManyToMany(cascade ={CascadeType.PERSIST,CascadeType.MERGE})
publicSet<Customer> getCustomers(){
...
}
}
@Entity
publicclassCustomer{
@ManyToMany(mappedBy="customers")
publicSet<Store> getStores(){
...
}
}

A Store_Customer is used as the join table. The stores_id column is a foreign key to the Store table. The customers_id column is a foreign key to the Customer table.

In some simple situation, do don't need to associate two entities but simply create a collection of basic types or embeddable objects. Use the @ElementCollection in this case.

@Entity

publicclassUser{
[...]
publicString getLastname(){...}
@ElementCollection
@CollectionTable(name="Nicknames", joinColumns=@JoinColumn(name="user_id"))
@Column(name="nickname")
publicSet<String> getNicknames(){...}
}

The collection table holding the collection data is set using the @CollectionTable annotation. If omitted the collection table name default to the concatenation of the name of the containing entity and the name of the collection attribute, separated by an underscore: in our example, it would be User_nicknames.

The column holding the basic type is set using the @Column annotation. If omitted, the column name defaults to the property name: in our example, it would be nicknames.

But you are not limited to basic types, the collection type can be any embeddable object. To override the columns of the embeddable object in the collection table, use the @AttributeOverride annotation.

@Entity

publicclassUser{
[...]
publicString getLastname(){...}
@ElementCollection
@CollectionTable(name="Addresses", joinColumns=@JoinColumn(name="user_id"))
@AttributeOverrides({
@AttributeOverride(name="street1", column=@Column(name="fld_street"))
})
publicSet<Address> getAddresses(){...}
}
@Embeddable
publicclassAddress{
publicString getStreet1(){...}
[...]
}

Such an embeddable object cannot contains a collection itself.

Lists can be mapped in two different ways:

To order lists in memory, add @javax.persistence.OrderBy to your property. This annotation takes into parameter a list of comma separated properties (of the target entity) and order the collection accordingly (eg firstname asc, age desc), if the string is empty, the collection will be ordered by the primary key of the target entity.

@Entity

publicclassCustomer{
@Id @GeneratedValuepublicInteger getId(){return id;}
publicvoid setId(Integer id){this.id = id;}
privateInteger id;
@OneToMany(mappedBy="customer")
@OrderBy("number")
publicList<Order> getOrders(){return orders;}
publicvoid setOrders(List<Order> orders){this.orders = orders;}
privateList<Order> orders;
}
@Entity
publicclassOrder{
@Id @GeneratedValuepublicInteger getId(){return id;}
publicvoid setId(Integer id){this.id = id;}
privateInteger id;
publicString getNumber(){return number;}
publicvoid setNumber(String number){this.number = number;}
privateString number;
@ManyToOne
publicCustomer getCustomer(){return customer;}
publicvoid setCustomer(Customer customer){this.customer = customer;}
privateCustomer number;
}
--Table schema
|-------------||----------|
|Order||Customer|
|-------------||----------|
| id || id |
| number ||----------|
| customer_id |
|-------------|

To store the index value in a dedicated column, use the @javax.persistence.OrderColumn annotation on your property. This annotations describes the column name and attributes of the column keeping the index value. This column is hosted on the table containing the association foreign key. If the column name is not specified, the default is the name of the referencing property, followed by underscore, followed by ORDER (in the following example, it would be orders_ORDER).

@Entity

publicclassCustomer{
@Id @GeneratedValuepublicInteger getId(){return id;}
publicvoid setId(Integer id){this.id = id;}
privateInteger id;
@OneToMany(mappedBy="customer")
@OrderColumn(name"orders_index")
publicList<Order> getOrders(){return orders;}
publicvoid setOrders(List<Order> orders){this.orders = orders;}
privateList<Order> orders;
}
@Entity
publicclassOrder{
@Id @GeneratedValuepublicInteger getId(){return id;}
publicvoid setId(Integer id){this.id = id;}
privateInteger id;
publicString getNumber(){return number;}
publicvoid setNumber(String number){this.number = number;}
privateString number;
@ManyToOne
publicCustomer getCustomer(){return customer;}
publicvoid setCustomer(Customer customer){this.customer = customer;}
privateCustomer number;
}
--Table schema
|--------------||----------|
|Order||Customer|
|--------------||----------|
| id || id |
| number ||----------|
| customer_id |
| orders_index |
|--------------|

Likewise, maps can borrow their keys from one of the associated entity properties or have dedicated columns to store an explicit key.

To use one of the target entity property as a key of the map, use @MapKey(name="myProperty") (myProperty is a property name in the target entity). When using @MapKey (without property name), the target entity primary key is used. The map key uses the same column as the property pointed out: there is no additional column defined to hold the map key, and it does make sense since the map key actually represent a target property. Be aware that once loaded, the key is no longer kept in sync with the property, in other words, if you change the property value, the key will not change automatically in your Java model.

@Entity

publicclassCustomer{
@Id @GeneratedValuepublicInteger getId(){return id;}
publicvoid setId(Integer id){this.id = id;}
privateInteger id;
@OneToMany(mappedBy="customer")
@MapKey(name"number")
publicMap<String,Order> getOrders(){return orders;}
publicvoid setOrders(Map<String,Order> order){this.orders = orders;}
privateMap<String,Order> orders;
}
@Entity
publicclassOrder{
@Id @GeneratedValuepublicInteger getId(){return id;}
publicvoid setId(Integer id){this.id = id;}
privateInteger id;
publicString getNumber(){return number;}
publicvoid setNumber(String number){this.number = number;}
privateString number;
@ManyToOne
publicCustomer getCustomer(){return customer;}
publicvoid setCustomer(Customer customer){this.customer = customer;}
privateCustomer number;
}
--Table schema
|-------------||----------|
|Order||Customer|
|-------------||----------|
| id || id |
| number ||----------|
| customer_id |
|-------------|

Otherwise, the map key is mapped to a dedicated column or columns. To customize things, use one of the following annotations:

You can also use @MapKeyClass to define the type of the key if you don't use generics (at this stage, you should wonder why at this day and age you don't use generics).

@Entity

publicclassCustomer{
@Id @GeneratedValuepublicInteger getId(){return id;}
publicvoid setId(Integer id){this.id = id;}
privateInteger id;
@OneToMany @JoinTable(name="Cust_Order")
@MapKeyColumn(name"orders_number")
publicMap<String,Order> getOrders(){return orders;}
publicvoid setOrders(Map<String,Order> orders){this.orders = orders;}
privateMap<String,Order> orders;
}
@Entity
publicclassOrder{
@Id @GeneratedValuepublicInteger getId(){return id;}
publicvoid setId(Integer id){this.id = id;}
privateInteger id;
publicString getNumber(){return number;}
publicvoid setNumber(String number){this.number = number;}
privateString number;
@ManyToOne
publicCustomer getCustomer(){return customer;}
publicvoid setCustomer(Customer customer){this.customer = customer;}
privateCustomer number;
}
--Table schema
|-------------||----------||---------------|
|Order||Customer||Cust_Order|
|-------------||----------||---------------|
| id || id || customer_id |
| number ||----------|| order_id |
| customer_id || orders_number |
|-------------||---------------|

Let's now explore the various collection semantics based on the mapping you are choosing.


Specifically, java.util.List collections without @OrderColumn or @IndexColumn are going to be considered as bags.

More support for collections are available via Hibernate specific extensions (see Section 2.4, "Hibernate Annotation Extensions").

You probably have noticed the cascade attribute taking an array of CascadeType as a value. The cascade concept in JPA is very is similar to the transitive persistence and cascading of operations in Hibernate, but with slightly different semantics and cascading types:

Please refer to the chapter 6.3 of the JPA specification for more information on cascading and create/merge semantics.

You can also enable the orphan removal semantic. If an entity is removed from a @OneToMany collection or an associated entity is dereferenced from a @OneToOne association, this associated entity can be marked for deletion if orphanRemoval is set to true. In a way, it means that the associated entity's lifecycle is bound to the owning entity just like an embeddable object is.

@EntityclassCustomer{

@OneToMany(orphanRemoval=true)publicSet<Order> getOrders(){return orders;}
publicvoid setOrders(Set<Order> orders){this.orders = orders;}
privateSet<Order> orders;
[...]
}
@EntityclassOrder{...}
Customer customer = em.find(Customer.class,1l);
Order order = em.find(Order.class,1l);
customer.getOrders().remove(order);//order will be deleted by cascade

You have the ability to either eagerly or lazily fetch associated entities. The fetch parameter can be set to FetchType.LAZY or FetchType.EAGER. EAGER will try to use an outer join select to retrieve the associated object, while LAZY will only trigger a select when the associated object is accessed for the first time. @OneToMany and @ManyToMany associations are defaulted to LAZY and @OneToOne and @ManyToOne are defaulted to EAGER. For more information about static fetching, check Section 2.4.5.1, "Lazy options and fetching modes".

The recommanded approach is to use LAZY on all static fetching definitions and override this choice dynamically through JP-QL. JP-QL has a fetch keyword that allows you to override laziness when doing a particular query. This is very useful to improve performance and is decided on a use case to use case basis.

Composite primary keys use a embedded class as the primary key representation, so you'd use the @Id and @Embeddable annotations. Alternatively, you can use the @EmbeddedId annotation. Note that the dependent class has to be serializable and implements equals()/hashCode(). You can also use @IdClass. These are more detailed in Section 2.2.3, "Mapping identifier properties".

@Entity

publicclassRegionalArticleimplementsSerializable{
@Id
publicRegionalArticlePk getPk(){...}
}
@Embeddable
publicclassRegionalArticlePkimplementsSerializable{...}

or alternatively

@Entity

publicclassRegionalArticleimplementsSerializable{
@EmbeddedId
publicRegionalArticlePk getPk(){...}
}
publicclassRegionalArticlePkimplementsSerializable{...}

@Embeddable inherit the access type of its owning entity unless @Access is used. Composite foreign keys (if not using the default sensitive values) are defined on associations using the @JoinColumns element, which is basically an array of @JoinColumn. It is considered a good practice to express referencedColumnNames explicitly. Otherwise, Hibernate will suppose that you use the same order of columns as in the primary key declaration.

@Entity

publicclassParentimplementsSerializable{
@Id
publicParentPk id;
publicint age;
@OneToMany(cascade=CascadeType.ALL)
@JoinColumns({
@JoinColumn(name="parentCivility", referencedColumnName ="isMale"),
@JoinColumn(name="parentLastName", referencedColumnName ="lastName"),
@JoinColumn(name="parentFirstName", referencedColumnName ="firstName")
})
publicSet<Child> children;//unidirectional
...
}
@Entity

publicclassChildimplementsSerializable{
@Id @GeneratedValue
publicInteger id;
@ManyToOne
@JoinColumns({
@JoinColumn(name="parentCivility", referencedColumnName ="isMale"),
@JoinColumn(name="parentLastName", referencedColumnName ="lastName"),
@JoinColumn(name="parentFirstName", referencedColumnName ="firstName")
})
publicParent parent;//unidirectional
}
@Embeddable

publicclassParentPkimplementsSerializable{
String firstName;
String lastName;
...
}

Note the explicit usage of the referencedColumnName.

You can map a single entity to several tables using the @SecondaryTable or @SecondaryTables class level annotations. To express that a column is in a particular table, use the table parameter of @Column or @JoinColumn.

@Entity

@Table(name="MainCat")
@SecondaryTables({
@SecondaryTable(name="Cat1", pkJoinColumns={
@PrimaryKeyJoinColumn(name="cat_id", referencedColumnName="id")
),
@SecondaryTable(name="Cat2", uniqueConstraints={@UniqueConstraint(columnNames={"storyPart2"})})
})
publicclassCatimplementsSerializable{
privateInteger id;
privateString name;
privateString storyPart1;
privateString storyPart2;
@Id @GeneratedValue
publicInteger getId(){
return id;
}
publicString getName(){
return name;
}

@Column(table="Cat1")
publicString getStoryPart1(){
return storyPart1;
}
@Column(table="Cat2")
publicString getStoryPart2(){
return storyPart2;
}
}

In this example, name will be in MainCat. storyPart1 will be in Cat1 and storyPart2 will be in Cat2. Cat1 will be joined to MainCat using the cat_id as a foreign key, and Cat2 using id (ie the same column name, the MainCat id column has). Plus a unique constraint on storyPart2 has been set.

Hibernate offers naturally a first level cache for entities called a persistence context via the notion of Session. This cache is contextual to the use case at hand. Some entities however are shared by many different use cases and are barely changed. You can cache these in what is called the second level cache.

By default, entities are not part of the second level cache. While we do not recommend that, you can override this by setting the shared-cache-mode element in your persistence.xml file or by using the javax.persistence.sharedCache.mode property. The following values are possible:

The cache concurrency strategy used by default can be set with the hibernate.cache.default_cache_concurrency_strategy property:

@Entity @Cacheable

@Cache(usage =CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
publicclassForest{...}

Hibernate also let's you cache the content of a collection or the identifiers if the collection contains other entities. Use the @Cache annotation on the collection property.

@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)

@JoinColumn(name="CUST_ID")
@Cache(usage =CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
publicSortedSet<Ticket> getTickets(){
return tickets;
}

@org.hibernate.annotations.Cache defines the caching strategy and region of a given second level cache.

@Cache(
 CacheConcu(1)rrencyStrategy usage();
 String reg(2)ion() default "";
 String inc(3)lude() default "all";
)

1

usage: the given cache concurrency strategy (NONE, READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, TRANSACTIONAL)

2

region (optional): the cache region (default to the fqcn of the class or the fq role name of the collection)

3

include (optional): all to include all properties, non-lazy to only include non lazy properties (default all).

While you can write queries in your code, it is considered a good practice to externalize them:

Unfortunately, you lose the type-safety of queries written using the Criteria API.

You can map JP-QL/HQL queries using annotations. @NamedQuery and @NamedQueries can be defined at the class level or in a JPA XML deployment descriptor. However their definitions are global to the session factory/entity manager factory scope. A named query is defined by its name and the actual query string.

<entity-mappings>

<named-query name="plane.getAll">
<query>select p from Plane p</query>
</named-query>
...
</entity-mappings>
...
@Entity
@NamedQuery(name="night.moreRecentThan", query="select n from Night n where n.date >= :date")
publicclassNight{
...
}
publicclassMyDao{
doStuff(){
Query q = s.getNamedQuery("night.moreRecentThan");
q.setDate("date", aMonthAgo );
List results = q.list();
...
}
...
}

You can also provide some hints to a query through an array of QueryHint through a hints attribute.

The available Hibernate hints are


You can also define the lock mode by which the returned entities should be locked using the lockMode property. This is equivalent to the optional lock mode of the entitymanager lookup operations.

You can also map a native query (ie a plain SQL query). To achieve that, you need to describe the SQL resultset structure using @SqlResultSetMapping (or @SqlResultSetMappings if you plan to define several resulset mappings). Like @NamedQuery, a @SqlResultSetMapping can be defined at class level or in a JPA XML file. However its scope is global to the application.

As we will see, a resultSetMapping parameter is defined in @NamedNativeQuery, it represents the name of a defined @SqlResultSetMapping. The resultset mapping declares the entities retrieved by this native query. Each field of the entity is bound to an SQL alias (or column name). All fields of the entity including the ones of subclasses and the foreign key columns of related entities have to be present in the SQL query. Field definitions are optional provided that they map to the same column name as the one declared on the class property.

@NamedNativeQuery(name="night&area", query="select night.id nid, night.night_duration, "

+" night.night_date, area.id aid, night.area_id, area.name "
+"from Night night, Area area where night.area_id = area.id",
resultSetMapping="joinMapping")
@SqlResultSetMapping(name="joinMapping", entities={
@EntityResult(entityClass=Night.class, fields ={
@FieldResult(name="id", column="nid"),
@FieldResult(name="duration", column="night_duration"),
@FieldResult(name="date", column="night_date"),
@FieldResult(name="area", column="area_id"),
discriminatorColumn="disc"
}),
@EntityResult(entityClass=org.hibernate.test.annotations.query.Area.class, fields ={
@FieldResult(name="id", column="aid"),
@FieldResult(name="name", column="name")
})
}
)

In the above example, the night&area named query use the joinMapping result set mapping. This mapping returns 2 entities, Night and Area, each property is declared and associated to a column name, actually the column name retrieved by the query. Let's now see an implicit declaration of the property / column.

@Entity

@SqlResultSetMapping(name="implicit",
entities=@EntityResult(entityClass=SpaceShip.class))
@NamedNativeQuery(name="implicitSample",
query="select * from SpaceShip",
resultSetMapping="implicit")
publicclassSpaceShip{
privateString name;
privateString model;
privatedouble speed;
@Id
publicString getName(){
return name;
}
publicvoid setName(String name){
this.name = name;
}
@Column(name="model_txt")
publicString getModel(){
return model;
}
publicvoid setModel(String model){
this.model = model;
}
publicdouble getSpeed(){
return speed;
}
publicvoid setSpeed(double speed){
this.speed = speed;
}
}

In this example, we only describe the entity member of the result set mapping. The property / column mappings is done using the entity mapping values. In this case the model property is bound to the model_txt column. If the association to a related entity involve a composite primary key, a @FieldResult element should be used for each foreign key column. The @FieldResult name is composed of the property name for the relationship, followed by a dot ("."), followed by the name or the field or property of the primary key.

@Entity

@SqlResultSetMapping(name="compositekey",
entities=@EntityResult(entityClass=SpaceShip.class,
fields ={
@FieldResult(name="name", column ="name"),
@FieldResult(name="model", column ="model"),
@FieldResult(name="speed", column ="speed"),
@FieldResult(name="captain.firstname", column ="firstn"),
@FieldResult(name="captain.lastname", column ="lastn"),
@FieldResult(name="dimensions.length", column ="length"),
@FieldResult(name="dimensions.width", column ="width")
}),
columns ={ @ColumnResult(name ="surface"),
@ColumnResult(name ="volume")})
@NamedNativeQuery(name="compositekey",
query="select name, model, speed, lname as lastn, fname as firstn, length, width, length * width as surface from SpaceShip",
resultSetMapping="compositekey")
})
publicclassSpaceShip{
privateString name;
privateString model;
privatedouble speed;
privateCaptain captain;
privateDimensions dimensions;
@Id
publicString getName(){
return name;
}
publicvoid setName(String name){
this.name = name;
}
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumns({
@JoinColumn(name="fname", referencedColumnName ="firstname"),
@JoinColumn(name="lname", referencedColumnName ="lastname")
})
publicCaptain getCaptain(){
return captain;
}
publicvoid setCaptain(Captain captain){
this.captain = captain;
}
publicString getModel(){
return model;
}
publicvoid setModel(String model){
this.model = model;
}
publicdouble getSpeed(){
return speed;
}
publicvoid setSpeed(double speed){
this.speed = speed;
}
publicDimensions getDimensions(){
return dimensions;
}
publicvoid setDimensions(Dimensions dimensions){
this.dimensions = dimensions;
}
}
@Entity
@IdClass(Identity.class)
publicclassCaptainimplementsSerializable{
privateString firstname;
privateString lastname;
@Id
publicString getFirstname(){
return firstname;
}
publicvoid setFirstname(String firstname){
this.firstname = firstname;
}
@Id
publicString getLastname(){
return lastname;
}
publicvoid setLastname(String lastname){
this.lastname = lastname;
}
}

If you retrieve a single entity and if you use the default mapping, you can use the resultClass attribute instead of resultSetMapping:

@NamedNativeQuery(name="implicitSample", query="select * from SpaceShip",

resultClass=SpaceShip.class)
publicclassSpaceShip{

In some of your native queries, you'll have to return scalar values, for example when building report queries. You can map them in the @SqlResultsetMapping through @ColumnResult. You actually can even mix, entities and scalar returns in the same native query (this is probably not that common though).

@SqlResultSetMapping(name="scalar", columns=@ColumnResult(name="dimension"))

@NamedNativeQuery(name="scalar", query="select length*width as dimension from SpaceShip", resultSetMapping="scalar")

An other query hint specific to native queries has been introduced: org.hibernate.callable which can be true or false depending on whether the query is a stored procedure or not.

Hibernate 3.1 offers a variety of additional annotations that you can mix/match with your EJB 3 entities. They have been designed as a natural extension of EJB3 annotations.

To empower the EJB3 capabilities, hibernate provides specific annotations that match hibernate features. The org.hibernate.annotations package contains all these annotations extensions.

You can fine tune some of the actions done by Hibernate on entities beyond what the EJB3 spec offers.

@org.hibernate.annotations.Entity adds additional metadata that may be needed beyond what is defined in the standard @Entity

Here are some additional Hibernate annotation extensions

@org.hibernate.annotations.BatchSize allows you to define the batch size when fetching instances of this entity ( eg. @BatchSize(size=4) ). When loading a given entity, Hibernate will then load all the uninitialized entities of the same type in the persistence context up to the batch size.

@org.hibernate.annotations.Proxy defines the laziness attributes of the entity. lazy (default to true) define whether the class is lazy or not. proxyClassName is the interface used to generate the proxy (default is the class itself).

@org.hibernate.annotations.Where defines an optional SQL WHERE clause used when instances of this class is retrieved.

@org.hibernate.annotations.Check defines an optional check constraints defined in the DDL statetement.

@OnDelete(action=OnDeleteAction.CASCADE) on joined subclasses: use a SQL cascade delete on deletion instead of the regular Hibernate mechanism.

@Table(appliesTo="tableName", indexes = { @Index(name="index1", columnNames={"column1", "column2"} ) } ) creates the defined indexes on the columns of table tableName. This can be applied on the primary table or any secondary table. The @Tables annotation allows your to apply indexes on different tables. This annotation is expected where @javax.persistence.Table or @javax.persistence.SecondaryTable(s) occurs.

@org.hibernate.annotations.Table can also be used to define the following elements of secondary tables:

@Immutable marks an entity or collection as immutable. An immutable entity may not be updated by the application. This allows Hibernate to make some minor performance optimizations. Updates to an immutable entity will be ignored, but no exception is thrown. @Immutable must be used on root entities only. @Immutable placed on a collection makes the collection immutable, meaning additions and deletions to and from the collection are not allowed. A HibernateException is thrown in this case.

@Persister lets you define your own custom persistence strategy. You may, for example, specify your own subclass of org.hibernate.persister.EntityPersister or you might even provide a completely new implementation of the interface org.hibernate.persister.ClassPersister that implements persistence via, for example, stored procedure calls, serialization to flat files or LDAP.

@Entity

@BatchSize(size=5)
@org.hibernate.annotations.Entity(
selectBeforeUpdate =true,
dynamicInsert =true, dynamicUpdate =true,
optimisticLock =OptimisticLockType.ALL,
polymorphism =PolymorphismType.EXPLICIT)
@Where(clause="1=1")
@org.hibernate.annotations.Table(name="Forest", indexes ={ @Index(name="idx", columnNames ={"name","length"})})
@Persister(impl=MyEntityPersister.class)
publicclassForest{...}
@Entity

@Inheritance(
strategy=InheritanceType.JOINED
)
publicclassVegetable{...}
@Entity
@OnDelete(action=OnDeleteAction.CASCADE)
publicclassCarrotextendsVegetable{...}

Hibernate Annotations goes beyond the Java Persistence specification when defining identifiers.

@org.hibernate.annotations.GenericGenerator and @org.hibernate.annotations.GenericGenerators allows you to define an Hibernate specific id generator.

@Id @GeneratedValue(generator="system-uuid")

@GenericGenerator(name="system-uuid", strategy ="uuid")
publicString getId(){
@Id @GeneratedValue(generator="hibseq")
@GenericGenerator(name="hibseq", strategy ="seqhilo",
parameters ={
@Parameter(name="max_lo", value ="5"),
@Parameter(name="sequence", value="heybabyhey")
}
)
publicInteger getId(){

strategy is the short name of an Hibernate3 generator strategy or the fully qualified class name of an IdentifierGenerator implementation. You can add some parameters through the parameters attribute.

Contrary to their standard counterpart, @GenericGenerator and @GenericGenerators can be used in package level annotations, making them application level generators (just like if they were in a JPA XML file).

@GenericGenerators(

{
@GenericGenerator(
name="hibseq",
strategy ="seqhilo",
parameters ={
@Parameter(name="max_lo", value ="5"),
@Parameter(name="sequence", value="heybabyhey")
}
),
@GenericGenerator(...)
}
)
package org.hibernate.test.model

While not used as identifier property, some (group of) properties represent natural identifier of an entity. This is especially true when the schema uses the recommended approach of using surrogate primary key even if a natural business key exists. Hibernate allows to map such natural properties and reuse them in a Criteria query. The natural identifier is composed of all the properties marked @NaturalId.

@Entity

publicclassCitizen{
@Id
@GeneratedValue
privateInteger id;
privateString firstname;
privateString lastname;

@NaturalId
@ManyToOne
privateState state;
@NaturalId
privateString ssn;
...
}
//and later on query
List results = s.createCriteria(Citizen.class)
.add(Restrictions.naturalId().set("ssn","1234").set("state", ste ))
.list();

Note that the group of properties representing the natural identifier have to be unique (Hibernate will generate a unique constraint if the database schema is generated).

@org.hibernate.annotations.Type overrides the default hibernate type used: this is generally not necessary since the type is correctly inferred by Hibernate. Please refer to the Hibernate reference guide for more informations on the Hibernate types.

@org.hibernate.annotations.TypeDef and @org.hibernate.annotations.TypeDefs allows you to declare type definitions. These annotations can be placed at the class or package level. Note that these definitions are global for the session factory (even when defined at the class level). If the type is used on a single entity, you can place the definition on the entity itself. Otherwise, it is recommended to place the definition at the package level. In the example below, when Hibernate encounters a property of class PhoneNumer, it delegates the persistence strategy to the custom mapping type PhoneNumberType. However, properties belonging to other classes, too, can delegate their persistence strategy to PhoneNumberType, by explicitly using the @Type annotation.

@TypeDef(

name ="phoneNumber",
defaultForType =PhoneNumber.class,
typeClass =PhoneNumberType.class
)
@Entity
publicclassContactDetails{
[...]
privatePhoneNumber localPhoneNumber;
@Type(type="phoneNumber")
privateOverseasPhoneNumber overseasPhoneNumber;
[...]
}

The following example shows the usage of the parameters attribute to customize the TypeDef.

//in org/hibernate/test/annotations/entity/package-info.java

@TypeDefs(
{
@TypeDef(
name="caster",
typeClass =CasterStringType.class,
parameters ={
@Parameter(name="cast", value="lower")
}
)
}
)
package org.hibernate.test.annotations.entity;
//in org/hibernate/test/annotations/entity/Forest.java
publicclassForest{
@Type(type="caster")
publicString getSmallText(){
...
}

When using composite user type, you will have to express column definitions. The @Columns has been introduced for that purpose.

@Type(type="org.hibernate.test.annotations.entity.MonetaryAmountUserType")

@Columns(columns ={
@Column(name="r_amount"),
@Column(name="r_currency")
})
publicMonetaryAmount getAmount(){
return amount;
}
publicclassMonetaryAmountimplementsSerializable{
privateBigDecimal amount;
privateCurrency currency;
...
}

Some properties are generated at insert or update time by your database. Hibernate can deal with such properties and triggers a subsequent select to read these properties.

@Entity

publicclassAntenna{
@IdpublicInteger id;
@Generated(GenerationTime.ALWAYS)
@Column(insertable =false, updatable =false)
publicString longitude;
@Generated(GenerationTime.INSERT) @Column(insertable =false)
publicString latitude;
}

Annotate your property as @Generated You have to make sure your insertability or updatability does not conflict with the generation strategy you have chosen. When GenerationTime.INSERT is chosen, the property must not contains insertable columns, when GenerationTime.ALWAYS is chosen, the property must not contains insertable nor updatable columns.

@Version properties cannot be @Generated(INSERT) by design, it has to be either NEVER or ALWAYS.

SINGLE_TABLE is a very powerful strategy but sometimes, and especially for legacy systems, you cannot add an additional discriminator column. For that purpose Hibernate has introduced the notion of discriminator formula: @DiscriminatorFormula is a replacement of @DiscriminatorColumn and use a SQL fragment as a formula for discriminator resolution (no need to have a dedicated column).

@Entity

@DiscriminatorFormula("case when forest_type is null then 0 else forest_type end")
publicclassForest{...}

By default, when querying the top entities, Hibernate does not put a restriction clause on the discriminator column. This can be inconvenient if this column contains values not mapped in your hierarchy (through @DiscriminatorValue). To work around that you can use @ForceDiscriminator (at the class level, next to @DiscriminatorColumn). Hibernate will then list the available values when loading the entities.

You can define the foreign key name generated by Hibernate for subclass tables in the JOINED inheritance strategy.

@Entity

@Inheritance(strategy =InheritanceType.JOINED)
publicabstractclassFile{...}
@Entity
@ForeignKey(name ="FK_DOCU_FILE")
publicclassDocumentextendsFile{

The foreign key from the Document table to the File table will be named FK_DOCU_FILE.

By default, when Hibernate cannot resolve the association because the expected associated element is not in database (wrong id on the association column), an exception is raised by Hibernate. This might be inconvenient for legacy and badly maintained schemas. You can ask Hibernate to ignore such elements instead of raising an exception using the @NotFound annotation. This annotation can be used on a @OneToOne (with FK), @ManyToOne, @OneToMany or @ManyToMany association.

@Entity

publicclassChild{
...
@ManyToOne
@NotFound(action=NotFoundAction.IGNORE)
publicParent getParent(){...}
...
}

Sometimes you want to delegate to your database the deletion of cascade when a given entity is deleted.

@Entity

publicclassChild{
...
@ManyToOne
@OnDelete(action=OnDeleteAction.CASCADE)
publicParent getParent(){...}
...
}

In this case Hibernate generates a cascade delete constraint at the database level.

Foreign key constraints, while generated by Hibernate, have a fairly unreadable name. You can override the constraint name by use @ForeignKey.

@Entity

publicclassChild{
...
@ManyToOne
@ForeignKey(name="FK_PARENT")
publicParent getParent(){...}
...
}
alter table Child add constraint FK_PARENT foreign key (parent_id) references Parent

JPA comes with the fetch option to define lazy loading and fetching modes, however Hibernate has a much more option set in this area. To fine tune the lazy loading and fetching strategies, some additional annotations have been introduced:

The Hibernate annotations overrides the EJB3 fetching options.


The @Any annotation defines a polymorphic association to classes from multiple tables. This type of mapping always requires more than one column. The first column holds the type of the associated entity. The remaining columns hold the identifier. It is impossible to specify a foreign key constraint for this kind of association, so this is most certainly not meant as the usual way of mapping (polymorphic) associations. You should use this only in very special cases (eg. audit logs, user session data, etc).

The @Any annotation describes the column holding the metadata information. To link the value of the metadata information and an actual entity type, The @AnyDef and @AnyDefs annotations are used.

  @Any( metaColumn = @Column( name ="property_type"), fetch=FetchType.EAGER )

@AnyMetaDef(
idType ="integer",
metaType ="string",
metaValues ={
@MetaValue( value ="S", targetEntity =StringProperty.class),
@MetaValue( value ="I", targetEntity =IntegerProperty.class)
})
@JoinColumn( name ="property_id")
publicProperty getMainProperty(){
return mainProperty;
}

idType represents the target entities identifier property type and metaType the metadata type (usually String).

Note that @AnyDef can be mutualized and reused. It is recommended to place it as a package metadata in this case.

//on a package

@AnyMetaDef( name="property"
idType ="integer",
metaType ="string",
metaValues ={
@MetaValue( value ="S", targetEntity =StringProperty.class),
@MetaValue( value ="I", targetEntity =IntegerProperty.class)
})
package org.hibernate.test.annotations.any;
//in a class
@Any( metaDef="property", metaColumn = @Column( name ="property_type"), fetch=FetchType.EAGER )
@JoinColumn( name ="property_id")
publicProperty getMainProperty(){
return mainProperty;
}

It is possible to set

You can also declare a sort comparator. Use the @Sort annotation. Expressing the comparator type you want between unsorted, natural or custom comparator. If you want to use your own comparator implementation, you'll also have to express the implementation class using the comparator attribute. Note that you need to use either a SortedSet or a SortedMap interface.

  @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)

@JoinColumn(name="CUST_ID")
@Sort(type =SortType.COMPARATOR, comparator =TicketComparator.class)
@Where(clause="1=1")
@OnDelete(action=OnDeleteAction.CASCADE)
publicSortedSet<Ticket> getTickets(){
return tickets;
}

Please refer to the previous descriptions of these annotations for more informations.

Foreign key constraints, while generated by Hibernate, have a fairly unreadable name. You can override the constraint name by use @ForeignKey. Note that this annotation has to be placed on the owning side of the relationship, inverseName referencing to the other side constraint.

@Entity

publicclassWoman{
...
@ManyToMany(cascade ={CascadeType.ALL})
@ForeignKey(name ="TO_WOMAN_FK", inverseName ="TO_MAN_FK")
publicSet<Man> getMens(){
return mens;
}
}
alter table Man_Woman add constraint TO_WOMAN_FK foreign key (woman_id) references Woman
alter table Man_Woman add constraint TO_MAN_FK foreign key (man_id) references Man

A bidirectional association where one end is an indexed collection (ie. represented as a @OrderColumn, or as a Map) requires special consideration. If a property on the associated class explicitly maps the indexed value, the use of mappedBy is permitted:

@Entity

publicclassParent{
@OneToMany(mappedBy="parent")
@OrderColumn(name="order")
privateList<Child> children;
...
}
@Entity
publicclassChild{
...
//the index column is mapped as a property in the associated entity
@Column(name="order")
privateint order;
@ManyToOne
@JoinColumn(name="parent_id", nullable=false)
privateParent parent;
...
}

But, if there is no such property on the child class, we can't think of the association as truly bidirectional (there is information available at one end of the association that is not available at the other end: the index). In this case, we can't map the collection as mappedBy. Instead, we could use the following mapping:

@Entity

publicclassParent{
@OneToMany
@OrderColumn(name="order")
@JoinColumn(name="parent_id", nullable=false)
privateList<Child> children;
...
}
@Entity
publicclassChild{
...
@ManyToOne
@JoinColumn(name="parent_id", insertable=false, updatable=false, nullable=false)
privateParent parent;
...
}

Note that in this mapping, the collection-valued end of the association is responsible for updating the foreign key.

Another interesting feature is the ability to define a surrogate primary key to a bag collection. This remove pretty much all of the drawbacks of bags: update and removal are efficient, more than one EAGER bag per query or per entity. This primary key will be contained in a additional column of your collection table but will not be visible to the Java application. @CollectionId is used to mark a collection as id bag, it also allow to override the primary key column(s), the primary key type and the generator strategy. The strategy can be identity, or any defined generator name of your application.

@Entity

@TableGenerator(name="ids_generator", table="IDS")
publicclassPassport{
...
@ManyToMany(cascade =CascadeType.ALL)
@JoinTable(name="PASSPORT_VISASTAMP")
@CollectionId(
columns = @Column(name="COLLECTION_ID"),
type=@Type(type="long"),
generator ="ids_generator"
)
privateCollection<Stamp> visaStamp =newArrayList();
...
}

@ManyToAny allows polymorphic associations to classes from multiple tables. This type of mapping always requires more than one column. The first column holds the type of the associated entity. The remaining columns hold the identifier. It is impossible to specify a foreign key constraint for this kind of association, so this is most certainly not meant as the usual way of mapping (polymorphic) associations. You should use this only in very special cases (eg. audit logs, user session data, etc).

  @ManyToAny(

metaColumn = @Column( name ="property_type"))
@AnyMetaDef(
idType ="integer",
metaType ="string",
metaValues ={
@MetaValue( value ="S", targetEntity =StringProperty.class),
@MetaValue( value ="I", targetEntity =IntegerProperty.class)})
@Cascade({ org.hibernate.annotations.CascadeType.ALL })
@JoinTable( name ="obj_properties", joinColumns = @JoinColumn( name ="obj_id"),
inverseJoinColumns = @JoinColumn( name ="property_id"))
publicList<Property> getGeneralProperties(){

Like @Any, @ManyToAny can use named @AnyDefs, see Section 2.4.5.2, "@Any" for more info.

Hibernate offers more operations than the Java Persistence specification. You can use the @Cascade annotation to cascade the following operations:

This is especially useful for SAVE_UPDATE (which is the operation cascaded at flush time if you use plain Hibernate Annotations - Hibernate EntityManager cascade PERSIST at flush time as per the specification).

@OneToMany( cascade ={CascadeType.PERSIST,CascadeType.MERGE})

@Cascade(org.hibernate.annotations.CascadeType.REPLICATE)
publicCollection<Employer> getEmployers()

It is recommended to use @Cascade to compliment @*To*(cascade=...) as shown in the previous example.

Hibernate has the ability to apply arbitrary filters on top of your data. Those filters are applied at runtime on a given session. First, you need to define them.

@org.hibernate.annotations.FilterDef or @FilterDefs define filter definition(s) used by filter(s) using the same name. A filter definition has a name() and an array of parameters(). A parameter will allow you to adjust the behavior of the filter at runtime. Each parameter is defined by a @ParamDef which has a name and a type. You can also define a defaultCondition() parameter for a given @FilterDef to set the default condition to use when none are defined in each individual @Filter. A @FilterDef(s) can be defined at the class or package level.

We now need to define the SQL filter clause applied to either the entity load or the collection load. @Filter is used and placed either on the entity or the collection element

@Entity

@FilterDef(name="minLength", parameters=@ParamDef( name="minLength", type="integer"))
@Filters({
@Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length"),
@Filter(name="minLength", condition=":minLength <= length")
})
publicclassForest{...}

When the collection use an association table as a relational representation, you might want to apply the filter condition to the association table itself or to the target entity table. To apply the constraint on the target entity, use the regular @Filter annotation. However, if you wan to target the association table, use the @FilterJoinTable annotation.

  @OneToMany

@JoinTable
//filter on the target entity table
@Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length")
//filter on the association table
@FilterJoinTable(name="security", condition=":userlevel >= requredLevel")
publicSet<Forest> getForests(){...}

Since Hibernate has more features on named queries than the one defined in the JPA specification, @org.hibernate.annotations.NamedQuery, @org.hibernate.annotations.NamedQueries, @org.hibernate.annotations.NamedNativeQuery and @org.hibernate.annotations.NamedNativeQueries have been introduced. They add some attributes to the standard version and can be used as a replacement:

Those hints can be set in a standard @javax.persistence.NamedQuery annotations through the detyped @QueryHint. Another key advantage is the ability to set those annotations at a package level.

Hibernate gives you the ability to override every single SQL statement generated. We have seen native SQL query usage already, but you can also override the SQL statement used to load or change the state of entities.

@Entity

@Table(name="CHAOS")
@SQLInsert( sql="INSERT INTO CHAOS(size, name, nickname, id) VALUES(?,upper(?),?,?)")
@SQLUpdate( sql="UPDATE CHAOS SET size = ?, name = upper(?), nickname = ? WHERE id = ?")
@SQLDelete( sql="DELETE CHAOS WHERE id = ?")
@SQLDeleteAll( sql="DELETE CHAOS")
@Loader(namedQuery ="chaos")
@NamedNativeQuery(name="chaos", query="select id, size, name, lower( nickname ) as nickname from CHAOS where id= ?", resultClass =Chaos.class)
publicclassChaos{
@Id
privateLong id;
privateLong size;
privateString name;
privateString nickname;

@SQLInsert, @SQLUpdate, @SQLDelete, @SQLDeleteAll respectively override the INSERT statement, UPDATE statement, DELETE statement, DELETE statement to remove all entities.

If you expect to call a store procedure, be sure to set the callable attribute to true (@SQLInsert(callable=true, ...)).

To check that the execution happens correctly, Hibernate allows you to define one of those three strategies:

To define the result check style, use the check parameter (@SQLUpdate(check=ResultCheckStyle.COUNT, ...)).

You can also override the SQL load statement by a native SQL query or a HQL query. You just have to refer to a named query with the @Loader annotation.

You can use the exact same set of annotations to override the collection related statements.

@OneToMany

@JoinColumn(name="chaos_fk")
@SQLInsert( sql="UPDATE CASIMIR_PARTICULE SET chaos_fk = ? where id = ?")
@SQLDelete( sql="UPDATE CASIMIR_PARTICULE SET chaos_fk = null where id = ?")
privateSet<CasimirParticle> particles =newHashSet<CasimirParticle>();

The parameters order is important and is defined by the order Hibernate handle properties. You can see the expected order by enabling debug logging for the org.hibernate.persister.entity level. With this level enabled Hibernate will print out the static SQL that is used to create, update, delete etc. entities. (To see the expected sequence, remember to not include your custom SQL through annotations as that will override the Hibernate generated static sql.)

Overriding SQL statements for secondary tables is also possible using @org.hibernate.annotations.Table and either (or all) attributes sqlInsert, sqlUpdate, sqlDelete:

@Entity

@SecondaryTables({
@SecondaryTable(name ="`Cat nbr1`"),
@SecondaryTable(name ="Cat2"})
@org.hibernate.annotations.Tables({
@Table(appliesTo ="Cat", comment ="My cat table"),
@Table(appliesTo ="Cat2", foreignKey = @ForeignKey(name="FK_CAT2_CAT"), fetch =FetchMode.SELECT,
sqlInsert=@SQLInsert(sql="insert into Cat2(storyPart2, id) values(upper(?), ?)"))
})
publicclassCatimplementsSerializable{

The previous example also show that you can give a comment to a given table (promary or secondary): This comment will be used for DDL generation.

org.hibernate.tuple.Tuplizer, and its sub-interfaces, are responsible for managing a particular representation of a piece of data, given that representation's org.hibernate.EntityMode. If a given piece of data is thought of as a data structure, then a tuplizer is the thing which knows how to create such a data structure and how to extract values from and inject values into such a data structure. For example, for the POJO entity mode, the correpsonding tuplizer knows how create the POJO through its constructor and how to access the POJO properties using the defined property accessors. There are two high-level types of Tuplizers, represented by the org.hibernate.tuple.EntityTuplizer and org.hibernate.tuple.ComponentTuplizer interfaces. EntityTuplizers are responsible for managing the above mentioned contracts in regards to entities, while ComponentTuplizers do the same for components. Check the Hibernate reference documentation for more information.

To define tuplixer in annotations, simply use the @Tuplizer annotation on the according element

@Entity

@Tuplizer(impl =DynamicEntityTuplizer.class)
publicinterfaceCuisine{
@Id
@GeneratedValue
publicLong getId();
publicvoid setId(Long id);
publicString getName();
publicvoid setName(String name);
@Tuplizer(impl =DynamicComponentTuplizer.class)
publicCountry getCountry();
publicvoid setCountry(Country country);
}

In Section 2.4.5.1, "Lazy options and fetching modes" we have seen how to affect the fetching strategy for associated objects using the @Fetch annotation. An alternative approach is a so called fetch profile. A fetch profile is a named configuration associated with the org.hibernate.SessionFactory which gets enabled on the org.hibernate.Session. Once enabled on a org.hibernate.Session, the fetch profile will be in affect for that session until it is explicitly disabled. Lets look at an example:

@Entity

@FetchProfile(name ="customer-with-orders", fetchOverrides ={
@FetchProfile.FetchOverride(entity =Customer.class, association ="orders", mode =FetchMode.JOIN)
})
publicclassCustomer{
@Id
@GeneratedValue
privatelong id;
privateString name;
privatelong customerNumber;
@OneToMany
privateSet<Order> orders;
// standard getter/setter
...
}

In the normal case the orders association would be lazy loaded by Hibernate, but in a usecase where it is more efficient to load the customer and their orders together you could do something like this:

Session session =...;

session.enableFetchProfile("customer-with-orders");// name matches @FetchProfile name
Customer customer =(Customer) session.get(Customer.class, customerId );
session.disableFetchProfile("customer-with-orders");// or just close the session
...

Note

Fetch profile definitions are global and it does not matter on which class you place them. You can place the @FetchProfile annotation either onto a class or package (package-info.java). In order to define multiple fetch profiles for the same class or package @FetchProfiles can be used.

Currently only join style fetch profiles are supported, but they plan is to support additional styles. See HHH-3414 for details. Refer also to the discussion about fetch profiles in the Hibernate Core documentation.

The primary target for metadata in EJB3 is annotations, but the EJB3 specification provides a way to override or replace the annotation defined metadata through an XML deployment descriptor. In the current release only pure EJB3 annotations overriding are supported. If you wish to use Hibernate specific features in some entities, you'll have to either use annotations or fallback to hbm files. You can of course mix and match annotated entities and entities describes in hbm files.

The unit test suite shows some additional XML file samples.

The XML deployment descriptor structure has been designed to reflect the annotations one. So if you know the annotations structure, using the XML schema will be straightforward for you.

You can define one or more XML files describing your metadata, these files will be merged by the overriding engine.

You can define global level metadata available for all XML files. You must not define these metadata more than once per deployment.

<?xml version="1.0" encoding="UTF-8"?>

<entity-mappings
xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
version="2.0">

<persistence-unit-metadata>
<xml-mapping-metadata-complete/>
<persistence-unit-defaults>
<schema>myschema</schema>
<catalog>mycatalog</catalog>
<cascade-persist/>
</persistence-unit-defaults>
</persistence-unit-metadata>

xml-mapping-metadata-complete means that all entity, mapped-superclasses and embeddable metadata should be picked up from XML (ie ignore annotations).

schema / catalog will override all default definitions of schema and catalog in the metadata (both XML and annotations).

cascade-persist means that all associations have PERSIST as a cascade type. We recommend you to not use this feature.

You can either define or override metadata informations on a given entity.

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappin(1)gs 
 xmlns="http://java.sun.com/xml/ns/persistence/orm"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
 version="2.0">
 <package>o(2)rg.hibernate.test.annotations.reflection</package>
 <entity cl(3)ass="Administration" access="PROPERTY" metadata-complete="true">
 <table(4) name="tbl_admin">
 <unique-constraint>
 <column-name>firstname</column-name>
 <column-name>lastname</column-name>
 </unique-constraint>
 </table>
 <secon(5)dary-table name="admin2">
 <primary-key-join-column name="admin_id" referenced-column-name="id"/>
 <unique-constraint>
 <column-name>address</column-name>
 </unique-constraint>
 </secondary-table>
 <id-cl(6)ass class="SocialSecurityNumber"/>
 <inher(7)itance strategy="JOINED"/>
 <seque(8)nce-generator name="seqhilo" sequence-name="seqhilo"/>
 <table(9)-generator name="table" table="tablehilo"/>
 ...
 </entity>
 <entity class="PostalAdministration">
 <prima(10)ry-key-join-column name="id"/>
 ...
 </entity>
</entity-mappings>

1

entity-mappings: entity-mappings is the root element for all XML files. You must declare the xml schema, the schema file is included in the hibernate-annotations.jar file, no internet access will be processed by Hibernate Annotations.

2

package (optional): default package used for all non qualified class names in the given deployment descriptor file.

3

entity: desribes an entity.

metadata-complete defines whether the metadata description for this element is complete or not (in other words, if annotations present at the class level should be considered or not).

An entity has to have a class attribute refering the java class the metadata applies on.

You can overrides entity name through the name attribute, if none is defined and if an @Entity.name is present, then it is used (provided that metadata complete is not set).

For metadata complete (see below) element, you can define an access (either FIELD or PROPERTY (default)). For non medatada complete element, if access is not defined, the @Id position will lead position, if access is defined, the value is used.

4

table: you can declare table properties (name, schema, catalog), if none is defined, the java annotation is used.

You can define one or several unique constraints as seen in the example

5

secondary-table: defines a secondary table very much like a regular table except that you can define the primary key / foreign key column(s) through the primary-key-join-column element. On non metadata complete, annotation secondary tables are used only if there is no secondary-table definition, annotations are ignored otherwise.

6

id-class: defines the id class in a similar way @IdClass does

7

inheritance: defines the inheritance strategy (JOINED, TABLE_PER_CLASS, SINGLE_TABLE), Available only at the root entity level

8

sequence-generator: defines a sequence generator

9

table-generator: defines a table generator

10

primary-key-join-column: defines the primary key join column for sub entities when JOINED inheritance strategy is used

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings 
 xmlns="http://java.sun.com/xml/ns/persistence/orm"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
 version="2.0">
 <package>org.hibernate.test.annotations.reflection</package>
 <entity class="Music" access="PROPERTY" metadata-complete="true">
 <discr(1)iminator-value>Generic</discriminator-value>
 <discriminator-column length="34"/>
 ...
 </entity>
 <entity class="PostalAdministration">
 <primary-key-join-column name="id"/>
 <named(2)-query name="adminById">
 <query>select m from Administration m where m.id = :id</query>
 <hint name="org.hibernate.timeout" value="200"/>
 </named-query>
 <named(3)-native-query name="allAdmin" result-set-mapping="adminrs">
 <query>select *, count(taxpayer_id) as taxPayerNumber 
 from Administration, TaxPayer
 where taxpayer_admin_id = admin_id group by ...</query>
 <hint name="org.hibernate.timeout" value="200"/>
 </named-native-query>
 <sql-r(4)esult-set-mapping name="adminrs">
 <entity-result entity-class="Administration">
 <field-result name="name" column="fld_name"/>
 </entity-result>
 <column-result name="taxPayerNumber"/>
 </sql-result-set-mapping>
 <attri(5)bute-override name="ground">
 <column name="fld_ground" unique="true" scale="2"/>
 </attribute-override>
 <association-override name="referer">
 <join-column name="referer_id" referenced-column-name="id"/>
 </association-override>
 ...
 </entity>
</entity-mappings>

1

discriminator-value / discriminator-column: defines the discriminator value and the column holding it when the SINGLE_TABLE inheritance strategy is chosen

2

named-query: defines named queries and possibly the hints associated to them. Those definitions are additive to the one defined in annotations, if two definitions have the same name, the XML one has priority.

3

named-native-query: defines an named native query and its sql result set mapping. Alternatively, you can define the result-class. Those definitions are additive to the one defined in annotations, if two definitions have the same name, the XML one has priority.

4

sql-result-set-mapping: describes the result set mapping structure. You can define both entity and column mappings. Those definitions are additive to the one defined in annotations, if two definitions have the same name, the XML one has priority

5

attribute-override / association-override: defines a column or join column overriding. This overriding is additive to the one defined in annotations

Same applies for <embeddable> and <mapped-superclass>.

You can of course defines XML overriding for properties. If metadata complete is defined, then additional properties (ie at the Java level) will be ignored. Otherwise, once you start overriding a property, all annotations on the given property are ignored. All property level metadata behave in entity/attributes, mapped-superclass/attributes or embeddable/attributes.

<attributes>
<idname="id">
<columnname="fld_id"/>
<generated-valuegenerator="generator"strategy="SEQUENCE"/>
<temporal>DATE</temporal>
<sequence-generatorname="generator"sequence-name="seq"/>
</id>
<versionname="version"/>
<embeddedname="embeddedObject">
<attribute-overridename"subproperty">
<columnname="my_column"/>
</attribute-override>
</embedded>
<basicname="status"optional="false">
<enumerated>STRING</enumerated>
</basic>
<basicname="serial"optional="true">
<columnname="serialbytes"/>
<lob/>
</basic>
<basicname="terminusTime"fetch="LAZY">
<temporal>TIMESTAMP</temporal>
</basic>
</attributes>

You can override a property through id, embedded-id, version, embedded and basic. Each of these elements can have subelements accordingly: lob, temporal, enumerated, column.

You can define XML overriding for associations. All association level metadata behave in entity/attributes, mapped-superclass/attributes or embeddable/attributes.

<attributes>
<one-to-manyname="players"fetch="EAGER">
<map-keyname="name"/>
<join-columnname="driver"/>
<join-columnname="number"/>
</one-to-many>
<many-to-manyname="roads"target-entity="Administration">
<order-by>maxSpeed</order-by>
<join-tablename="bus_road">
<join-columnname="driver"/>
<join-columnname="number"/>
<inverse-join-columnname="road_id"/>
<unique-constraint>
<column-name>driver</column-name>
<column-name>number</column-name>
</unique-constraint>
</join-table>
</many-to-many>
<many-to-manyname="allTimeDrivers"mapped-by="drivenBuses">
</attributes>

You can override an association through one-to-many, one-to-one, many-to-one, and many-to-many. Each of these elements can have subelements accordingly: join-table (which can have join-columns and inverse-join-columns), join-columns, map-key, and order-by. mapped-by and target-entity can be defined as attributes when it makes sense. Once again the structure is reflects the annotations structure. You can find all semantic informations in the chapter describing annotations.

Hibernate Annotations mainly focuses on persistence metadata. The project also have a nice integration with some external modules.

Bean Validation standardizes how to define and declare domain model level constraints. You can, for example, express that a property should never be null, that the account balance should be strictly positive, etc. These domain model constraints are declared in the bean itself by annotating its properties. Bean Validation can then read them and check for constraint violations. The validation mechanism can be executed in different layers in your application without having to duplicate any of these rules (presentation layer, data access layer). Following the DRY principle, Bean Validation and its reference implementation Hibernate Validator has been designed for that purpose.

The integration between Hibernate and Bean Validation works at two levels. First, it is able to check in-memory instances of a class for constraint violations. Second, it can apply the constraints to the Hibernate metamodel and incorporate them into the generated database schema.

Each constraint annotation is associated to a validator implementation responsible for checking the constraint on the entity instance. A validator can also (optionally) apply the constraint to the Hibernate metamodel, allowing Hibernate to generate DDL that expresses the constraint. With the appropriate event listener, you can execute the checking operation on inserts, updates and deletes done by Hibernate.

When checking instances at runtime, Hibernate Validator returns information about constraint violations in a set of ConstraintViolations. Among other information, the ConstraintViolation contains an error description message that can embed the parameter values bundle with the annotation (eg. size limit), and message strings that may be externalized to a ResourceBundle.

By default, no configuration is necessary.

The Default group is validated on entity insert and update and the database model is updated accordingly based on the Default group as well.

You can customize the Bean Validation integration by setting the validation mode. Use the javax.persistence.validation.mode property and set it up for example in your persistence.xml file or your hibernate.cfg.xml file. Several options are possible:

If you want to validate different groups during insertion, update and deletion, use:

Each property accepts the fully qualified class names of the groups validated separated by a comma (,)


Note

You can set these properties in hibernate.cfg.xml, hibernate.properties or programmatically.

If an entity is found to be invalid, the list of constraint violations is propagated by the ConstraintViolationException which exposes the set of ConstraintViolations.

This exception is wrapped in a RollbackException when the violation happens at commit time. Otherwise the ConstraintViolationException is returned (for example when calling flush(). Note that generally, catchable violations are validated at a higher level (for example in Seam / JSF 2 via the JSF - Bean Validation integration or in your business layer by explicitly calling Bean Validation).

An application code will rarely be looking for a ConstraintViolationException raised by Hibernate. This exception should be treated as fatal and the persistence context should be discarded (EntityManager or Session).

Annotations are a very convenient and elegant way to specify invariant constraints for a domain model. You can, for example, express that a property should never be null, that the account balance should be strictly positive, etc. These domain model constraints are declared in the bean itself by annotating its properties. A validator can then read them and check for constraint violations. The validation mechanism can be executed in different layers in your application without having to duplicate any of these rules (presentation layer, data access layer). Following the DRY principle, Hibernate Validator has been designed for that purpose.

Hibernate Validator works at two levels. First, it is able to check in-memory instances of a class for constraint violations. Second, it can apply the constraints to the Hibernate metamodel and incorporate them into the generated database schema.

Each constraint annotation is associated to a validator implementation responsible for checking the constraint on the entity instance. A validator can also (optionally) apply the constraint to the Hibernate metamodel, allowing Hibernate to generate DDL that expresses the constraint. With the appropriate event listener, you can execute the checking operation on inserts and updates done by Hibernate. Hibernate Validator is not limited to use with Hibernate. You can easily use it anywhere in your application.

When checking instances at runtime, Hibernate Validator returns information about constraint violations in an array of InvalidValue s. Among other information, the InvalidValue contains an error description message that can embed the parameter values bundle with the annotation (eg. length limit), and message strings that may be externalized to a ResourceBundle .

If Hibernate Validator (hibernate-validator.jar) is available in the classpath, Hibernate Annotations will integrate in two ways:

For entities free of validation rules, the runtime performance cost is null.

To disable constraint propagation to DDL, set up hibernate.validator.apply_to_ddl to false in the configuration file. Such a need is very uncommon and not recommended.

To disable pre-entity change validation, set up hibernate.validator.autoregister_listeners to false in the configuration file. Such a need is very uncommon and not recommended.

Check the Hibernate Validator reference documentation for more information.


Copyright © 2004 Red Hat Inc. and the various authors

AltStyle によって変換されたページ (->オリジナル) /