Hibernate.org Community Documentation

- Précédent
- Suivant

## Chapitre 5. Mappage O/R de base

## 5.1. Déclaration de mappage

Object/relational mappings can be defined in three approaches:

- using Java 5 annotations (via the Java Persistence 2 annotations)

- using JPA 2 XML deployment descriptors (described in chapter XXX)

- using the Hibernate legacy XML files approach known as hbm.xml

Annotations are 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. Hibernate specific extensions are in `org.hibernate.annotations.*`. You favorite IDE can auto-complete annotations and their attributes for you (even without a specific "JPA" plugin, since JPA annotations are plain Java 5 annotations).

Here is an example of mapping

    package eg;

    @Entity

    @Table(name="cats") @Inheritance(strategy=SINGLE_TABLE)

    @DiscriminatorValue("C") @DiscriminatorColumn(name="subclass", discriminatorType=CHAR)

    public class Cat {

       @Id @GeneratedValue

       public Integer getId() { return id; }

       public void setId(Integer id) { this.id = id; }

       private Integer id;

       public BigDecimal getWeight() { return weight; }

       public void setWeight(BigDecimal weight) { this.weight = weight; }

       private BigDecimal weight;

       @Temporal(DATE) @NotNull @Column(updatable=false)

       public Date getBirthdate() { return birthdate; }

       public void setBirthdate(Date birthdate) { this.birthdate = birthdate; }

       private Date birthdate;

       @org.hibernate.annotations.Type(type="eg.types.ColorUserType")

       @NotNull @Column(updatable=false)

       public ColorType getColor() { return color; }

       public void setColor(ColorType color) { this.color = color; }

       private ColorType color;

       @NotNull @Column(updatable=false)

       public String getSex() { return sex; }

       public void setSex(String sex) { this.sex = sex; }

       private String sex;

       @NotNull @Column(updatable=false)

       public Integer getLitterId() { return litterId; }

       public void setLitterId(Integer litterId) { this.litterId = litterId; }

       private Integer litterId;

       @ManyToOne @JoinColumn(name="mother_id", updatable=false)

       public Cat getMother() { return mother; }

       public void setMother(Cat mother) { this.mother = mother; }

       private Cat mother;

       @OneToMany(mappedBy="mother") @OrderBy("litterId")

       public Set<Cat> getKittens() { return kittens; }

       public void setKittens(Set<Cat> kittens) { this.kittens = kittens; }

       private Set<Cat> kittens = new HashSet<Cat>();

    }

    @Entity @DiscriminatorValue("D")

    public class DomesticCat extends Cat {

       public String getName() { return name; }

       public void setName(String name) { this.name = name }

       private String name;

    }

    @Entity

    public class Dog { ... }

The legacy hbm.xml approach uses an XML schema designed to be readable and hand-editable. The mapping language is Java-centric, meaning that mappings are constructed around persistent class declarations and not table declarations.

Remarquez que même si beaucoup d'utilisateurs de Hibernate préfèrent écrire les fichiers de mappages XML à la main, plusieurs outils existent pour générer ce document, notamment XDoclet, Middlegen et AndroMDA.

Commençons avec un exemple de mappage :

    <?xml version="1.0"?>

    <!DOCTYPE hibernate-mapping PUBLIC

          "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

              "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

    <hibernate-mapping package="eg">

            <class name="Cat"

                table="cats"

                discriminator-value="C">

                    <id name="id">

                            <generator class="native"/>

                    </id>

                    <discriminator column="subclass"

                         type="character"/>

                    <property name="weight"/>

                    <property name="birthdate"

                        type="date"

                        not-null="true"

                        update="false"/>

                    <property name="color"

                        type="eg.types.ColorUserType"

                        not-null="true"

                        update="false"/>

                    <property name="sex"

                        not-null="true"

                        update="false"/>

                    <property name="litterId"

                        column="litterId"

                        update="false"/>

                    <many-to-one name="mother"

                        column="mother_id"

                        update="false"/>

                    <set name="kittens"

                        inverse="true"

                        order-by="litter_id">

                            <key column="mother_id"/>

                            <one-to-many class="Cat"/>

                    </set>

                    <subclass name="DomesticCat"

                        discriminator-value="D">

                            <property name="name"

                                type="string"/>

                    </subclass>

            </class>

            <class name="Dog">

                    <!-- mapping for Dog could go here -->

            </class>

    </hibernate-mapping>

We will now discuss the concepts of the mapping documents (both annotations and XML). We will only describe, however, the document elements and attributes that are used by Hibernate at runtime. The mapping document also contains some extra optional attributes and elements that affect the database schemas exported by the schema export tool (for example, the `not-null` attribute).

### 5.1.1. Entity

An entity is a regular Java object (aka POJO) which will be persisted by Hibernate.

To mark an object as an entity in annotations, use the `@Entity` annotation.

    @Entity

    public class Flight implements Serializable {

        Long id;

        @Id

        public Long getId() { return id; }

        public void setId(Long id) { this.id = id; }

    }

That's pretty much it, the rest is optional. There are however any options to tweak your entity mapping, let's explore them.

`@Table` lets you define the table the entity will be persisted into. If undefined, the table name is the unqualified class name of the entity. You can also optionally define the catalog, the schema as well as unique constraints on the table.

    @Entity

    @Table(name="TBL_FLIGHT",

           schema="AIR_COMMAND",

           uniqueConstraints=

               @UniqueConstraint(

                   name="flight_number",

                   columnNames={"comp_prefix", "flight_number"} ) )

    public class Flight implements Serializable {

        @Column(name="comp_prefix")

        public String getCompagnyPrefix() { return companyPrefix; }

        @Column(name="flight_number")

        public String getNumber() { return number; }

    }

The constraint name is optional (generated if left undefined). The column names composing the constraint correspond to the column names as defined before the Hibernate `NamingStrategy` is applied.

`@Entity.name` lets you define the shortcut name of the entity you can used in JP-QL and HQL queries. It defaults to the unqualified class name of the class.

Hibernate goes beyond the JPA specification and provide additional configurations. Some of them are hosted on `@org.hibernate.annotations.Entity`:

- `dynamicInsert` / `dynamicUpdate` (defaults to false): specifies that `INSERT` / `UPDATE` SQL should be generated at runtime and contain only the columns whose values are not null. The `dynamic-update` and `dynamic-insert` settings are not inherited by subclasses. Although these settings can increase performance in some cases, they can actually decrease performance in others.

- `selectBeforeUpdate` (defaults to false): specifies that Hibernate should never perform an SQL `UPDATE` unless it is certain that an object is actually modified. Only when a transient object has been associated with a new session using `update()`, will Hibernate perform an extra SQL `SELECT` to determine if an `UPDATE` is actually required. Use of `select-before-update` will usually decrease performance. It is useful to prevent a database update trigger being called unnecessarily if you reattach a graph of detached instances to a `Session`.

- `polymorphisms` (defaults to `IMPLICIT`): determines whether implicit or explicit query polymorphisms is used. Implicit polymorphisms means that instances of the class will be returned by a query that names any superclass or implemented interface or class, and that instances of any subclass of the class will be returned by a query that names the class itself. Explicit polymorphisms means that class instances will be returned only by queries that explicitly name that class. Queries that name the class will return only instances of subclasses mapped. For most purposes, the default `polymorphisms=IMPLICIT` is appropriate. Explicit polymorphisms is useful when two different classes are mapped to the same table This allows a "lightweight" class that contains a subset of the table columns.

- `persister`: specifies a custom `ClassPersister`. The `persister` attribute lets you customize the persistence strategy used for the class. You can, for example, specify your own subclass of `org.hibernate.persister.EntityPersister`, or you can even provide a completely new implementation of the interface `org.hibernate.persister.ClassPersister` that implements, for example, persistence via stored procedure calls, serialization to flat files or LDAP. See `org.hibernate.test.CustomPersister` for a simple example of "persistence" to a `Hashtable`.

- `optimisticLock` (defaults to `VERSION`): determines the optimistic locking strategy. If you enable `dynamicUpdate`, you will have a choice of optimistic locking strategies:

  - `version` vérifie les colonnes version/timestamp

  - `all` vérifie toutes les colonnes

  - `dirty` vérifie les colonnes modifiées, permettant quelques mise à jour concurrentes

  - `none` n'utilisez pas le verrouillage optimiste

  Nous encourageons très fortement l'utilisation de colonnes de version/timestamp pour le verrouillage optimiste avec Hibernate. C'est la meilleure stratégie en ce qui concerne les performances et la seule qui gère correctement les modifications sur les instances détachées (c'est à dire lorsqu'on utilise `Session.merge()`).

## Astuce

Be sure to import `@javax.persistence.Entity` to mark a class as an entity. It's a common mistake to import `@org.hibernate.annotations.Entity` by accident.

Some entities are not mutable. They cannot be updated or deleted by the application. This allows Hibernate to make some minor performance optimizations.. Use the `@Immutable` annotation.

You can also alter how Hibernate deals with lazy initialization for this class. On `@Proxy`, use `lazy`=false to disable lazy fetching (not recommended). You can also specify an interface to use for lazy initializing proxies (defaults to the class itself): use `proxyClass` on `@Proxy`. Hibernate will initially return proxies (Javassist or CGLIB) that implement the named interface. The persistent object will load when a method of the proxy is invoked. See "Initializing collections and proxies" below.

`@BatchSize` specifies a "batch size" for fetching instances of this class by identifier. Not yet loaded instances are loaded batch-size at a time (default 1).

You can specific an arbitrary SQL WHERE condition to be used when retrieving objects of this class. Use `@Where` for that.

In the same vein, `@Check` lets you define an SQL expression used to generate a multi-row check constraint for automatic schema generation.

There is no difference between a view and a base table for a Hibernate mapping. This is transparent at the database level, although some DBMS do not support views properly, especially with updates. Sometimes you want to use a view, but you cannot create one in the database (i.e. with a legacy schema). In this case, you can map an immutable and read-only entity to a given SQL subselect expression using `@org.hibernate.annotations.Subselect`:

    @Entity

    @Subselect("select item.name, max(bid.amount), count(*) "

            + "from item "

            + "join bid on bid.item_id = item.id "

            + "group by item.name")

    @Synchronize( {"item", "bid"} ) //tables impacted

    public class Summary {

        @Id

        public String getId() { return id; }

        ...

    }

Déclarez les tables à synchroniser avec cette entité pour assurer que le flush automatique se produise correctement, et pour que les requêtes sur l'entité dérivée ne renvoient pas des données périmées. Le `<subselect>` est disponible comme attribut ou comme élément de mappage imbriqué.

We will now explore the same options using the hbm.xml structure. You can declare a persistent class using the `class` element. For example:

    <class
            name="ClassName"
            table="tableName"
            discriminator-value="discriminator_value"
            mutable="true|false"
            schema="owner"
            catalog="catalog"
            proxy="ProxyInterface"
            dynamic-update="true|false"
            dynamic-insert="true|false"
            select-before-update="true|false"
            polymorphism="implicit|explicit"
            where="arbitrary sql where condition"
            persister="PersisterClass"
            batch-size="N"
            optimistic-lock="none|version|dirty|all"
            lazy="(16)true|false"
            entity(17)-name="EntityName"
            check=(18)"arbitrary sql check condition"
            rowid=(19)"rowid"
            subsel(20)ect="SQL expression"
            abstra(21)ct="true|false"
            node="element-name"
    />

| `name` (optionnel) : le nom Java complet de la classe (ou interface) persistante. Si cet attribut est absent, nous supposons que ce mappage ne se rapporte pas à une entité POJO.
| `table` (optionnel - par défaut le nom non-qualifié de la classe) : le nom de sa table en base de données.
| `discriminator-value` (optionnel - par défaut le nom de la classe) : une valeur permettant de distinguer les différentes sous-classes utilisées dans le comportement polymorphique. Les valeurs `null` et `not null` sont autorisées.
| `mutable` (optionnel, vaut `true` par défaut) : spécifie que des instances de la classe sont (ou non) immuables.
| `schema` (optionnel) : surcharge le nom de schéma spécifié par l'élément racine `<hibernate-mappage>`.
| `catalog` (optionnel) : surcharge le nom du catalogue spécifié par l'élément racine `<hibernate-mappage>`.
| `proxy` (optionnel) : spécifie une interface à utiliser pour l'initialisation différée (lazy loading) des proxies. Vous pouvez indiquer le nom de la classe elle-même.
| `dynamic-update` (optionnel, par défaut à `false`) : spécifie que les SQL `UPDATE` doivent être générés à l'exécution et contenir uniquement les colonnes dont les valeurs ont été modifiées.
| `dynamic-insert` (optionnel, par défaut à `false`) : spécifie que les SQL `INSERT` doivent être générés à l'exécution et ne contenir que les colonnes dont les valeurs sont non nulles.
| `select-before-update` (optionnel, par défaut à `false`): spécifie que Hibernate ne doit jamais exécuter un SQL `UPDATE` sans être certain qu'un objet a été réellement modifié. Dans certains cas, (en réalité, seulement quand un objet transient a été associé à une nouvelle session par `update()`), cela signifie que Hibernate exécutera un SQL `SELECT` pour déterminer si un SQL `UPDATE` est véritablement nécessaire.
| `polymorphisms` (optional - defaults to `implicit`): determines whether implicit or explicit query polymorphisms is used.
| `where` (optionnel) spécifie une clause SQL `WHERE` à utiliser lorsque l'on récupère des objets de cette classe.
| `persister` (optionnel) : spécifie un `ClassPersister` particulier.
| `batch-size` (optionnel, par défaut = `1`) : spécifie une "taille de lot" pour remplir les instances de cette classe par identifiant en une seule requête.
| `optimistic-lock` (optionnel, par défaut = `version`) : détermine la stratégie de verrouillage optimiste.
(16) | `lazy` (optionnel) : l'extraction différée (lazy fetching) peut être totalement désactivée en configurant `lazy="false"`.
(17) | `entity-name` (optional - defaults to the class name): Hibernate3 allows a class to be mapped multiple times, potentially to different tables. It also allows entity mappings that are represented by Maps or XML at the Java level. In these cases, you should provide an explicit arbitrary name for the entity. See Section 4.4, « Modèles dynamiques » and Chapitre 20, Mappage XML for more information.
(18) | `check` (optionnel) : expression SQL utilisée pour générer une contrainte de vérification check multi-lignes pour la génération automatique de schéma.
(19) | `rowid` (optionnel) : Hibernate peut utiliser des ROWID sur les bases de données qui utilisent ce mécanisme. Par exemple avec Oracle, Hibernate peut utiliser la colonne additionnelle `rowid` pour des mise à jour rapides si cette option vaut `rowid`. Un ROWID est un détail d'implémentation et représente la localisation physique d'un uplet enregistré.
(20) | `subselect` (optionnel) : permet de mapper une entité immuable en lecture-seule sur un sous-select de base de données. Utile pour avoir une vue au lieu d'une table de base, mais à éviter. Voir plus bas pour plus d'informations.
(21) | `abstract` (optionnel) : utilisé pour marquer des superclasses abstraites dans des hiérarchies de `<union-subclass>`.

Il est tout à fait possible d'utiliser une interface comme nom de classe persistante. Vous devez alors déclarer les classes implémentant cette interface en utilisant l'élément `<subclass>`. Vous pouvez faire persister toute classe interne static. Vous devez alors spécifier le nom de la classe par la notation habituelle des classes internes, c'est à dire `eg.Foo$Bar`.

Here is how to do a virtual view (subselect) in XML:

    <class name="Summary">

        <subselect>

            select item.name, max(bid.amount), count(*)

            from item

            join bid on bid.item_id = item.id

            group by item.name

        </subselect>

        <synchronize table="item"/>

        <synchronize table="bid"/>

        <id name="name"/>

        ...

    </class>

The `<subselect>` is available both as an attribute and a nested mapping element.

### 5.1.2. Identifiers

Mapped classes must declare the primary key column of the database table. Most classes will also have a JavaBeans-style property holding the unique identifier of an instance.

Mark the identifier property with `@Id`.

    @Entity

    public class Person {

       @Id Integer getId() { ... }

       ...

    }

In hbm.xml, use the `<id>` element which defines the mapping from that property to the primary key column.

    <id
            name="propertyName"
            type="typename"
            column="column_name"
            unsaved-value="null|any|none|undefined|id_value"
            access="field|property|ClassName">
            node="element-name|@attribute-name|element/@attribute|."

            <generator class="generatorClass"/>
    </id>

| `name` (optionnel) : nom de la propriété de l'identifiant.
| `type` (optionnel) : nom indiquant le type Hibernate.
| `column` (optionnel - le nom de la propriété est pris par défaut) : nom de la colonne de la clé primaire.
| `unsaved-value` (optionnel - devient par défaut une valeur "sensible") : une valeur de propriété d'identifiant qui indique que l'instance est nouvellement instanciée (non sauvegardée), et qui la distingue des instances détachées qui ont été sauvegardées ou chargées dans une session précédente.
| `access` (optionnel - par défaut `property`) : la stratégie que doit utiliser Hibernate pour accéder aux valeurs des propriétés.

Si l'attribut `name` est absent, Hibernate considère que la classe ne possède pas de propriété d'identifiant.

The `unsaved-value` attribute is almost never needed in Hibernate3 and indeed has no corresponding element in annotations.

You can also declare the identifier as a composite identifier. This allows access to legacy data with composite keys. Its use is strongly discouraged for anything else.

#### 5.1.2.1. Composite identifier

You can define a composite primary key through several syntaxes:

- use a component type to represent the identifier and map it as a property in the entity: you then annotated the property as `@EmbeddedId`. The component type has to be `Serializable`.

- map multiple properties as `@Id` properties: the identifier type is then the entity class itself and needs to be `Serializable`. This approach is unfortunately not standard and only supported by Hibernate.

- map multiple properties as `@Id` properties and declare an external class to be the identifier type. This class, which needs to be `Serializable`, is declared on the entity via the `@IdClass` annotation. The identifier type must contain the same properties as the identifier properties of the entity: each property name must be the same, its type must be the same as well if the entity property is of a basic type, its type must be the type of the primary key of the associated entity if the entity property is an association (either a `@OneToOne` or a `@ManyToOne`).

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.

##### 5.1.2.1.1. id as a property using a component type

Here is a simple example of `@EmbeddedId`.

    @Entity

    class User {

       @EmbeddedId

       @AttributeOverride(name="firstName", column=@Column(name="fld_firstname")

       UserId id;

       Integer age;

    }

    @Embeddable

    class UserId implements Serializable {

       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

    class Customer {

       @EmbeddedId CustomerId id;

       boolean preferredCustomer;

       @MapsId("userId")

       @JoinColumns({

          @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),

          @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")

       })

       @OneToOne User user;

    }

    @Embeddable

    class CustomerId implements Serializable {

       UserId userId;

       String customerNumber;

       //implements equals and hashCode

    }

    @Entity

    class User {

       @EmbeddedId UserId id;

       Integer age;

    }

    @Embeddable

    class UserId implements Serializable {

       String firstName;

       String lastName;

       //implements equals and hashCode

    }

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

## Astuce

The component type used as identifier must implement `equals()` and `hashCode()`.

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

## Avertissement

The id value can be copied as late as flush time, don't rely on it until after flush time.

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

    class Customer {

       @EmbeddedId CustomerId id;

       boolean preferredCustomer;

    }

    @Embeddable

    class CustomerId implements Serializable {

       @OneToOne

       @JoinColumns({

          @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),

          @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")

       })

       User user;

       String customerNumber;

       //implements equals and hashCode

    }

    @Entity

    class User {

       @EmbeddedId UserId id;

       Integer age;

    }

    @Embeddable

    class UserId implements Serializable {

       String firstName;

       String lastName;

       //implements equals and hashCode

    }

Let's now rewrite these examples using the hbm.xml syntax.

    <composite-id

            name="propertyName"

            class="ClassName"

            mapped="true|false"

            access="field|property|ClassName"

            node="element-name|.">

            <key-property name="propertyName" type="typename" column="column_name"/>

            <key-many-to-one name="propertyName" class="ClassName" column="column_name"/>

            ......

    </composite-id>

First a simple example:

    <class name="User">

       <composite-id name="id" class="UserId">

          <key-property name="firstName" column="fld_firstname"/>

          <key-property name="lastName"/>

       </composite-id>

    </class>

Then an example showing how an association can be mapped.

    <class name="Customer">

       <composite-id name="id" class="CustomerId">

          <key-property name="firstName" column="userfirstname_fk"/>

          <key-property name="lastName" column="userfirstname_fk"/>

          <key-property name="customerNumber"/>

       </composite-id>

       <property name="preferredCustomer"/>

       <many-to-one name="user">

          <column name="userfirstname_fk" updatable="false" insertable="false"/>

          <column name="userlastname_fk" updatable="false" insertable="false"/>

       </many-to-one>

    </class>

    <class name="User">

       <composite-id name="id" class="UserId">

          <key-property name="firstName"/>

          <key-property name="lastName"/>

       </composite-id>

       <property name="age"/>

    </class>

Notice a few things in the previous example:

- the order of the properties (and column) matters. It must be the same between the association and the primary key of the associated entity

- the many to one uses the same columns as the primary key and thus must be marked as read only (`insertable` and `updatable` to false).

- unlike with `@MapsId`, the id value of the associated entity is not transparently copied, check the `foreign` id generator for more information.

The last example shows how to map association directly in the embedded id component.

    <class name="Customer">

       <composite-id name="id" class="CustomerId">

          <key-many-to-one name="user">

             <column name="userfirstname_fk"/>

             <column name="userlastname_fk"/>

          </key-many-to-one>

          <key-property name="customerNumber"/>

       </composite-id>

       <property name="preferredCustomer"/>

    </class>

    <class name="User">

       <composite-id name="id" class="UserId">

          <key-property name="firstName"/>

          <key-property name="lastName"/>

       </composite-id>

       <property name="age"/>

    </class>

This is the recommended approach to map composite identifier. The following options should not be considered unless some constraint are present.

##### 5.1.2.1.2. Multiple id properties without identifier type

Another, arguably more natural, approach is to place `@Id` on multiple properties of your entity. This approach is only supported by Hibernate (not JPA compliant) but does not require an extra embeddable component.

    @Entity

    class Customer implements Serializable {

       @Id @OneToOne

       @JoinColumns({

          @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),

          @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")

       })

       User user;

       @Id String customerNumber;

       boolean preferredCustomer;

       //implements equals and hashCode

    }

    @Entity

    class User {

       @EmbeddedId UserId id;

       Integer age;

    }

    @Embeddable

    class UserId implements Serializable {

       String firstName;

       String lastName;

       //implements equals and hashCode

    }

In this case `Customer` is its own identifier representation: it must implement `Serializable` and must implement `equals()` and `hashCode()`.

In hbm.xml, the same mapping is:

    <class name="Customer">

       <composite-id>

          <key-many-to-one name="user">

             <column name="userfirstname_fk"/>

             <column name="userlastname_fk"/>

          </key-many-to-one>

          <key-property name="customerNumber"/>

       </composite-id>

       <property name="preferredCustomer"/>

    </class>

    <class name="User">

       <composite-id name="id" class="UserId">

          <key-property name="firstName"/>

          <key-property name="lastName"/>

       </composite-id>

       <property name="age"/>

    </class>

##### 5.1.2.1.3. Multiple id properties with with a dedicated identifier type

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

## Avertissement

This approach is inherited from the EJB 2 days and we recommend against its use. But, after all it's your application and Hibernate supports it.

    @Entity

    @IdClass(CustomerId.class)

    class Customer implements Serializable {

       @Id @OneToOne

       @JoinColumns({

          @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),

          @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")

       })

       User user;

       @Id String customerNumber;

       boolean preferredCustomer;

    }

    class CustomerId implements Serializable {

       UserId user;

       String customerNumber;

       //implements equals and hashCode

    }

    @Entity

    class User {

       @EmbeddedId UserId id;

       Integer age;

       //implements equals and hashCode

    }

    @Embeddable

    class UserId implements Serializable {

       String firstName;

       String lastName;

       //implements equals and hashCode

    }

`Customer` and `CustomerId` do have the same properties `customerNumber` as well as `user`. `CustomerId` must be `Serializable` and implement `equals()` and `hashCode()`.

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

    @Entity

    @IdClass(CustomerId.class)

    class Customer implements Serializable {

       @Id @OneToOne

       @JoinColumns({

          @JoinColumn(name="userfirstname_fk", referencedColumnName="firstName"),

          @JoinColumn(name="userlastname_fk", referencedColumnName="lastName")

       })

       User user;

       @Id String customerNumber;

       boolean preferredCustomer;

    }

    class CustomerId implements Serializable {

       @OneToOne User user;

       String customerNumber;

       //implements equals and hashCode

    }

    @Entity

    class User {

       @EmbeddedId UserId id;

       Integer age;

       //implements equals and hashCode

    }

    @Embeddable

    class UserId implements Serializable {

      String firstName;

      String lastName;

    }

This feature is of limited interest though as you are likely to have chosen the `@IdClass` approach to stay JPA compliant or you have a quite twisted mind.

Here are the equivalent on hbm.xml files:

    <class name="Customer">

       <composite-id class="CustomerId" mapped="true">

          <key-many-to-one name="user">

             <column name="userfirstname_fk"/>

             <column name="userlastname_fk"/>

          </key-many-to-one>

          <key-property name="customerNumber"/>

       </composite-id>

       <property name="preferredCustomer"/>

    </class>

    <class name="User">

       <composite-id name="id" class="UserId">

          <key-property name="firstName"/>

          <key-property name="lastName"/>

       </composite-id>

       <property name="age"/>

    </class>

#### 5.1.2.2. Identifier generator

Hibernate can generate and populate identifier values for you automatically. This is the recommended approach over "business" or "natural" id (especially composite ids).

Hibernate offers various generation strategies, let's explore the most common ones first that happens to be standardized by JPA:

- IDENTITY: supports identity columns in DB2, MySQL, MS SQL Server, Sybase and HypersonicSQL. The returned identifier is of type `long`, `short` or `int`.

- SEQUENCE (called `seqhilo` in Hibernate): uses a hi/lo algorithm to efficiently generate identifiers of type `long`, `short` or `int`, given a named database sequence.

- TABLE (called `MultipleHiLoPerTableGenerator` in Hibernate) : uses a hi/lo algorithm to efficiently generate identifiers of type `long`, `short` or `int`, given a table and column as a source of hi values. The hi/lo algorithm generates identifiers that are unique only for a particular database.

- AUTO: selects `IDENTITY`, `SEQUENCE` or `TABLE` depending upon the capabilities of the underlying database.

## Important

We recommend all new projects to use the new enhanced identifier generators. They are deactivated by default for entities using annotations but can be activated using `hibernate.id.new_generator_mappings=true`. These new generators are more efficient and closer to the JPA 2 specification semantic.

However they are not backward compatible with existing Hibernate based application (if a sequence or a table is used for id generation). See XXXXXXX ??? for more information on how to activate them.

To mark an id property as generated, use the `@GeneratedValue` annotation. You can specify the strategy used (default to `AUTO`) by setting `strategy`.

    @Entity

    public class Customer {

       @Id @GeneratedValue

       Integer getId() { ... };

    }

    @Entity

    public class Invoice {

       @Id @GeneratedValue(strategy=GenerationType.IDENTITY)

       Integer getId() { ... };

    }

`SEQUENCE` and `TABLE` require additional configurations that you can set using `@SequenceGenerator` and `@TableGenerator`:

- `name`: name of the generator

- `table` / `sequenceName`: name of the table or the sequence (defaulting respectively to `hibernate_sequences` and `hibernate_sequence`)

- `catalog` / `schema`:

- `initialValue`: the value from which the id is to start generating

- `allocationSize`: the amount to increment by when allocating id numbers from the generator

In addition, the `TABLE` strategy also let you customize:

- `pkColumnName`: the column name containing the entity identifier

- `valueColumnName`: the column name containing the identifier value

- `pkColumnValue`: the entity identifier

- `uniqueConstraints`: any potential column constraint on the table containing the ids

To link a table or sequence generator definition with an actual generated property, use the same name in both the definition `name` and the generator value `generator` as shown below.

    @Id

    @GeneratedValue(

        strategy=GenerationType.SEQUENCE,

        generator="SEQ_GEN")

    @javax.persistence.SequenceGenerator(

        name="SEQ_GEN",

        sequenceName="my_sequence",

        allocationSize=20

    )

    public Integer getId() { ... }

The scope of a generator definition 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 in JPA's XML deployment descriptors (see XXXXXX ???):

    <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 a JPA XML descriptor (like `META-INF/orm.xml`) is used to define the generators, `EMP_GEN` and `SEQ_GEN` are application level generators.

## Note

Package level definition is not supported by the JPA specification. However, you can use the `@GenericGenerator` at the package level (see ???).

These are the four standard JPA generators. Hibernate goes beyond that and provide additional generators or additional options as we will see below. You can also write your own custom identifier generator by implementing `org.hibernate.id.IdentifierGenerator`.

To define a custom generator, use the `@GenericGenerator` annotation (and its plural counter part `@GenericGenerators`) that describes the class of the identifier generator or its short cut name (as described below) and a list of key/value parameters. When using `@GenericGenerator` and assigning it via `@GeneratedValue.generator`, the `@GeneratedValue.strategy` is ignored: leave it blank.

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

    @GenericGenerator(name="system-uuid", strategy = "uuid")

    public String getId() {

    @Id @GeneratedValue(generator="trigger-generated")

    @GenericGenerator(

        name="trigger-generated",

        strategy = "select",

        parameters = @Parameter(name="key", value = "socialSecurityNumber")

    )

    public String getId() {

The hbm.xml approach uses the optional `<generator>` child element inside `<id>`. If any parameters are required to configure or initialize the generator instance, they are passed using the `<param>` element.

    <id name="id" type="long" column="cat_id">

            <generator class="org.hibernate.id.TableHiLoGenerator">

                    <param name="table">uid_table</param>

                    <param name="column">next_hi_value_column</param>

            </generator>

    </id>

##### 5.1.2.2.1. Various additional generators

Tous les générateurs implémentent l'interface `org.hibernate.id.IdentifierGenerator`. C'est une interface très simple ; certaines applications peuvent proposer leurs propres implémentations spécialisées. Cependant, Hibernate propose une série d'implémentations intégrées. Il existe des noms raccourcis pour les générateurs intégrés :

`increment`

  génère des identifiants de type `long`, `short` ou `int` qui ne sont uniques que si aucun autre processus n'insère de données dans la même table. Ne pas utiliser en environnement clusterisé.

`identity`

  prend en charge les colonnes d'identité dans DB2, MySQL, MS SQL Server, Sybase et HypersonicSQL. L'identifiant renvoyé est de type `long`, `short` ou `int`.

`sequence`

  utilise une séquence dans DB2, PostgreSQL, Oracle, SAP DB, McKoi ou un générateur dans Interbase. L'identifiant renvoyé est de type `long`, `short` ou `int`

`hilo`

  utilise un algorithme hi/lo pour générer de façon efficace des identifiants de type `long`, `short` ou `int`, en prenant comme source de valeurs "hi" une table et une colonne (par défaut `hibernate_unique_key` et `next_hi` respectivement). L'algorithme hi/lo génère des identifiants uniques pour une base de données particulière seulement.

`seqhilo`

  utilise un algorithme hi/lo pour générer efficacement des identifiants de type `long`, `short` ou `int`, en prenant une séquence en base nommée.

`uuid`

  Generates a 128-bit UUID based on a custom algorithm. The value generated is represented as a string of 32 hexidecimal digits. Users can also configure it to use a separator (config parameter "separator") which separates the hexidecimal digits into 8{sep}8{sep}4{sep}8{sep}4. Note specifically that this is different than the IETF RFC 4122 representation of 8-4-4-4-12. If you need RFC 4122 compliant UUIDs, consider using "uuid2" generator discussed below.

`uuid2`

  Generates a IETF RFC 4122 compliant (variant 2) 128-bit UUID. The exact "version" (the RFC term) generated depends on the pluggable "generation strategy" used (see below). Capable of generating values as `java.util.UUID`, `java.lang.String` or as a byte array of length 16 (`byte[16]`). The "generation strategy" is defined by the interface `org.hibernate.id.UUIDGenerationStrategy`. The generator defines 2 configuration parameters for defining which generation strategy to use:

  `uuid_gen_strategy_class`

    Names the UUIDGenerationStrategy class to use

  `uuid_gen_strategy`

    Names the UUIDGenerationStrategy instance to use

  Out of the box, comes with the following strategies:

  - `org.hibernate.id.uuid.StandardRandomStrategy` (the default) - generates "version 3" (aka, "random") UUID values via the `randomUUID` method of `java.util.UUID`

  - `org.hibernate.id.uuid.CustomVersionOneStrategy` - generates "version 1" UUID values, using IP address since mac address not available. If you need mac address to be used, consider leveraging one of the existing third party UUID generators which sniff out mac address and integrating it via the `org.hibernate.id.UUIDGenerationStrategy` contract. Two such libraries known at time of this writing include http://johannburkard.de/software/uuid/ and http://commons.apache.org/sandbox/id/uuid.html

`guid`

  utilise une chaîne GUID générée par la base pour MS SQL Server et MySQL.

`native`

  choisit `identity`, `sequence` ou `hilo` selon les possibilités offertes par la base de données sous-jacente.

`assigned`

  permet à l'application d'affecter un identifiant à l'objet avant que la méthode `save()` soit appelée. Il s'agit de la stratégie par défaut si aucun `<generator>` n'est spécifié.

`select`

  récupère une clé primaire assignée par un déclencheur (trigger) de base de données en sélectionnant la ligne par une clé unique quelconque et en extrayant la valeur de la clé primaire.

`foreign`

  utilise l'identifiant d'un autre objet associé. Habituellement utilisé en conjonction avec une association `<one-to-one>` sur la clé primaire.

`sequence-identity`

  Une stratégie de génération de séquence spécialisée qui utilise une séquence de base de données pour la génération réelle de valeurs, tout en utilisant JDBC3 getGeneratedKeys pour retourner effectivement la valeur d'identifiant générée, comme faisant partie de l'exécution de la déclaration insert. Cette stratégie est uniquement prise en charge par les pilotes Oracle 10g pour JDK 1.4. Notez que les commentaires sur ces déclarations insert sont désactivés à cause d'un bogue dans les pilotes d'Oracle.

##### 5.1.2.2.2. Algorithme Hi/lo

Les générateurs `hilo` et `seqhilo` proposent deux implémentations alternatives de l'algorithme hi/lo. La première implémentation nécessite une table "spéciale" en base pour héberger la prochaine valeur "hi" disponible. La seconde utilise une séquence de type Oracle (quand la base sous-jacente le propose).

    <id name="id" type="long" column="cat_id">

            <generator class="hilo">

                    <param name="table">hi_value</param>

                    <param name="column">next_value</param>

                    <param name="max_lo">100</param>

            </generator>

    </id>

    <id name="id" type="long" column="cat_id">

            <generator class="seqhilo">

                    <param name="sequence">hi_value</param>

                    <param name="max_lo">100</param>

            </generator>

    </id>

Malheureusement, vous ne pouvez pas utiliser `hilo` quand vous apportez votre propre `Connection` à Hibernate. Quand Hibernate utilise une datasource du serveur d'application pour obtenir des connexions inscrites avec JTA, vous devez correctement configurer `hibernate.transaction.manager_lookup_class`.

##### 5.1.2.2.3. Algorithme UUID

Le contenu du UUID est : l'adresse IP, la date de démarrage de la JVM (précis au quart de seconde), l'heure système et une contre-valeur (unique au sein de la JVM). Il n'est pas possible d'obtenir une adresse MAC ou une adresse mémoire à partir de Java, c'est donc le mieux que l'on puisse faire sans utiliser JNI.

##### 5.1.2.2.4. Colonnes identifiantes et séquences

Pour les bases qui implémentent les colonnes "identité" (DB2, MySQL, Sybase, MS SQL), vous pouvez utiliser la génération de clé par `identity`. Pour les bases qui implémentent les séquences (DB2, Oracle, PostgreSQL, Interbase, McKoi, SAP DB) vous pouvez utiliser la génération de clé par `sequence`. Ces deux méthodes nécessitent deux requêtes SQL pour insérer un nouvel objet. Par exemple :

    <id name="id" type="long" column="person_id">

            <generator class="sequence">

                    <param name="sequence">person_id_sequence</param>

            </generator>

    </id>

    <id name="id" type="long" column="person_id" unsaved-value="0">

            <generator class="identity"/>

    </id>

Pour le développement multi-plateformes, la stratégie `native` choisira entre les méthodes `identity`, `sequence` et `hilo`, selon les possibilités offertes par la base sous-jacente.

##### 5.1.2.2.5. Identifiants assignés

If you want the application to assign identifiers, as opposed to having Hibernate generate them, you can use the `assigned` generator. This special generator uses the identifier value already assigned to the object's identifier property. The generator is used when the primary key is a natural key instead of a surrogate key. This is the default behavior if you do not specify `@GeneratedValue` nor `<generator>` elements.

Choisir le générateur `assigned` fait que Hibernate utilise`unsaved-value="undefined"`, le forçant ainsi à interroger la base de données pour déterminer si une instance est transiente ou détachée, à moins d'utiliser une propriété version ou timestamp, ou alors de définir `Interceptor.isUnsaved()`.

##### 5.1.2.2.6. Clés primaires assignées par les triggers

Pour les schémas de base hérités d'anciens systèmes uniquement (Hibernate ne génère pas de DDL avec des triggers)

    <id name="id" type="long" column="person_id">

            <generator class="select">

                    <param name="key">socialSecurityNumber</param>

            </generator>

    </id>

Dans l'exemple ci-dessus, il y a une valeur de propriété unique appelée `socialSecurityNumber`. Elle est définie par la classe en tant que clé naturelle et il y a également une clé secondaire appelée `person_id` dont la valeur est générée par un trigger.

##### 5.1.2.2.7. Identity copy (foreign generator)

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

    class MedicalHistory implements Serializable {

      @Id @OneToOne

      @JoinColumn(name = "person_id")

      Person patient;

    }

    @Entity

    public class Person implements Serializable {

      @Id @GeneratedValue Integer id;

    }

Or alternatively

    @Entity

    class MedicalHistory implements Serializable {

      @Id Integer id;

      @MapsId @OneToOne

      @JoinColumn(name = "patient_id")

      Person patient;

    }

    @Entity

    class Person {

      @Id @GeneratedValue Integer id;

    }

In hbm.xml use the following approach:

    <class name="MedicalHistory">

       <id name="id">

          <generator class="foreign">

             <param name="property">patient</param>

          </generator>

       </id>

       <one-to-one name="patient" class="Person" constrained="true"/>

    </class>

#### 5.1.2.3. La méthode getter de l'identifiant

A partir de la version 3.2.3, 2 générateurs représentent une nouvelle conception de 2 aspects séparés de la génération d'identifiants. Le premier aspect est la portabilité de la base de données; le second est l'optimization, c'est à dire que vous n'avez pas à interroger la base de données pour chaque requête de valeur d'identifiant. Ces deux nouveaux générateurs sont sensés prendre la place de générateurs décrits ci-dessus, ayant pour préfixe 3.3.x. Cependant, ils sont inclus dans les versions actuelles, et peuvent être référencés par FQN.

Le premier de ces nouveaux générateurs est `org.Hibernate.ID.Enhanced.SequenceStyleGenerator` qui est destiné, tout d'abord, comme un remplacement pour le générateur `séquence` et, deuxièmement, comme un générateur de portabilité supérieur à `natif`. C'est parce que `natif` a généralement le choix entre `identité` et `séquence` qui ont des sémantiques largement différentes, ce qui peut entraîner des problèmes subtils en observant la portabilité des applications. `org.Hibernate.ID.Enhanced SequenceStyleGenerator.`, cependant, réalise la portabilité d'une manière différente. Il choisit entre une table ou une séquence dans la base de données pour stocker ses valeurs s'incrémentant, selon les capacités du dialecte utilisé. La différence avec `natif` c'est que de stockage basé sur les tables ou basé sur la séquence ont la même sémantique. En fait, les séquences sont exactement ce qu'Hibernate essaie d'émuler avec ses générateurs basée sur les tables. Ce générateur a un certain nombre de paramètres de configuration :

- `sequence_name` (en option, par défaut = `hibernate_sequence`): le nom de la séquence ou table à utiliser.

- `initial_value` (en option - par défaut = `1`) : la première valeur à extraire de la séquence/table. En termes de création de séquences, c'est semblable à la clause qui s'appelle "STARTS WITH" normalement.

- `increment_size` (en option - par défaut = `1`): la valeur par laquelle les appels suivants à la séquence / table doivent différer. En termes de création de séquence, c'est analogue à la clause généralement nommé "INCREMENT BY".

- `force_table_use` (optionnel - par défaut = `false`) : doit-on forcer l'utilisation de la table en tant que structure de soutien même si le dialecte peut supporter la séquence ?

- `value_column` (en option - par défaut = `next_val`): uniquement utile pour les structures de tables. Correspond au nom de la colonne de la table qui est utilisée pour contenir la valeur.

- `optimizer` (optional - defaults to `none`): See Section 5.1.2.3.1, « Optimisation du générateur d'identifiants »

Le deuxième de ces nouveaux générateurs est `org.Hibernate.ID.Enhanced.TableGenerator`, qui est destiné, tout d'abord, comme un remplacement pour le générateur de la `table`, même si elle fonctionne effectivement beaucoup plus comme `org.Hibernate.ID.MultipleHiLoPerTableGenerator`et deuxièmement, comme une remise en œuvre de `org.Hibernate.ID.MultipleHiLoPerTableGenerator`, qui utilise la notion d'optimizers enfichables. Essentiellement ce générateur définit une table susceptible de contenir un certain nombre de valeurs d'incrément différents simultanément à l'aide de plusieurs lignes distinctement masquées. Ce générateur a un certain nombre de paramètres de configuration :

- `table_name` (en optin - valeur par défaut = `hibernate_sequences`): le nom de la table à utiliser.

- `value_column_name` (en option - valeur par défaut =`next_val`): le nom de la colonne contenue dans la table utilisée pour la valeur.

- `segment_column_name` (en option - par défaut = `sequence_name`): le nom de la colonne de la table qui est utilisée pour contenir la "segment key". Il s'agit de la valeur qui identifie la valeur d'incrément à utiliser.

- `segment_value` (en option - par défaut = `par défaut`): La "segment key"valeur pour le segment à partir de laquelle nous voulons extraire des valeurs d'incrémentation pour ce générateur.

- `segment_value_length` (en option - par défaut = `255`): Utilisée pour la génération de schéma ; la taille de la colonne pour créer cette colonne de clé de segment.

- `initial_value` (en option - par défaut est `1` : La valeur initiale à récupérer à partir de la table.

- `increment_size` (en option - par défaut = `1`): La valeur par laquelle les appels à la table, qui suivent, devront différer.

- `optimizer` (optional - defaults to `??`): See Section 5.1.2.3.1, « Optimisation du générateur d'identifiants ».

##### 5.1.2.3.1. Optimisation du générateur d'identifiants

For identifier generators that store values in the database, it is inefficient for them to hit the database on each and every call to generate a new identifier value. Instead, you can group a bunch of them in memory and only hit the database when you have exhausted your in-memory value group. This is the role of the pluggable optimizers. Currently only the two enhanced generators (Section 5.1.2.3, « La méthode getter de l'identifiant » support this operation.

- `aucun` (en général il s'agit de la valeur par défaut si aucun optimizer n'a été spécifié): n'effectuera pas d'optimisations et n'interrogera pas la base de données à chaque demande.

- `hilo`: applique un algorithme hi/lo autour des valeurs extraites des base de données. Les valeurs de la base de données de cet optimizer sont censées être séquentielles. Les valeurs extraites de la structure des base de données pour cet optimizer indique le "numéro de groupe". Le `increment_size` est multiplié par cette valeur en mémoire pour définir un groupe de "hi value".

- `mise en commun`: tout comme dans le cas de `hilo`, cet optimizer tente de réduire le nombre d'interrogations vers la base de données. Ici, cependant, nous avons simplement stocké la valeur de départ pour le "prochain groupe"dans la structure de la base de données plutôt qu'une valeur séquentielle en combinaison avec un algorithme de regroupement en mémoire. Ici, `increment_size` fait référence aux valeurs provenant de la base de données.

#### 5.1.2.4. Partial identifier generation

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

## Avertissement

The Hibernate team has always felt such a construct as fundamentally wrong. Try hard to fix your data model before using this feature.

    @Entity

    public class CustomerInventory implements Serializable {

      @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

    public class Customer implements Serializable {

       @Id

       private int id;

    }

You can also generate properties inside an `@EmbeddedId` class.

### 5.1.3. Optimistic locking properties (optional)

When using long transactions or conversations that span several database transactions, it is useful to store versioning data to ensure that if the same entity is updated by two conversations, the last to commit changes will be informed and not override the other conversation's work. It guarantees some isolation while still allowing for good scalability and works particularly well in read-often write-sometimes situations.

You can use two approaches: a dedicated version number or a timestamp.

Une propriété de version ou un timestamp ne doit jamais être null pour une instance détachée, ainsi Hibernate pourra détecter toute instance ayant une version ou un timestamp null comme transient, quelles que soient les stratégies `unsaved-value` spécifiées. Déclarer un numéro de version ou un timestamp "nullable" est un moyen pratique d'éviter tout problème avec les ré-attachements transitifs dans Hibernate, particulièrement utile pour ceux qui utilisent des identifiants assignés ou des clés composées .

#### 5.1.3.1. Version number

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

    @Entity

    public class Flight implements Serializable {

    ...

        @Version

        @Column(name="OPTLOCK")

        public Integer 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. 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`.

If the version number is generated by the database (via a trigger for example), make sure to use `@org.hibernate.annotations.Generated(GenerationTime.ALWAYS).`

To declare a version property in hbm.xml, use:

    <version
            column="version_column"
            name="propertyName"
            type="typename"
            access="field|property|ClassName"
            unsaved-value="null|negative|undefined"
            generated="never|always"
            insert="true|false"
            node="element-name|@attribute-name|element/@attribute|."
    />

| `column` (optionnel - par défaut égal au nom de la propriété) : le nom de la colonne contenant le numéro de version.
| `name` : le nom d'un attribut de la classe persistante.
| `type` (optionnel - par défaut à `integer`) : le type du numéro de version.
| `access` (optionnel - par défaut `property`) : la stratégie que doit utiliser Hibernate pour accéder aux valeurs des propriétés.
| `unsaved-value` (optionnel - par défaut à `undefined`) : une valeur de la propriété d'identifiant qui indique que l'instance est nouvellement instanciée (non sauvegardée), et qui la distingue des instances détachées qui ont été sauvegardées ou chargées dans une session précédente. `Undefined` indique que la valeur de la propritété identifiant devrait être utilisée.
| `generated` (optional - defaults to `never`): specifies that this version property value is generated by the database. See the discussion of generated properties for more information.
| `insert` (optionnel - par défaut à `true`) : indique si la colonne de version doit être incluse dans les ordres SQL insert. Peut être configuré à `false` si et seulement si la colonne de la base de données est définie avec une valeur par défaut égale à `0`.

#### 5.1.3.2. Timestamp

Alternatively, you can use a timestamp. Timestamps are a less safe implementation of optimistic locking. However, sometimes an application might use the timestamps in other ways as well.

Simply mark a property of type `Date` or `Calendar` as `@Version`.

    @Entity

    public class Flight implements Serializable {

    ...

        @Version

        public Date getLastUpdate() { ... }

    }

When using timestamp versioning you can tell Hibernate where to retrieve the timestamp value from - database or JVM - by optionally adding the `@org.hibernate.annotations.Source` annotation to the property. Possible values for the value attribute of the annotation are `org.hibernate.annotations.SourceType.VM` and `org.hibernate.annotations.SourceType.DB`. The default is `SourceType.DB` which is also used in case there is no `@Source` annotation at all.

Like in the case of version numbers, the timestamp can also be generated by the database instead of Hibernate. To do that, use `@org.hibernate.annotations.Generated(GenerationTime.ALWAYS).`

In hbm.xml, use the `<timestamp>` element:

    <timestamp
            column="timestamp_column"
            name="propertyName"
            access="field|property|ClassName"
            unsaved-value="null|undefined"
            source="vm|db"
            generated="never|always"
            node="element-name|@attribute-name|element/@attribute|."
    />

| `column` (optionnel - par défaut devient le nom de la propriété) : le nom d'une colonne contenant le timestamp.
| `name` : le nom d'une propriété au sens JavaBean de type Java `Date` ou `Timestamp` de la classe persistante.
| `access` (optionnel - par défaut `property`) : la stratégie que doit utiliser Hibernate pour accéder aux valeurs des propriétés.
| `unsaved-value` (optionnel - par défaut à `null`) : propriété dont la valeur est un numéro de version qui indique que l'instance est nouvellement instanciée (non sauvegardée), et qui la distingue des instances détachées qui ont été sauvegardées ou chargées dans une session précédente. (`undefined` indique que la valeur de propriété identifiant devrait être utilisée).
| `source` (optionnel - par défaut à `vm`) : d'où Hibernate doit-il récupérer la valeur du timestamp? Depuis la base de données ou depuis la JVM d'exécution? Les valeurs de timestamp de la base de données provoquent une surcharge puisque Hibernate doit interroger la base pour déterminer la prochaine valeur mais cela est plus sûr lorsque vous fonctionnez dans un cluster. Remarquez aussi que certains des `Dialect` s ne supportent pas cette fonction, et que d'autres l'implémentent mal, à cause d'un manque de précision (Oracle 8 par exemple).
| `generated` (optional - defaults to `never`): specifies that this timestamp property value is actually generated by the database. See the discussion of generated properties for more information.

## Note

Notez que `<timestamp>` est équivalent à `<version type="timestamp">` et `<timestamp source="db">` équivaut à `<version type="dbtimestamp">`

### 5.1.4. Property

You need to decide which property needs to be made persistent in a given entity. This differs slightly between the annotation driven metadata and the hbm.xml files.

#### 5.1.4.1. Property mapping with annotations

In the annotations world, 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. If set to `LAZY`, specifies that this property should be fetched lazily when the instance variable is first accessed. It requires build-time bytecode instrumentation, if your classes are not instrumented, property level lazy loading is silently ignored. The default is `EAGER`. You can also mark a property as not optional thanks to the `@Basic.optional` attribute. This will ensure that the underlying column are not nullable (if possible). Note that a better approach is to use the `@NotNull` annotation of the Bean Validation specification.

Let's look at a few examples:

    public transient int counter; //transient property

    private String 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 Hibernate. `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 supports 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

    public String getFullText() {

        return fullText;

    }

    @Lob

    public byte[] 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.

##### 5.1.4.1.1. Type

You can also manually specify a type using the `@org.hibernate.annotations.Type` and some parameters if needed. `@Type.type` could be:

1. Le nom d'un type basique Hibernate (par ex : `integer, string, character, date, timestamp, float, binary, serializable, object, blob` etc.).

2. le nom d'une classe Java avec un type basique par défaut (par ex : `int, float, char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob` etc.).

3. Le nom d'une classe Java sérialisable.

4. Le nom d'une classe avec un type personnalisé (par ex : `com.illflow.type.MyCustomType`).

If you do not specify a type, Hibernate will use reflection upon the named property and guess the correct Hibernate type. Hibernate will attempt to interpret the name of the return class of the property getter using, in order, rules 2, 3, and 4.

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

## Note

Package level annotations are placed in a file named `package-info.java` in the appropriate package. Place your annotations before the package declaration.

    @TypeDef(

       name = "phoneNumber",

       defaultForType = PhoneNumber.class,

       typeClass = PhoneNumberType.class

    )

    @Entity

    public class ContactDetails {

       [...]

       private PhoneNumber localPhoneNumber;

       @Type(type="phoneNumber")

       private OverseasPhoneNumber 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

    public class Forest {

        @Type(type="caster")

        public String 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")

    })

    public MonetaryAmount getAmount() {

        return amount;

    }

    public class MonetaryAmount implements Serializable {

        private BigDecimal amount;

        private Currency currency;

        ...

    }

##### 5.1.4.1.2. Access type

By default the access type of a class hierarchy is defined by the position of the `@Id` or `@EmbeddedId` annotations. If these annotations are on a field, then only fields are considered for persistence and the state is accessed via the field. If there annotations are on a getter, then only the getters are considered for persistence and the state is accessed via the getter/setter. That works well in practice and is the recommended approach.

## Note

The placement of annotations within a class hierarchy has to be consistent (either field or on property) to be able to determine the default access type. It is recommended to stick to one single annotation placement strategy throughout your whole application.

However in some situations, you need to:

- force the access type of the entity hierarchy

- override the access type of a specific entity in the class hierarchy

- override the access type of an embeddable type

The best use case is an embeddable class used by several entities that might not use the same access type. In this case it is better to force the access type at the embeddable class level.

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

    @Entity

    public class Order {

       @Id private Long id;

       public Long getId() { return id; }

       public void setId(Long id) { this.id = id; }

       @Embedded private Address address;

       public Address getAddress() { return address; }

       public void setAddress() { this.address = address; }

    }

    @Entity

    public class User {

       private Long id;

       @Id public Long getId() { return id; }

       public void setId(Long id) { this.id = id; }

       private Address address;

       @Embedded public Address getAddress() { return address; }

       public void setAddress() { this.address = address; }

    }

    @Embeddable

    @Access(AcessType.PROPERTY)

    public class Address {

       private String street1;

       public String getStreet1() { return street1; }

       public void 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

    public class Order {

       @Id private Long id;

       public Long getId() { return id; }

       public void setId(Long id) { this.id = id; }

       @Transient private String userId;

       @Transient private String orderId;

       @Access(AccessType.PROPERTY)

       public String getOrderNumber() { return userId + ":" + orderId; }

       public void 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`.

## @org.hibernate.annotations.AccessType

The annotation `@org.hibernate.annotations.AccessType` should be considered deprecated for FIELD and PROPERTY access. It is still useful however if you need to use a custom access type.

##### 5.1.4.1.3. Optimistic lock

It is sometimes useful to avoid increasing the version number even if a given property is dirty (particularly collections). You can do that by annotating the property (or collection) with `@OptimisticLock(excluded=true)`.

More formally, specifies that updates to this property do not require acquisition of the optimistic lock.

##### 5.1.4.1.4. Declaring column attributes

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

- not annotated at all

- annotated with `@Basic`

- annotated with `@Version`

- annotated with `@Lob`

- annotated with `@Temporal`

    @Entity

    public class Flight implements Serializable {

    ...

    @Column(updatable = false, name = "flight_name", nullable = false, length=50)

    public String 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="columnName";
        boolean unique() default false;
        boolean nullable() default true;
        boolean insertable() default true;
        boolean updatable() default true;
        String columnDefinition() default "";
        String table() default "";
        int length() default 255;
        int precision() default 0; // decimal precision
        int scale() default 0; // decimal scale

| `name` (optional): the column name (default to the property name)
| `unique` (optional): set a unique constraint on this column or not (default false)
| `nullable` (optional): set the column as nullable (default true).
| `insertable` (optional): whether or not the column will be part of the insert statement (default true)
| `updatable` (optional): whether or not the column will be part of the update statement (default true)
| `columnDefinition` (optional): override the sql DDL fragment for this particular column (non portable)
| `table` (optional): define the targeted table (default primary table)
| ``length`` (optional): column length (default 255)
| ``precision`` (optional): column decimal precision (default 0)
| ``scale`` (optional): column decimal scale if useful (default 0)

##### 5.1.4.1.5. Formula

Sometimes, you want the Database to do some computation for you rather than in the JVM, you might also create some kind of virtual column. You can use a SQL fragment (aka formula) instead of mapping a property into a column. This kind of property is read only (its value is calculated by your formula fragment).

    @Formula("obj_length * obj_height * obj_width")

    public long getObjectVolume()

The SQL fragment can be as complex as you want and even include subselects.

##### 5.1.4.1.6. Non-annotated property defaults

If a property is not annotated, the following rules apply:

- If the property is of a single type, it is mapped as @Basic

- Otherwise, if the type of the property is annotated as @Embeddable, it is mapped as @Embedded

- Otherwise, if the type of the property is `Serializable`, it is mapped as `@Basic` in a column holding the object in its serialized version

- Otherwise, if the type of the property is `java.sql.Clob` or `java.sql.Blob`, it is mapped as `@Lob` with the appropriate `LobType`

#### 5.1.4.2. Property mapping with hbm.xml

L'élément `<property>` déclare une propriété persistante de la classe au sens JavaBean.

    <property
            name="propertyName"
            column="column_name"
            type="typename"
            update="true|false"
            insert="true|false"
            formula="arbitrary SQL expression"
            access="field|property|ClassName"
            lazy="true|false"
            unique="true|false"
            not-null="true|false"
            optimistic-lock="true|false"
            generated="never|insert|always"
            node="element-name|@attribute-name|element/@attribute|."
            index="index_name"
            unique_key="unique_key_id"
            length="L"
            precision="P"
            scale="S"
    />

| `name` : nom de la propriété, avec une lettre initiale en minuscule.
| `column` (optionnel - par défaut au nom de la propriété) : le nom de la colonne mappée. Cela peut aussi être indiqué dans le(s) sous-élément(s) `<column>` imbriqués.
| `type` (optionnel) : nom indiquant le type Hibernate.
| `update, insert` (optionnel - par défaut à `true`) : indique que les colonnes mappées devraient être incluses dans des déclarations SQL `UPDATE` et/ou des `INSERT`. Mettre les deux à `false` autorise une propriété pure dérivée dont la valeur est initialisée de quelque autre propriété qui mappe à la même colonne(s) ou par un trigger ou une autre application. (utile si vous savez qu'un trigger affectera la valeur à la colonne).
| `formula` (optionnel) : une expression SQL qui définit la valeur pour une propriété calculée. Les propriétés calculées ne possèdent pas leur propre mappage.
| `access` (optionnel - par défaut `property`) : la stratégie que doit utiliser Hibernate pour accéder aux valeurs des propriétés.
| `lazy` (optionnel - par défaut à `false`) : indique que cette propriété devrait être chargée en différé (lazy loading) quand on accède à la variable d'instance pour la première fois (nécessite une instrumentation du bytecode lors de la phase de construction).
| `unique` (optionnel) : génère le DDL d'une contrainte d'unicité pour les colonnes. Permet aussi d'en faire la cible d'une `property-ref`.
| `not-null` (optionnel) : génère le DDL d'une contrainte de nullité pour les colonnes.
| `optimistic-lock` (optionnel - par défaut à `true`) : indique si les mise à jour de cette propriété nécessitent ou non l'acquisition d'un verrou optimiste. En d'autres termes, cela détermine s'il est nécessaire d'incrémenter un numéro de version quand cette propriété est marquée obsolète (dirty).
| `generated` (optional - defaults to `never`): specifies that this property value is actually generated by the database. See the discussion of generated properties for more information.

typename peut être :

1. Le nom d'un type basique Hibernate (par ex : `integer, string, character, date, timestamp, float, binary, serializable, object, blob` etc.).

2. le nom d'une classe Java avec un type basique par défaut (par ex : `int, float, char, java.lang.String, java.util.Date, java.lang.Integer, java.sql.Clob` etc.).

3. Le nom d'une classe Java sérialisable.

4. Le nom d'une classe avec un type personnalisé (par ex : `com.illflow.type.MyCustomType`).

Si vous n'indiquez pas un type, Hibernate utilisera la réflexion sur le nom de la propriété pour tenter de trouver le type Hibernate correct. Hibernate essayera d'interprêter le nom de la classe retournée par le getter de la propriété en utilisant les règles 2, 3, 4 dans cet ordre. Dans certains cas vous aurez encore besoin de l'attribut `type`. (Par exemple, pour distinguer `Hibernate.DATE` et `Hibernate.TIMESTAMP`, ou pour préciser un type personnalisé).

L'attribut `access` permet de contrôler comment Hibernate accédera à la propriété à l'exécution. Par défaut, Hibernate utilisera les méthodes set/get. Si vous indiquez `access="field"`, Hibernate ignorera les getter/setter et accédera à la propriété directement en utilisant la réflexion. Vous pouvez spécifier votre propre stratégie d'accès aux propriétés en nommant une classe qui implémente l'interface `org.hibernate.propertexige une instrumentation de code d'octets build-timey.PropertyAccessor`.

Les propriétés dérivées représentent une fonctionnalité particulièrement intéressante. Ces propriétés sont par définition en lecture seule, la valeur de la propriété est calculée au chargement. Le calcul est déclaré comme une expression SQL, qui se traduit par une sous-requête `SELECT` dans la requête SQL qui charge une instance :

    <property name="totalPrice"

        formula="( SELECT SUM (li.quantity*p.price) FROM LineItem li, Product p

                    WHERE li.productId = p.productId

                    AND li.customerId = customerId

                    AND li.orderNumber = orderNumber )"/>

Remarquez que vous pouvez référencer la propre table des entités en ne déclarant pas un alias sur une colonne particulière (`customerId` dans l'exemple donné). Notez aussi que vous pouvez utiliser le sous-élément de mappage `<formula>` plutôt que d'utiliser l'attribut si vous le souhaitez.

### 5.1.5. Embedded objects (aka components)

Embeddable objects (or components) are objects whose properties are mapped to the same table as the owning entity's table. Components can, in turn, declare their own properties, components or collections

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

    public class Person implements Serializable {

        // 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

    public class Address implements Serializable {

        String city;

        Country nationality; //no overriding here

    }

    @Embeddable

    public class Country implements Serializable {

        private String iso2;

        @Column(name="countryName") private String name;

        public String getIso2() { return iso2; }

        public void setIso2(String iso2) { this.iso2 = iso2; }

        public String getName() { return name; }

        public void 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.

If a property of the embedded object points back to the owning entity, annotate it with the `@Parent` annotation. Hibernate will make sure this property is properly loaded with the entity reference.

In XML, use the `<component>` element.

    <component
            name="propertyName"
            class="className"
            insert="true|false"
            update="true|false"
            access="field|property|ClassName"
            lazy="true|false"
            optimistic-lock="true|false"
            unique="true|false"
            node="element-name|."
    >

            <property ...../>
            <many-to-one .... />
            ........
    </component>

| `name` : le nom de la propriété.
| `class` (optionnel - par défaut au type de la propriété déterminé par réflexion) : le nom de la classe (enfant) du composant.
| `insert` : les colonnes mappées apparaissent-elles dans les SQL `INSERT` s ?
| `update`: les colonnes mappées apparaissent-elles dans les SQL `UPDATE` s ?
| `access` (optionnel - par défaut `property`) : la stratégie que doit utiliser Hibernate pour accéder aux valeurs des propriétés.
| `lazy` (optionnel - par défaut à `false`) : indique que ce composant doit être chargé en différé au premier accès à la variable d'instance (nécessite une instrumentation du bytecode lors de la phase de construction).
| `optimistic-lock` (optionnel - par défaut à `true`) : spécifie si les mise à jour sur ce composant nécessitent ou non l'acquisition d'un verrou optimiste. En d'autres termes, cela détermine si une incrémentation de version doit avoir lieu quand la propriété est marquée obsolète (dirty).
| `unique` (optionnel - par défaut à `false`) : Indique qu'une contrainte d'unicité existe sur toutes les colonnes mappées de ce composant.

Les balises enfant `<property>` mappent les propriétés de la classe enfant sur les colonnes de la table.

L'élément `<component>` permet de déclarer un sous-élément `<parent>` qui associe une propriété de la classe composant comme une référence arrière vers l'entité contenante.

The `<dynamic-component>` element allows a `Map` to be mapped as a component, where the property names refer to keys of the map. See Section 9.5, « Les composants dynamiques » for more information. This feature is not supported in annotations.

### 5.1.6. Inheritance strategy

Java is a language supporting polymorphism: a class can inherit from another. Several strategies are possible to persist a class hierarchy:

- Single table per class hierarchy strategy: a single table hosts all the instances of a class hierarchy

- Joined subclass strategy: one table per class and subclass is present and each table persist the properties specific to a given subclass. The state of the entity is then stored in its corresponding class table and all its superclasses

- Table per class strategy: one table per concrete class and subclass is present and each table persist the properties of the class and its superclasses. The state of the entity is then stored entirely in the dedicated table for its class.

#### 5.1.6.1. Single table per class hierarchy strategy

With this approach the properties of all the subclasses in a given mapped class hierarchy are stored in a single table.

Each subclass declares its own persistent properties and subclasses. Version and id properties are assumed to be inherited from the root class. Each subclass in a hierarchy must define a unique discriminator value. If this is not specified, the fully qualified Java class name is used.

    @Entity

    @Inheritance(strategy=InheritanceType.SINGLE_TABLE)

    @DiscriminatorColumn(

        name="planetype",

        discriminatorType=DiscriminatorType.STRING

    )

    @DiscriminatorValue("Plane")

    public class Plane { ... }

    @Entity

    @DiscriminatorValue("A320")

    public class A320 extends Plane { ... }

In hbm.xml, for the table-per-class-hierarchy mapping strategy, the `<subclass>` declaration is used. For example:

    <subclass
            name="ClassName"
            discriminator-value="discriminator_value"
            proxy="ProxyInterface"
            lazy="true|false"
            dynamic-update="true|false"
            dynamic-insert="true|false"
            entity-name="EntityName"
            node="element-name"
            extends="SuperclassName">

            <property .... />
            .....
    </subclass>

| `name` : le nom de classe complet de la sous-classe.
| `discriminator-value` (optionnel - par défaut le nom de la classe) : une valeur qui distingue les différentes sous-classes.
| `proxy` (optionnel) : indique une classe ou interface à utiliser pour l'initialisation différée des proxies.
| `lazy` (optionnel, par défaut à `true`) : spécifier `lazy="false"` désactive l'utilisation de l'extraction différée.

For information about inheritance mappings see Chapitre 10, Mapping d'héritage de classe .

##### 5.1.6.1.1. Discriminator

Discriminators are required for polymorphic persistence using the table-per-class-hierarchy mapping strategy. It declares a discriminator column of the table. The discriminator column contains marker values that tell the persistence layer what subclass to instantiate for a particular row. Hibernate Core supports the follwoing restricted set of types as discriminator column: `string`, `character`, `integer`, `byte`, `short`, `boolean`, `yes_no`, `true_false`.

Use the `@DiscriminatorColumn` to define the discriminator column as well as the discriminator type.

## Note

`The enum DiscriminatorType` used in `javax.persitence.DiscriminatorColumn` only contains the values `STRING`, `CHAR` and `INTEGER` which means that not all Hibernate supported types are available via the `@DiscriminatorColumn` annotation.

You can also use `@DiscriminatorFormula` to express in SQL a virtual discriminator column. This is particularly useful when the discriminator value can be extracted from one or more columns of the table. Both `@DiscriminatorColumn` and `@DiscriminatorFormula` are to be set on the root entity (once per persisted hierarchy).

`@org.hibernate.annotations.DiscriminatorOptions` allows to optionally specify Hibernate specific discriminator options which are not standardized in JPA. The available options are `force` and `insert`. The `force` attribute is useful if the table contains rows with "extra" discriminator values that are not mapped to a persistent class. This could for example occur when working with a legacy database. If `force` is set to `true` Hibernate will specify the allowed discriminator values in the `SELECT` query, even when retrieving all instances of the root class. The second option - `insert` - tells Hibernate whether or not to include the discriminator column in SQL `INSERTs`. Usually the column should be part of the `INSERT` statement, but if your discriminator column is also part of a mapped composite identifier you have to set this option to `false`.

## Astuce

There is also a `@org.hibernate.annotations.ForceDiscriminator` annotation which is deprecated since version 3.6. Use `@DiscriminatorOptions` instead.

Finally, use `@DiscriminatorValue` on each class of the hierarchy to specify the value stored in the discriminator column for a given entity. If you do not set `@DiscriminatorValue` on a class, the fully qualified class name is used.

    @Entity

    @Inheritance(strategy=InheritanceType.SINGLE_TABLE)

    @DiscriminatorColumn(

        name="planetype",

        discriminatorType=DiscriminatorType.STRING

    )

    @DiscriminatorValue("Plane")

    public class Plane { ... }

    @Entity

    @DiscriminatorValue("A320")

    public class A320 extends Plane { ... }

In hbm.xml, the `<discriminator>` element is used to define the discriminator column or formula:

    <discriminator
            column="discriminator_column"
            type="discriminator_type"
            force="true|false"
            insert="true|false"
            formula="arbitrary sql expression"
    />

| `column` (optionnel - par défaut à `class`), le nom de la colonne discriminante.
| `type` (optionnel - par défaut à `string`) un nom indiquant le type Hibernate.
| `force` (optionnel - par défaut à `false`) "oblige" Hibernate à spécifier une valeur discriminante autorisée même quand on récupère toutes les instances de la classe de base.
| `insert` (optionnel - par défaut à `true`) à passer à `false` si la colonne discriminante fait aussi partie d'un identifiant composé mappé (Indique à Hibernate de ne pas inclure la colonne dans les SQL `INSERT` s).
| `formula` (optionnel) une expression SQL arbitraire qui est exécutée quand un type doit être évalué. Permet la discrimination basée sur le contenu.

Les véritables valeurs de la colonne discriminante sont spécifiées par l'attribut `discriminator-value` des éléments `<class>` et `<subclass>`.

En utilisant l'attribut `formula` vous pouvez déclarer une expression SQL arbitraire qui sera utilisée pour évaluer le type d'une ligne :

    <discriminator

        formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0 else 1 end"

        type="integer"/>

#### 5.1.6.2. Joined subclass strategy

Each subclass can also be mapped to its own table. This is called the table-per-subclass mapping strategy. An inherited state is retrieved by joining with the table of the superclass. A discriminator column is not required for this mapping strategy. Each subclass must, however, declare a table column holding the object identifier. The primary key of this table is also a foreign key to the superclass table and described by the `@PrimaryKeyJoinColumn`s or the `<key>` element.

    @Entity @Table(name="CATS")

    @Inheritance(strategy=InheritanceType.JOINED)

    public class Cat implements Serializable {

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

        @GenericGenerator(name="cat-uuid", strategy="uuid")

        String getId() { return id; }

        ...

    }

    @Entity @Table(name="DOMESTIC_CATS")

    @PrimaryKeyJoinColumn(name="CAT")

    public class DomesticCat extends Cat {

        public String getName() { return name; }

    }

## Note

The table name still defaults to the non qualified class name. Also if `@PrimaryKeyJoinColumn` is not set, the primary key / foreign key columns are assumed to have the same names as the primary key columns of the primary table of the superclass.

In hbm.xml, use the `<joined-subclass>` element. For example:

    <joined-subclass
            name="ClassName"
            table="tablename"
            proxy="ProxyInterface"
            lazy="true|false"
            dynamic-update="true|false"
            dynamic-insert="true|false"
            schema="schema"
            catalog="catalog"
            extends="SuperclassName"
            persister="ClassName"
            subselect="SQL expression"
            entity-name="EntityName"
            node="element-name">

            <key .... >

            <property .... />
            .....
    </joined-subclass>

| `name` : le nom de classe complet de la sous-classe.
| `table`: le nom de la table de la sous-classe.
| `proxy` (optionnel) : indique une classe ou interface à utiliser pour l'initialisation différée des proxies.
| `lazy` (optionnel, par défaut à `true`) : spécifier `lazy="false"` désactive l'utilisation de l'extraction différée.

Use the `<key>` element to declare the primary key / foreign key column. The mapping at the start of the chapter would then be re-written as:

    <?xml version="1.0"?>

    <!DOCTYPE hibernate-mapping PUBLIC

            "-//Hibernate/Hibernate Mapping DTD//EN"

            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

    <hibernate-mapping package="eg">

            <class name="Cat" table="CATS">

                    <id name="id" column="uid" type="long">

                            <generator class="hilo"/>

                    </id>

                    <property name="birthdate" type="date"/>

                    <property name="color" not-null="true"/>

                    <property name="sex" not-null="true"/>

                    <property name="weight"/>

                    <many-to-one name="mate"/>

                    <set name="kittens">

                            <key column="MOTHER"/>

                            <one-to-many class="Cat"/>

                    </set>

                    <joined-subclass name="DomesticCat" table="DOMESTIC_CATS">

                        <key column="CAT"/>

                        <property name="name" type="string"/>

                    </joined-subclass>

            </class>

            <class name="eg.Dog">

                    <!-- mapping for Dog could go here -->

            </class>

    </hibernate-mapping>

For information about inheritance mappings see Chapitre 10, Mapping d'héritage de classe .

#### 5.1.6.3. Table per class strategy

A third option is to map only the concrete classes of an inheritance hierarchy to tables. This is called the table-per-concrete-class strategy. Each table defines all persistent states of the class, including the inherited state. In Hibernate, it is not necessary to explicitly map such inheritance hierarchies. You can map each class as a separate entity root. However, if you wish use polymorphic associations (e.g. an association to the superclass of your hierarchy), you need to use the union subclass mapping.

    @Entity

    @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)

    public class Flight implements Serializable { ... }

Or in hbm.xml:

    <union-subclass
            name="ClassName"
            table="tablename"
            proxy="ProxyInterface"
            lazy="true|false"
            dynamic-update="true|false"
            dynamic-insert="true|false"
            schema="schema"
            catalog="catalog"
            extends="SuperclassName"
            abstract="true|false"
            persister="ClassName"
            subselect="SQL expression"
            entity-name="EntityName"
            node="element-name">

            <property .... />
            .....
    </union-subclass>

| `name` : le nom de classe complet de la sous-classe.
| `table`: le nom de la table de la sous-classe.
| `proxy` (optionnel) : indique une classe ou interface à utiliser pour l'initialisation différée des proxies.
| `lazy` (optionnel, par défaut à `true`) : spécifier `lazy="false"` désactive l'utilisation de l'extraction différée.

Aucune colonne discriminante ou colonne clé n'est requise pour cette stratégie de mappage.

For information about inheritance mappings see Chapitre 10, Mapping d'héritage de classe .

#### 5.1.6.4. Inherit properties from superclasses

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

    public class BaseEntity {

        @Basic

        @Temporal(TemporalType.TIMESTAMP)

        public Date getLastUpdate() { ... }

        public String getLastUpdater() { ... }

        ...

    }

    @Entity class Order extends BaseEntity {

        @Id public Integer 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.

## Note

Properties from superclasses not mapped as `@MappedSuperclass` are ignored.

## Note

The default access type (field or methods) is used, unless you use the `@Access` annotation.

## Note

The same notion can be applied to `@Embeddable` objects to persist properties from their superclasses. You also need to use `@MappedSuperclass` to do that (this should not be considered as a standard EJB3 feature though)

## Note

It is allowed to mark a class as `@MappedSuperclass` in the middle of the mapped inheritance hierarchy.

## Note

Any class in the hierarchy non annotated with `@MappedSuperclass` nor `@Entity` will be ignored.

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

    @MappedSuperclass

    public class FlyingObject implements Serializable {

        public int getAltitude() {

            return altitude;

        }

        @Transient

        public int getMetricAltitude() {

            return metricAltitude;

        }

        @ManyToOne

        public PropulsionType getPropulsion() {

            return metricAltitude;

        }

        ...

    }

    @Entity

    @AttributeOverride( name="altitude", column = @Column(name="fld_altitude") )

    @AssociationOverride(

       name="propulsion",

       joinColumns = @JoinColumn(name="fld_propulsion_fk")

    )

    public class Plane extends FlyingObject {

        ...

    }

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.

In hbm.xml, simply map the properties of the superclass in the `<class>` element of the entity that needs to inherit them.

#### 5.1.6.5. Mapping one entity to several tables

While not recommended for a fresh schema, some legacy databases force your to map a single entity on 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"})})

    })

    public class Cat implements Serializable {

        private Integer id;

        private String name;

        private String storyPart1;

        private String storyPart2;

        @Id @GeneratedValue

        public Integer getId() {

            return id;

        }

        public String getName() {

            return name;

        }

        @Column(table="Cat1")

        public String getStoryPart1() {

            return storyPart1;

        }

        @Column(table="Cat2")

        public String 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.

There is also additional tuning accessible via the `@org.hibernate.annotations.Table` annotation:

- `fetch`: If set to JOIN, the default, Hibernate will use an inner join to retrieve a secondary table defined by a class or its superclasses and an outer join for a secondary table defined by a subclass. If set to `SELECT` then Hibernate will use a sequential select for a secondary table defined on a subclass, which will be issued only if a row turns out to represent an instance of the subclass. Inner joins will still be used to retrieve a secondary defined by the class and its superclasses.

- `inverse`: If true, Hibernate will not try to insert or update the properties defined by this join. Default to false.

- `optional`: If enabled (the default), Hibernate will insert a row only if the properties defined by this join are non-null and will always use an outer join to retrieve the properties.

- `foreignKey`: defines the Foreign Key name of a secondary table pointing back to the primary table.

Make sure to use the secondary table name in the `appliesto` property

    @Entity

    @Table(name="MainCat")

    @SecondaryTable(name="Cat1")

    @org.hibernate.annotations.Table(

       appliesTo="Cat1",

       fetch=FetchMode.SELECT,

       optional=true)

    public class Cat implements Serializable {

        private Integer id;

        private String name;

        private String storyPart1;

        private String storyPart2;

        @Id @GeneratedValue

        public Integer getId() {

            return id;

        }

        public String getName() {

            return name;

        }

        @Column(table="Cat1")

        public String getStoryPart1() {

            return storyPart1;

        }

        @Column(table="Cat2")

        public String getStoryPart2() {

            return storyPart2;

        }

    }

In hbm.xml, use the `<join>` element.

    <join
            table="tablename"
            schema="owner"
            catalog="catalog"
            fetch="join|select"
            inverse="true|false"
            optional="true|false">

            <key ... />

            <property ... />
            ...
    </join>

| `table` : le nom de la table jointe.
| `schema` (optionnel) : surcharge le nom de schéma spécifié par l'élément racine `<hibernate-mappage>`.
| `catalog` (optionnel) : surcharge le nom du catalogue spécifié par l'élément racine `<hibernate-mappage>`.
| `fetch` (optionnel - par défaut à `join`) : si positionné à `join`, Hibernate utilisera une jointure interne pour charger une `jointure` définie par une classe ou ses super-classes et une jointure externe pour une `<jointure>` définie par une sous-classe. Si positionné à `select`, Hibernate utilisera un select séquentiel pour une `<jointure>` définie sur une sous-classe, qui ne sera délivrée que si une ligne représente une instance de la sous-classe. Les jointures internes seront quand même utilisées pour charger une `<jointure>` définie par une classe et ses super-classes.
| `inverse` (optionnel - par défaut à `false`) : si positionné à true, Hibernate n'essaiera pas d'insérer ou de mettre à jour les propriétés définies par cette jointure.
| `optionnel` (optionnel - par défaut à `false`) : si positionné à true, Hibernate insèrera une ligne seulement si les propriétés définies par cette jointure sont non-nulles et utilisera toujours une jointure externe pour extraire les propriétés.

Par exemple, les informations d'adresse pour une personne peuvent être mappées vers une table séparée (tout en préservant des sémantiques de type valeur pour toutes ses propriétés) :

    <class name="Person"

        table="PERSON">

        <id name="id" column="PERSON_ID">...</id>

        <join table="ADDRESS">

            <key column="ADDRESS_ID"/>

            <property name="address"/>

            <property name="zip"/>

            <property name="country"/>

        </join>

        ...

Cette fonctionnalité est souvent seulement utile pour les modèles de données hérités d'anciens systèmes, nous recommandons d'utiliser moins de tables que de classes et un modèle de domaine à granularité fine. Cependant, c'est utile pour passer d'une stratégie de mappage d'héritage à une autre dans une hiérarchie simple, comme nous le verrons plus tard.

### 5.1.7. Mapping one to one and one to many associations

To link one entity to an other, you need to map the association property as a to one association. In the relational model, you can either use a foreign key or an association table, or (a bit less common) share the same primary key value between the two entities.

To mark an association, use either `@ManyToOne` or `@OnetoOne`.

`@ManyToOne` and `@OneToOne` have 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.

Setting a value of the `cascade` attribute to any meaningful value other than nothing will propagate certain operations to the associated object. The meaningful values are divided into three categories.

1. basic operations, which include: `persist, merge, delete, save-update, evict, replicate, lock and refresh`;

2. special values: `delete-orphan` or `all` ;

3. comma-separated combinations of operation names: `cascade="persist,merge,evict"` or `cascade="all,delete-orphan"`. See Section 11.11, « Persistance transitive » for a full explanation. Note that single valued many-to-one associations do not support orphan delete.

By default, single point associations are eagerly fetched in JPA 2. You can mark it as lazily fetched by using `@ManyToOne(fetch=FetchType.LAZY)` in which case Hibernate will proxy the association and load it when the state of the associated entity is reached. You can force Hibernate not to use a proxy by using `@LazyToOne(NO_PROXY)`. In this case, the property is fetched lazily when the instance variable is first accessed. This requires build-time bytecode instrumentation. lazy="false" specifies that the association will always be eagerly fetched.

With the default JPA options, single-ended associations are loaded with a subsequent select if set to `LAZY`, or a SQL JOIN is used for `EAGER` associations. You can however adjust the fetching strategy, ie how data is fetched by using `@Fetch`. `FetchMode` can be `SELECT` (a select is triggered when the association needs to be loaded) or `JOIN` (use a SQL JOIN to load the association while loading the owner entity). `JOIN` overrides any lazy attribute (an association loaded through a `JOIN` strategy cannot be lazy).

#### 5.1.7.1. Using a foreign key or an association table

An ordinary association to another persistent class is declared using a

- `@ManyToOne` if several entities can point to the the target entity

- `@OneToOne` if only a single entity can point to the the target entity

and a foreign key in one table is referencing the primary key column(s) of the target table.

    @Entity

    public class Flight implements Serializable {

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

        @JoinColumn(name="COMP_ID")

        public Company getCompany() {

            return company;

        }

        ...

    }

The `@JoinColumn` attribute is optional, the default value(s) is 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`.

    @Entity

    public class Flight implements Serializable {

        @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE}, targetEntity=CompanyImpl.class )

        @JoinColumn(name="COMP_ID")

        public Company getCompany() {

            return company;

        }

        ...

    }

    public interface Company {

        ...

    }

You can also map a 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

    public class Flight implements Serializable {

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

        @JoinTable(name="Flight_Company",

            joinColumns = @JoinColumn(name="FLIGHT_ID"),

            inverseJoinColumns = @JoinColumn(name="COMP_ID")

        )

        public Company getCompany() {

            return company;

        }

        ...

    }

## Note

You can use a SQL fragment to simulate a physical join column using the `@JoinColumnOrFormula` / `@JoinColumnOrformulas` annotations (just like you can use a SQL fragment to simulate a property column via the `@Formula` annotation).

    @Entity

    public class Ticket implements Serializable {

        @ManyToOne

        @JoinColumnOrFormula(formula="(firstname + ' ' + lastname)")

        public Person getOwner() {

            return person;

        }

        ...

    }

You can mark an association as mandatory by using the `optional=false` attribute. We recommend to use Bean Validation's `@NotNull` annotation as a better alternative however. As a consequence, the foreign key column(s) will be marked as not nullable (if possible).

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

Exemple 5.1. @NotFound annotation

    @Entity

    public class Child {

        ...

        @ManyToOne

        @NotFound(action=NotFoundAction.IGNORE)

        public Parent getParent() { ... }

        ...

    }

Sometimes you want to delegate to your database the deletion of cascade when a given entity is deleted. In this case Hibernate generates a cascade delete constraint at the database level.

Exemple 5.2. @OnDelete annotation

    @Entity

    public class Child {

        ...

        @ManyToOne

        @OnDelete(action=OnDeleteAction.CASCADE)

        public Parent getParent() { ... }

        ...

    }

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

Exemple 5.3. @ForeignKey annotation

    @Entity

    public class Child {

        ...

        @ManyToOne

        @ForeignKey(name="FK_PARENT")

        public Parent getParent() { ... }

        ...

    }

    alter table Child add constraint FK_PARENT foreign key (parent_id) references Parent

Sometimes, you want to link one entity to an other not by the target entity primary key but by a different unique key. You can achieve that by referencing the unique key column(s) in `@JoinColumn.referenceColumnName`.

    @Entity

    class Person {

       @Id Integer personNumber;

       String firstName;

       @Column(name="I")

       String initial;

       String lastName;

    }

    @Entity

    class Home {

       @ManyToOne

       @JoinColumns({

          @JoinColumn(name="first_name", referencedColumnName="firstName"),

          @JoinColumn(name="init", referencedColumnName="I"),

          @JoinColumn(name="last_name", referencedColumnName="lastName"),

       })

       Person owner

    }

This is not encouraged however and should be reserved to legacy mappings.

In hbm.xml, mapping an association is similar. The main difference is that a `@OneToOne` is mapped as `<many-to-one unique="true"/>`, let's dive into the subject.

    <many-to-one
            name="propertyName"
            column="column_name"
            class="ClassName"
            cascade="cascade_style"
            fetch="join|select"
            update="true|false"
            insert="true|false"
            property-ref="propertyNameFromAssociatedClass"
            access="field|property|ClassName"
            unique="true|false"
            not-null="true|false"
            optimistic-lock="true|false"
            lazy="proxy|no-proxy|false"
            not-found="ignore|exception"
            entity-name="EntityName"
            formula="arbitrary SQL expression"
            node="element-name|@attribute-name|element/@attribute|."
            embed-xml="true|false"
            index="index_name"
            unique_key="unique_key_id"
            foreign-key="foreign_key_name"
    />

| `name` : le nom de la propriété.
| `column` (optionnel) : le nom de la colonne de la clé étrangère. Cela peut être aussi spécifié par un ou des sous-élément(s) `<column>`.
| `class` (optionnel - par défaut, le type de la propriété déterminé par réflexion) : le nom de la classe associée.
| `cascade` (optionnel) : indique quelles opérations doivent être cascadées de l'objet parent vers l'objet associé.
| `fetch` (optionnel - par défaut à `select`) : choisit entre le chargement de type jointure externe (outer-join) ou le chargement par select successifs.
| `update, insert` (optionnel - par défaut à `true`) : indique que les colonnes mappées devraient être incluses dans des SQL `UPDATE` et/ou des déclarations `INSERT`. Mettre les deux à `false`, permet une association pure dérivée dont la valeur est initialisée à partir d'une autre propriété qui mappe à une ou plusieurs mêmes colonnes, ou par un trigger ou une autre application.
| `property-ref` (optionnel) : le nom d'une propriété de la classe associée qui est jointe à cette clé étrangère. Si non-spécifiée, la clé primaire de la classe associée est utilisée.
| `access` (optionnel - par défaut `property`) : la stratégie que doit utiliser Hibernate pour accéder aux valeurs des propriétés.
| `unique` (optionnel) : génère le DDL d'une contrainte unique pour la clé étrangère. Permet aussi d'en faire la cible d'une `property-ref`. Cela permet de créer une véritable association un-à-un.
| `not-null` (optionnel) : active le DDL d'une contrainte de nullité pour les colonnes de clés étrangères.
| `optimistic-lock` (optionnel - par défaut à `true`) : indique si les mise à jour de cette propriété nécessitent ou non l'acquisition d'un verrou optimiste. En d'autres termes, cela détermine s'il est nécessaire d'incrémenter un numéro de version quand cette propriété est marquée obsolète (dirty).
| `lazy` (optionnel - par défaut à `proxy`) : par défaut, les associations de point uniques utilisent des proxies. `lazy="no-proxy"` indique que cette propriété doit être chargée en différé au premier accès à la variable d'instance (nécessite une instrumentation du bytecode lors de la phase de construction). `lazy="false"` indique que l'association sera toujours chargée.
| `not-found` (optionnel - par défaut = `exception`) : spécifie comment les clés étrangères qui référencent des lignes manquantes seront gérées : `ignore` traitera une ligne manquante comme une association nulle.
| `entity-name` (optionnel) : le nom de l'entité de la classe associée.
| `formula` (optionnel) : une expression SQL qui définit la valeur pour une clé étrangère calculée.

Setting a value of the `cascade` attribute to any meaningful value other than `none` will propagate certain operations to the associated object. The meaningful values are divided into three categories. First, basic operations, which include: `persist, merge, delete, save-update, evict, replicate, lock and refresh`; second, special values: `delete-orphan`; and third,`all` comma-separated combinations of operation names: `cascade="persist,merge,evict"` or `cascade="all,delete-orphan"`. See Section 11.11, « Persistance transitive » for a full explanation. Note that single valued, many-to-one and one-to-one, associations do not support orphan delete.

Une déclaration `many-to-one` typique est aussi simple que :

    <many-to-one name="product" class="Product" column="PRODUCT_ID"/>

L'attribut `property-ref` devrait être utilisé pour mapper seulement des données provenant d'un ancien système où les clés étrangères font référence à une clé unique de la table associée et qui n'est pas la clé primaire. C'est un cas de mauvaise conception relationnelle. Par exemple, supposez que la classe `Product` ait un numéro de série unique qui n'est pas la clé primaire. L'attribut `unique` contrôle la génération DDL par Hibernate avec l'outil SchemaExport.

    <property name="serialNumber" unique="true" type="string" column="SERIAL_NUMBER"/>

Ainsi le mappage pour `OrderItem` peut utiliser :

    <many-to-one name="product" property-ref="serialNumber" column="PRODUCT_SERIAL_NUMBER"/>

Bien que ce ne soit certainement pas encouragé.

Si la clé unique référencée comprend des propriétés multiples de l'entité associée, vous devez mapper ces propriétés à l'intérieur d'un élément nommé `<properties>`.

Si la clé unique référencée est la propriété d'un composant, vous pouvez spécifier le chemin de propriété :

    <many-to-one name="owner" property-ref="identity.ssn" column="OWNER_SSN"/>

#### 5.1.7.2. Sharing the primary key with the associated entity

The second approach is to ensure an entity and its associated entity share the same primary key. In this case the primary key column is also a foreign key and there is no extra column. These associations are always one to one.

Exemple 5.4. One to One association

    @Entity

    public class Body {

        @Id

        public Long getId() { return id; }

        @OneToOne(cascade = CascadeType.ALL)

        @MapsId

        public Heart getHeart() {

            return heart;

        }

        ...

    }

    @Entity

    public class Heart {

        @Id

        public Long getId() { ...}

    }

## Note

Many people got confused by these primary key based one to one associations. They can only be lazily loaded if Hibernate knows that the other side of the association is always present. To indicate to Hibernate that it is the case, use `@OneToOne(optional=false)`.

In hbm.xml, use the following mapping.

    <one-to-one
            name="propertyName"
            class="ClassName"
            cascade="cascade_style"
            constrained="true|false"
            fetch="join|select"
            property-ref="propertyNameFromAssociatedClass"
            access="field|property|ClassName"
            formula="any SQL expression"
            lazy="proxy|no-proxy|false"
            entity-name="EntityName"
            node="element-name|@attribute-name|element/@attribute|."
            embed-xml="true|false"
            foreign-key="foreign_key_name"
    />

| `name` : le nom de la propriété.
| `class` (optionnel - par défaut, le type de la propriété déterminé par réflexion) : le nom de la classe associée.
| `cascade` (optionnel) : indique quelles opérations doivent être cascadées de l'objet parent vers l'objet associé.
| `constrained` (optionnel) : indique qu'une contrainte de clé étrangère sur la clé primaire de la table mappée référence la table de la classe associée. Cette option affecte l'ordre dans lequel chaque `save()` et chaque `delete()` est cascadé et détermine si l'association peut utiliser un proxy (aussi utilisé par l'outil SchemaExport).
| `fetch` (optionnel - par défaut à `select`) : choisit entre le chargement de type jointure externe (outer-join) ou le chargement par select successifs.
| `property-ref` (optionnel) : le nom de la propriété de la classe associée qui est jointe à la clé primaire de cette classe. Si ce n'est pas spécifié, la clé primaire de la classe associée est utilisée.
| `access` (optionnel - par défaut `property`) : la stratégie que doit utiliser Hibernate pour accéder aux valeurs des propriétés.
| `formula` (optionnel) : presque toutes les associations un-à-un pointent sur la clé primaire de l'entité propriétaire. Dans les rares cas différents, vous devez donner une ou plusieurs autres colonnes ou expression à joindre par une formule SQL . Voir `org.hibernate.test.onetooneformula` pour un exemple.
| `lazy` (optionnel - par défaut `proxy`) : par défaut, les associations simples sont soumises à proxy. `lazy="no-proxy"` spécifie que la propriété doit être chargée en différé au premier accès à l'instance. (nécessite l'instrumentation du bytecode à la construction). `lazy="false"` indique que l'association sera toujours chargée agressivement. . Notez que si `constrained="false"`, l'utilisation de proxy est impossible et Hibernate chargera automatiquement l'association .
| `entity-name` (optionnel) : le nom de l'entité de la classe associée.

Les associations par clé primaire ne nécessitent pas une colonne supplémentaire en table ; si deux lignes sont liées par l'association alors les deux lignes de la table partagent la même valeur de clé primaire. Donc si vous voulez que deux objets soient liés par une association par clé primaire, vous devez faire en sorte qu'on leur assigne la même valeur d'identifiant.

Pour une association par clé primaire, ajoutez les mappages suivants à `Employee` et `Person`, respectivement :

    <one-to-one name="person" class="Person"/>

    <one-to-one name="employee" class="Employee" constrained="true"/>

Maintenant, vous devez faire en sorte que les clés primaires des lignes liées dans les tables PERSON et EMPLOYEE sont égales. On utilise une stratégie Hibernate spéciale de génération d'identifiants appelée `foreign` :

    <class name="person" table="PERSON">

        <id name="id" column="PERSON_ID">

            <generator class="foreign">

                <param name="property">employee</param>

            </generator>

        </id>

        ...

        <one-to-one name="employee"

            class="Employee"

            constrained="true"/>

    </class>

Une instance fraîchement enregistrée de `Person` se voit alors assignée la même valeur de clé primaire que l'instance de `Employee` référencée par la propriété `employee` de cette `Person`.

### 5.1.8. Natural-id

Although we recommend the use of surrogate keys as primary keys, you should try to identify natural keys for all entities. A natural key is a property or combination of properties that is unique and non-null. It is also immutable. Map the properties of the natural key as `@NaturalId` or map them inside the `<natural-id>` element. Hibernate will generate the necessary unique key and nullability constraints and, as a result, your mapping will be more self-documenting.

    @Entity

    public class Citizen {

        @Id

        @GeneratedValue

        private Integer id;

        private String firstname;

        private String lastname;

        @NaturalId

        @ManyToOne

        private State state;

        @NaturalId

        private String ssn;

        ...

    }

    //and later on query

    List results = s.createCriteria( Citizen.class )

                    .add( Restrictions.naturalId().set( "ssn", "1234" ).set( "state", ste ) )

                    .list();

Or in XML,

    <natural-id mutable="true|false"/>

            <property ... />

            <many-to-one ... />

            ......

    </natural-id>

Nous vous recommandons fortement d'implémenter `equals()` et `hashCode()` pour comparer les propriétés clés naturelles de l'entité.

Ce mappage n'est pas destiné à être utilisé avec des entités qui ont des clés naturelles.

- `mutable` (optionnel, par défaut à `false`) : par défaut, les identifiants naturels sont supposés être immuables (constants).

### 5.1.9. Any

There is one more type of property mapping. The `@Any` mapping defines a polymorphic association to classes from multiple tables. This type of mapping requires more than one column. The first column contains the type of the associated entity. The remaining columns contain the identifier. It is impossible to specify a foreign key constraint for this kind of association. This is not the usual way of mapping polymorphic associations and you should use this only in special cases. For example, for 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. The `metaType` attribute allows the application to specify a custom type that maps database column values to persistent classes that have identifier properties of the type specified by `idType`. You must specify the mapping from values of the `metaType` to class names.

    @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" )

    public Property getMainProperty() {

        return mainProperty;

    }

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" )

        public Property getMainProperty() {

            return mainProperty;

        }

The hbm.xml equivalent is:

    <any name="being" id-type="long" meta-type="string">

        <meta-value value="TBL_ANIMAL" class="Animal"/>

        <meta-value value="TBL_HUMAN" class="Human"/>

        <meta-value value="TBL_ALIEN" class="Alien"/>

        <column name="table_name"/>

        <column name="id"/>

    </any>

## Note

You cannot mutualize the metadata in hbm.xml as you can in annotations.

    <any
            name="propertyName"
            id-type="idtypename"
            meta-type="metatypename"
            cascade="cascade_style"
            access="field|property|ClassName"
            optimistic-lock="true|false"
    >
            <meta-value ... />
            <meta-value ... />
            .....
            <column .... />
            <column .... />
            .....
    </any>

| `name` : le nom de la propriété.
| `id-type` : le type identifiant.
| `meta-type` (optionnel - par défaut à `string`) : tout type permis pour un mappage par discriminateur.
| `cascade` (optionnel - par défaut à `none`) : le style de cascade.
| `access` (optionnel - par défaut `property`) : la stratégie que doit utiliser Hibernate pour accéder aux valeurs des propriétés.
| `optimistic-lock` (optionnel - par défaut à `true`) : indique si les mise à jour sur cette propriété nécessitent ou non l'acquisition d'un verrou optimiste. En d'autres termes, définit si un incrément de version doit avoir lieu quand cette propriété est marquée dirty.

### 5.1.10. Propriétés

L'élément `<properties>` permet la définition d'un groupement logique nommé des propriétés d'une classe. L'utilisation la plus importante de cette construction est la possibilité pour une combinaison de propriétés d'être la cible d'un `property-ref`. C'est aussi un moyen pratique de définir une contrainte d'unicité multi-colonnes. Par exemple :

    <properties
            name="logicalName"
            insert="true|false"
            update="true|false"
            optimistic-lock="true|false"
            unique="true|false"
    >

            <property ...../>
            <many-to-one .... />
            ........
    </properties>

| `name` : le nom logique d'un regroupement et non le véritable nom d'une propriété.
| `insert` : les colonnes mappées apparaissent-elles dans les SQL `INSERT` s ?
| `update`: les colonnes mappées apparaissent-elles dans les SQL `UPDATE` s ?
| `optimistic-lock` (optionnel - par défaut à `true`) : indique si les mise à jour sur ce composant nécessitent ou non l'acquisition d'un verrou optimiste. En d'autres termes, cela détermine si une incrémentation de version doit avoir lieu quand la propriété est marquée obsolète (dirty).
| `unique` (optionnel - par défaut à `false`) : Indique qu'une contrainte d'unicité existe sur toutes les colonnes mappées de ce composant.

Par exemple, si nous avons le mappage de `<properties>` suivant :

    <class name="Person">

        <id name="personNumber"/>

        ...

        <properties name="name"

                unique="true" update="false">

            <property name="firstName"/>

            <property name="initial"/>

            <property name="lastName"/>

        </properties>

    </class>

Alors nous pourrions avoir une association sur des données d'un ancien système qui font référence à cette clé unique de la table `Person` au lieu de la clé primaire :

    <many-to-one name="owner"

             class="Person" property-ref="name">

        <column name="firstName"/>

        <column name="initial"/>

        <column name="lastName"/>

    </many-to-one>

## Note

When using annotations as a mapping strategy, such construct is not necessary as the binding between a column and its related column on the associated table is done directly

    @Entity

    class Person {

       @Id Integer personNumber;

       String firstName;

       @Column(name="I")

       String initial;

       String lastName;

    }

    @Entity

    class Home {

       @ManyToOne

       @JoinColumns({

          @JoinColumn(name="first_name", referencedColumnName="firstName"),

          @JoinColumn(name="init", referencedColumnName="I"),

          @JoinColumn(name="last_name", referencedColumnName="lastName"),

       })

       Person owner

    }

Nous ne recommandons pas une telle utilisation, en dehors du contexte de mappage de données héritées d'anciens systèmes.

### 5.1.11. Some hbm.xml specificities

The hbm.xml structure has some specificities naturally not present when using annotations, let's describe them briefly.

#### 5.1.11.1. Doctype

Tous les mappages XML devraient utiliser le doctype indiqué. En effet vous trouverez le fichier DTD à l'URL ci-dessus, dans le répertoire `hibernate-x.x.x/src/org/hibernate` ou dans `hibernate3.jar`. Hibernate va toujours chercher la DTD dans son classpath en premier lieu. Si vous constatez des recherches de la DTD sur Internet, vérifiez votre déclaration de DTD par rapport au contenu de votre classpath.

##### 5.1.11.1.1. EntityResolver

Comme mentionné précédemment, Hibernate tentera en premier lieu de résoudre les DTD dans leur classpath. Il réussit à le faire en enregistrant une implémentation personnalisée de `org.xml.sax.EntityResolver` avec le SAXReader qu'il utilise pour lire les fichiers xml. Cet `EntityResolver` personnalisé reconnaît deux espaces de nommage systemId différents :

- a `hibernate namespace` is recognized whenever the resolver encounters a systemId starting with `http://www.hibernate.org/dtd/`. The resolver attempts to resolve these entities via the classloader which loaded the Hibernate classes.

- un `espace de nommage utilisateur` est reconnu dès que le résolveur rencontre un systemId qui utilise un protocole URL `classpath://`. Le résolveur tentera alors de résoudre ces entités via (1) le chargeur de classe du contexte du thread courant et (2) le chargeur de classe qui a chargé les classes Hibernate.

Un exemple d'utilisation de l'espace de nommage utilisateur:

    <?xml version="1.0"?>

    <!DOCTYPE hibernate-mapping PUBLIC

            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

            "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" [

        <!ENTITY types SYSTEM "classpath://your/domain/types.xml">

    ]>

    <hibernate-mapping package="your.domain">

        <class name="MyEntity">

            <id name="id" type="my-custom-id-type">

                ...

            </id>

        <class>

        &types;

    </hibernate-mapping>

Where `types.xml` is a resource in the `your.domain` package and contains a custom typedef.

#### 5.1.11.2. Hibernate-mappage

Cet élément a plusieurs attributs optionnels. Les attributs `schema` et `catalog` indiquent que les tables mentionnées dans ce mappage appartiennent au schéma nommé et/ou au catalogue. S'ils sont spécifiés, les noms de tables seront qualifiés par les noms de schéma et de catalogue. L'attribut `default-cascade` indique quel type de cascade sera utilisé par défaut pour les propriétés et collections qui ne précisent pas l'attribut `cascade`. L'attribut `auto-import` nous permet d'utiliser par défaut des noms de classes non qualifiés dans le langage de requête, par défaut.

    <hibernate-mapping
             schema="schemaName"
             catalog="catalogName"
             default-cascade="cascade_style"
             default-access="field|property|ClassName"
             default-lazy="true|false"
             auto-import="true|false"
             package="package.name"
     />

| `schema` (optionnel) : le nom d'un schéma de base de données.
| `catalog` (optionnel) : le nom d'un catalogue de base de données.
| `default-cascade` (optionnel - par défaut vaut : `none`) : un type de cascade par défaut.
| `default-access` (optionnel - par défaut vaut : `property`) : Comment hibernate accèdera aux propriétés. On peut aussi redéfinir sa propre implémentation de `PropertyAccessor`.
| `default-lazy` (optionnel - par défaut vaut : `true`) : Valeur par défaut pour des attributs `lazy` non spécifiés des mappages de classe et de collection.
| `auto-import` (optionnel - par défaut vaut : `true`) : spécifie si l'on peut utiliser des noms de classes non qualifiés (de classes de ce mappage) dans le langage de requête.
| `package` (optionnel) : préfixe de paquetage par défaut pour les noms de classe non qualifiés du document de mappage.

Si deux classes persistantes possèdent le même nom de classe (non qualifié), vous devez configurer `auto-import="false"`. Hibernate lancera une exception si vous essayez d'assigner le même nom "importé" à deux classes.

Notez que l'élément `hibernate-mappage` vous permet d'imbriquer plusieurs mappages de `<class>` persistantes, comme dans l'exemple ci-dessus. Cependant il est recommandé (et c'est parfois une exigence de certains outils) de mapper une seule classe persistante (ou une seule hiérarchie de classes) par fichier de mappage et de nommer ce fichier d'après le nom de la superclasse persistante, par exemple `Cat.hbm.xml`, `Dog.hbm.xml`, ou en cas d'héritage, `Animal.hbm.xml`.

#### 5.1.11.3. Key

The `<key>` element is featured a few times within this guide. It appears anywhere the parent mapping element defines a join to a new table that references the primary key of the original table. It also defines the foreign key in the joined table:

    <key
            column="columnname"
            on-delete="noaction|cascade"
            property-ref="propertyName"
            not-null="true|false"
            update="true|false"
            unique="true|false"
    />

| `column` (optionnel) : le nom de la colonne de la clé étrangère. Cela peut être aussi spécifié par un ou des sous-élément(s) `<column>`.
| `on-delete` (optionnel, par défaut à `noaction`) : indique si la contrainte de clé étrangère possède la possibilité au niveau base de données de suppression en cascade.
| `property-ref` (optionnel) : indique que la clé étrangère fait référence à des colonnes qui ne sont pas la clé primaire de la table d'origine (Pour les données d'anciens systèmes).
| `not-null` (optionnel) : indique que les colonnes des clés étrangères ne peuvent pas être nulles (c'est implicite si la clé étrangère fait partie de la clé primaire).
| `update` (optionnel) : indique que la clé étrangère ne devrait jamais être mise à jour (implicite si celle-ci fait partie de la clé primaire).
| `unique` (optionnel) : indique que la clé étrangère doit posséder une contrainte d'unicité (implicite si la clé étrangère est aussi la clé primaire).

Là où les suppressions doivent être performantes, nous recommandons pour les systèmes de définir toutes les clés `on-delete="cascade"`, ainsi Hibernate utilisera une contrainte `ON CASCADE DELETE` au niveau base de données, plutôt que de nombreux `DELETE` individuels. Attention, cette fonctionnalité court-circuite la stratégie habituelle de verrou optimiste pour les données versionnées.

Les attributs `not-null` et `update` sont utiles pour mapper une association un-à-plusieurs unidirectionnelle. Si vous mappez un un-à-plusieurs unidirectionnel vers une clé étrangère non nulle, vous devez déclarer la colonne de la clé en utilisant `<key not-null="true">`.

#### 5.1.11.4. Import

Supposez que votre application possède deux classes persistantes du même nom, et vous ne voulez pas préciser le nom Java complet (paquetage) dans les requêtes Hibernate. Les classes peuvent alors être "importées" explicitement plutôt que de compter sur `auto-import="true"`.Vous pouvez même importer des classes et interfaces qui ne sont pas mappées explicitement :

    <import class="java.lang.Object" rename="Universe"/>

    <import
            class="ClassName"
            rename="ShortName"
    />

| `class` : nom complet de toute classe Java.
| `rename` (optionnel - par défaut vaut le nom de la classe non qualifié): nom pouvant être utilisé dans le langage de requête.

## Note

This feature is unique to hbm.xml and is not supported in annotations.

#### 5.1.11.5. Éléments column et formula

Tout élément de mappage qui accepte un attribut `column` acceptera alternativement un sous-élément `<column>`. Pareillement `<formula>` est une alternative à l'attribut `formula`. Par exemple :

    <column

            name="column_name"

            length="N"

            precision="N"

            scale="N"

            not-null="true|false"

            unique="true|false"

            unique-key="multicolumn_unique_key_name"

            index="index_name"

            sql-type="sql_type_name"

            check="SQL expression"

            default="SQL expression"

            read="SQL expression"

            write="SQL expression"/>

    <formula>SQL expression</formula>

Most of the attributes on `column` provide a means of tailoring the DDL during automatic schema generation. The `read` and `write` attributes allow you to specify custom SQL that Hibernate will use to access the column's value. For more on this, see the discussion of column read and write expressions.

The `column` and `formula` elements can even be combined within the same property or association mapping to express, for example, exotic join conditions.

    <many-to-one name="homeAddress" class="Address"

            insert="false" update="false">

        <column name="person_id" not-null="true" length="10"/>

        <formula>'MAILING'</formula>

    </many-to-one>

## 5.2. Types Hibernate

### 5.2.1. Entités et valeurs

Pour le service de persistance, les objets sont classés en deux groupes au niveau langage Java :

Une entité existe indépendamment de tout autre objet possédant des références vers l'entité. Comparez cela avec le modèle Java habituel où un objet est supprimé par le garbage collector dès qu'il n'est plus référencé. Les entités doivent être explicitement enregistrées et supprimées (sauf dans les cas où sauvegardes et suppressions sont cascadées d'une entité parent vers ses enfants). C'est différent du modèle ODMG de persistance par atteignabilité - et correspond mieux à la façon dont les objets sont habituellement utilisés dans des grands systèmes. Les entités permettent les références circulaires et partagées. Elles peuvent aussi être versionnées.

L'état persistant d'une entité consiste en des références vers d'autres entités et instances de types valeurs. Ces valeurs sont des types primitifs, des collections (et non le contenu d'une collection), des composants de certains objets immuables. Contrairement aux entités, les valeurs (et en particulier les collections et composants) sont persistées et supprimées par atteignabiliité. Comme les valeurs (et types primitifs) sont persistées et supprimées avec l'entité qui les contient, ils ne peuvent pas posséder leurs propres versions. Les valeurs n'ont pas d'identité indépendantes, ainsi elles ne peuvent pas être partagées par deux entités ou collections.

Jusqu'à présent nous avons utilisé le terme "classe persistante" pour parler d'entités. Nous allons continuer à faire ainsi. Cependant, au sens strict, toutes les classes définies par un utilisateur possédant un état persistant ne sont pas des entités. Un composant est une classe définie par un utilisateur avec la sémantique d'une valeur. Une propriété Java de type `java.lang.String` a aussi les caractéristiques d'une valeur. Selon cette définition, nous sommes en mesure de déclarer que tous les types (classes) fournis par JDK possèdent la sémantique d'une valeur dans Java, alors que les types définis par un utilisateur pourront être mappés avec des sémantiques entités ou valeur type. Cette décision est prise par le développeur d'application. Un bon conseil pour une classe entité dans un modèle de domaine sont des références partagées à une instance unique de cette classe, alors que la composition ou l'agrégation se traduit en général par une valeur type.

Nous nous pencherons sur ces deux concepts tout au long de la documentation.

Le défi est de mapper les types Javas (et la définition des développeurs des entités et valeurs types) sur les types du SQL ou des bases de données. Le pont entre les deux systèmes est proposé par Hibernate : pour les entités nous utilisons `<class>`, `<subclass>` et ainsi de suite. Pour les types valeurs nous utilisons `<property>`, `<component>`, etc., habituellement avec un attribut `type`. La valeur de cet attribut est le nom d'un type de mappage Hibernate. Hibernate propose de nombreux mappages prêts à l'utilisation (pour les types de valeurs standards du JDK). Vous pouvez écrire vos propres types de mappages et implémenter aussi vos propres stratégies de conversion comme nous le verrons plus tard.

Tous les types proposés Hibernate à part les collections autorisent les sémantiques null.

### 5.2.2. Types valeurs de base

Les types de mappage de base peuvent être classés de la façon suivante :

`integer, long, short, float, double, character, byte, boolean, yes_no, true_false`

  Les mappages de type des primitives Java ou leurs classes wrappers (ex : Integer pour int) vers les types de colonne SQL (propriétaires) appropriés. `boolean, yes_no`et `true_false` sont tous des alternatives pour les types Java `boolean` ou `java.lang.Boolean`.

`string`

  Mappage de type de `java.lang.String` vers `VARCHAR` (ou le `VARCHAR2` Oracle).

`date, time, timestamp`

  mappages de type pour `java.util.Date` et ses sous-classes vers les types SQL `DATE`, `TIME` et `TIMESTAMP` (ou équivalent).

`calendar, calendar_date`

  mappages de type pour `java.util.Calendar` vers les types SQL `TIMESTAMP` et `DATE` (ou équivalent).

`big_decimal, big_integer`

  mappages de type de `java.math.BigDecimal` et `java.math.BigInteger` vers `NUMERIC` (ou le `NUMBER` Oracle).

`locale, timezone, currency`

  mappages de type pour `java.util.Locale`, `java.util.TimeZone` et `java.util.Currency` vers `VARCHAR` (ou le `VARCHAR2` Oracle). Les instances de `Locale` et `Currency` sont mappées sur leurs codes ISO. Les instances de `TimeZone` sont mappées sur leur `ID`.

`class`

  Un type de mappage de `java.lang.Class` vers `VARCHAR` (ou le `VARCHAR2` Oracle). Un objet `Class` est mappé sur son nom Java complet.

`binary`

  Mappe les tableaux de bytes vers le type binaire SQL approprié.

`text`

  Maps long Java strings to a SQL `LONGVARCHAR` or `TEXT` type.

`image`

  Maps long byte arrays to a SQL `LONGVARBINARY`.

`serializable`

  Mappe les types Java sérialisables vers le type SQL binaire approprié. Vous pouvez aussi indiquer le type Hibernate `serializable` avec le nom d'une classe Java sérialisable ou une interface qui ne soit pas par défaut un type de base.

`clob, blob`

  Mappages de type pour les classes JDBC `java.sql.Clob` et `java.sql.Blob`. Ces types peuvent ne pas convenir pour certaines applications car un objet blob ou clob peut ne pas être réutilisable en dehors d'une transaction (de plus l'implémentation par les pilotes comporte des lacunes).

`materialized_clob`

  Maps long Java strings to a SQL `CLOB` type. When read, the `CLOB` value is immediately materialized into a Java string. Some drivers require the `CLOB` value to be read within a transaction. Once materialized, the Java string is available outside of the transaction.

`materialized_blob`

  Maps long Java byte arrays to a SQL `BLOB` type. When read, the `BLOB` value is immediately materialized into a byte array. Some drivers require the `BLOB` value to be read within a transaction. Once materialized, the byte array is available outside of the transaction.

`imm_date, imm_time, imm_timestamp, imm_calendar, imm_calendar_date, imm_serializable, imm_binary`

  Mappages de type pour ceux qui sont habituellement considérés comme des types Java modifiables, et pour lesquels Hibernate effectue certaines optimisations convenant seulement aux types Java immuables. L'application les traite comme immuables. Par exemple, vous ne devriez pas appeler `Date.setTime()` sur une instance mappée sur un `imm_timestamp`. Pour changer la valeur de la propriété, et faire en sorte que cette modification soit persistée, l'application doit assigner un nouvel (non identique) objet à la propriété.

Les identifiants uniques des entités et collections peuvent être de n'importe quel type de base excepté `binary`, `blob` et `clob` (les identifiants composites sont aussi permis, voir plus bas).

Les types de base des valeurs ont des `Type` constants correspondants et définis dans `org.hibernate.Hibernate`. Par exemple, `Hibernate.STRING` représente le type `string`.

### 5.2.3. Types de valeur personnalisés

Il est assez facile pour les développeurs de créer leurs propres types de valeurs. Par exemple, vous aimeriez persister des propriétés du type `java.lang.BigInteger` dans des colonnes `VARCHAR`. Hibernate ne procure pas de type par défaut à cet effet. Toutefois, les types personnalisés ne se limitent pas à mapper des propriétés (ou élément collection) à une simple colonne de table. Donc, par exemple, vous pourriez avoir une propriété Java `getName()`/`setName()` de type `java.lang.String` persistée dans les colonnes `FIRST_NAME`, `INITIAL`, `SURNAME`.

Pour implémenter votre propre type, vous pouvez soit implémenter `org.hibernate.UserType` soit `org.hibernate.CompositeUserType` et déclarer des propriétés utilisant des noms de classes complets du type. Consultez `org.hibernate.test.DoubleStringType` pour étudier les possibilités.

    <property name="twoStrings" type="org.hibernate.test.DoubleStringType">

        <column name="first_string"/>

        <column name="second_string"/>

    </property>

Remarquez l'utilisation des balises `<column>` pour mapper une propriété sur des colonnes multiples.

Les interfaces `CompositeUserType`, `EnhancedUserType`, `UserCollectionType`, et `UserVersionType` prennent en charge des utilisations plus spécialisées.

Vous pouvez même fournir des paramètres en indiquant `UserType` dans le fichier de mappage. À cet effet, votre `UserType` doit implémenter l'interface `org.hibernate.usertype.ParameterizedType`. Pour spécifier des paramètres dans votre type propre, vous pouvez utiliser l'élément `<type>` dans vos fichiers de mappage.

    <property name="priority">

        <type name="com.mycompany.usertypes.DefaultValueIntegerType">

            <param name="default">0</param>

        </type>

    </property>

Le `UserType` permet maintenant de récupérer la valeur pour le paramètre nommé `default` à partir de l'objet `Properties` qui lui est passé.

Si vous utilisez fréquemment un `UserType`, il est utile de lui définir un nom plus court. Vous pouvez l'effectuer, en utilisant l'élément `<typedef>`. Les typedefs permettent d'assigner un nom à votre type propre et peuvent aussi contenir une liste de valeurs de paramètres par défaut si ce type est paramétré.

    <typedef class="com.mycompany.usertypes.DefaultValueIntegerType" name="default_zero">

        <param name="default">0</param>

    </typedef>

    <property name="priority" type="default_zero"/>

Il est également possible de redéfinir les paramètres par défaut du typedef au cas par cas en utilisant des paramètres type sur le mappage de la propriété.

Alors que Hibernate offre une riche variété de types, et la prise en charge des composants, vous aurez très rarement besoin d'utiliser un type personnalisé, il est néanmoins recommandé d'utiliser des types personnalisés pour les classes (non entités) qui apparaissent fréquemment dans votre application. Par exemple, une classe `MonetaryAmount` est un bon candidat pour un `CompositeUserType` même si elle pourrait facilement être mappée en tant que composant. Une motivation pour cela est l'abstraction. Avec un type personnalisé, vos documents de mappage sont à l'abri des changements futurs dans votre façon de représenter des valeurs monétaires.

## 5.3. Mapper une classe plus d'une fois

Il est possible de fournir plus d'un mappage par classe persistante. Dans ce cas, vous devez spécifier un nom d'entité pour lever l'ambiguité entre les instances des entités mappées (par défaut, le nom de l'entité est celui de la classe). Hibernate vous permet de spécifier le nom de l'entité lorsque vous utilisez des objets persistants, lorsque vous écrivez des requêtes ou quand vous mappez des associations vers les entités nommées.

    <class name="Contract" table="Contracts"
            entity-name="CurrentContract">
        ...
        <set name="history" inverse="true"
                order-by="effectiveEndDate desc">
            <key column="currentContractId"/>
            <one-to-many entity-name="HistoricalContract"/>
        </set>
    </class>

    <class name="Contract" table="ContractHistory"
            entity-name="HistoricalContract">
        ...
        <many-to-one name="currentContract"
                column="currentContractId"
                entity-name="CurrentContract"/>
    </class>

Remarquez comment les associations sont désormais spécifiées en utilisant `entity-name` au lieu de `class`.

## Note

This feature is not supported in Annotations

## 5.4. SQL quoted identifiers

Vous pouvez forcer Hibernate à mettre un identifiant entre quotes dans le SQL généré en mettant le nom de la table ou de la colonne entre backticks dans le document de mappage. Hibernate utilisera les bons styles de quotes pour le SQL `Dialect` (habituellement des doubles quotes, mais des parenthèses pour SQL Server et des backticks pour MySQL).

    @Entity @Table(name="`Line Item`")

    class LineItem {

       @id @Column(name="`Item Id`") Integer id;

       @Column(name="`Item #`") int itemNumber

    }

    <class name="LineItem" table="`Line Item`">

        <id name="id" column="`Item Id`"/><generator class="assigned"/></id>

        <property name="itemNumber" column="`Item #`"/>

        ...

    </class>

## 5.5. Propriétés générées

Les propriétés générées sont des propriétés dont les valeurs sont générées par la base de données. Typiquement, les applications Hibernate avaient besoin d'invoquer `refresh` sur les instances qui contenaient des propriétés pour lesquelles la base de données générait des valeurs. Marquer les propriétés comme générées, permet à l'application de déléguer cette responsabilité à Hibernate. Principalement, à chaque fois que Hibernate réalise un SQL INSERT ou UPDATE en base de données pour une entité marquée comme telle, cela provoque immédiatement un select pour récupérer les valeurs générées.

Properties marked as generated must additionally be non-insertable and non-updateable. Only versions, timestamps, and simple properties, can be marked as generated.

`never` (par défaut) - indique que la valeur donnée de la propriété n'est pas générée dans la base de données.

`insert`: the given property value is generated on insert, but is not regenerated on subsequent updates. Properties like created-date fall into this category. Even though version and timestamp properties can be marked as generated, this option is not available.

`always` - indique que la valeur de la propriété est générée à l'insertion comme aux mise à jour.

To mark a property as generated, use `@Generated`.

## 5.6. Column transformers: read and write expressions

Hibernate allows you to customize the SQL it uses to read and write the values of columns mapped to simple properties. For example, if your database provides a set of data encryption functions, you can invoke them for individual columns like this:

    @Entity

    class CreditCard {

       @Column(name="credit_card_num")

       @ColumnTransformer(

          read="decrypt(credit_card_num)",

          write="encrypt(?)")

       public String getCreditCardNumber() { return creditCardNumber; }

       public void setCreditCardNumber(String number) { this.creditCardNumber = number; }

       private String creditCardNumber;

    }

or in XML

    <property name="creditCardNumber">

            <column

              name="credit_card_num"

              read="decrypt(credit_card_num)"

              write="encrypt(?)"/>

    </property>

## Note

You can use the plural form `@ColumnTransformers` if more than one columns need to define either of these rules.

If a property uses more that one column, you must use the `forColumn` attribute to specify which column, the expressions are targeting.

    @Entity

    class User {

       @Type(type="com.acme.type.CreditCardType")

       @Columns( {

          @Column(name="credit_card_num"),

          @Column(name="exp_date") } )

       @ColumnTransformer(

          forColumn="credit_card_num",

          read="decrypt(credit_card_num)",

          write="encrypt(?)")

       public CreditCard getCreditCard() { return creditCard; }

       public void setCreditCard(CreditCard card) { this.creditCard = card; }

       private CreditCard creditCard;

    }

Hibernate applies the custom expressions automatically whenever the property is referenced in a query. This functionality is similar to a derived-property `formula` with two differences:

- The property is backed by one or more columns that are exported as part of automatic schema generation.

- The property is read-write, not read-only.

The `write` expression, if specified, must contain exactly one '?' placeholder for the value.

## 5.7. Objets auxiliaires de la base de données

Permettent les ordres CREATE et DROP d'objets arbitraire de la base de données, en conjonction avec les outils Hibernate d'évolutions de schéma, pour permettre de définir complètement un schéma utilisateur au sein des fichiers de mappage Hibernate. Bien que conçu spécifiquement pour créer et supprimer des objets tels que les triggers et les procédures stockées, en réalité toute commande pouvant être exécutée via une méthode de `java.sql.Statement.execute()` (ALTERs, INSERTS, etc) est valable à cet endroit. Il y a principalement deux modes pour définir les objets auxiliaires de base de données :

Le premier mode est de lister explicitement les commandes CREATE et DROP dans le fichier de mappage :

    <hibernate-mapping>

        ...

        <database-object>

            <create>CREATE TRIGGER my_trigger ...</create>

            <drop>DROP TRIGGER my_trigger</drop>

        </database-object>

    </hibernate-mapping>

Le second mode est de fournir une classe personnalisée qui sait comment construire les commandes CREATE et DROP. Cette classe personnalisée doit implémenter l'interface `org.hibernate.mappage.AuxiliaryDatabaseObject`.

    <hibernate-mapping>

        ...

        <database-object>

            <definition class="MyTriggerDefinition"/>

        </database-object>

    </hibernate-mapping>

De plus, ces objets de base de données peuvent être optionnellement traités selon l'utilisation de dialectes particuliers.

    <hibernate-mapping>

        ...

        <database-object>

            <definition class="MyTriggerDefinition"/>

            <dialect-scope name="org.hibernate.dialect.Oracle9iDialect"/>

            <dialect-scope name="org.hibernate.dialect.Oracle10gDialect"/>

        </database-object>

    </hibernate-mapping>

## Note

This feature is not supported in Annotations

Copyright © 2004 Red Hat, Inc.

- PrécédentChapitre 4. Classes persistantes
- Niveau supérieur
- Sommaire
- SuivantChapitre 6. Types