[hibernate-commits] Hibernate SVN: r10656 - in branches/Branch_3_2/HibernateExt/metadata/doc/reference: . fr fr/images fr/modules fr/styles
hibernate-commits at lists.jboss.org
hibernate-commits at lists.jboss.org
Fri Oct 27 16:03:30 EDT 2006
Author: epbernard
Date: 2006-10-27 16:03:29 -0400 (Fri, 27 Oct 2006)
New Revision: 10656
Added:
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/images/
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/images/hibernate_logo_a.png
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/master.xml
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/entity.xml
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/lucene.xml
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/setup.xml
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/validator.xml
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/xml-overriding.xml
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/fopdf.xsl
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/html.css
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/html.xsl
branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/html_chunk.xsl
Modified:
branches/Branch_3_2/HibernateExt/metadata/doc/reference/build.xml
Log:
ANN-478 French translation (Vincent Ricard)
Modified: branches/Branch_3_2/HibernateExt/metadata/doc/reference/build.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/build.xml 2006-10-27 19:56:30 UTC (rev 10655)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/build.xml 2006-10-27 20:03:29 UTC (rev 10656)
@@ -12,10 +12,14 @@
<param name="docname" value="hibernate_annotations"/>
<param name="lang" value="en"/>
</antcall>
- <antcall target="lang.all">
+ <antcall target="lang.all">
<param name="docname" value="hibernate_annotations"/>
<param name="lang" value="zh_cn"/>
</antcall>
+ <antcall target="lang.all">
+ <param name="docname" value="hibernate_annotations"/>
+ <param name="lang" value="fr"/>
+ </antcall>
</target>
</project>
Added: branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/images/hibernate_logo_a.png
===================================================================
(Binary files differ)
Property changes on: branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/images/hibernate_logo_a.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/master.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/master.xml 2006-10-27 19:56:30 UTC (rev 10655)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/master.xml 2006-10-27 20:03:29 UTC (rev 10656)
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3CR3//EN"
+"../../../../../Hibernate3/doc/reference/support/docbook-dtd/docbookx.dtd" [
+<!ENTITY setup SYSTEM "modules/setup.xml">
+<!ENTITY entity SYSTEM "modules/entity.xml">
+<!ENTITY xml-overriding SYSTEM "modules/xml-overriding.xml">
+<!ENTITY validator SYSTEM "modules/validator.xml">
+<!ENTITY lucene SYSTEM "modules/lucene.xml">
+]>
+<book lang="fr">
+ <bookinfo>
+ <title>Hibernate Annotations</title>
+
+ <subtitle>Guide de référence</subtitle>
+
+ <releaseinfo>3.2.0.GA</releaseinfo>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/hibernate_logo_a.png" format="png" />
+ </imageobject>
+ </mediaobject>
+ </bookinfo>
+
+ <toc></toc>
+
+ <preface id="preface" revision="1">
+ <title>Préface</title>
+ <para>Traducteur(s): Vincent Ricard</para>
+
+ <para>Hibernate, comme tous les autres outils de mapping objet/relationnel,
+ nécessite des méta-données qui régissent la transformation des données
+ d'une représentation vers l'autre (et vice versa). Dans Hibernate 2.x, les
+ méta-données de mapping sont la plupart du temps déclarées dans des fichiers
+ XML. Une autre option est XDoclet, qui utilise les annotations du code source
+ Javadoc et un préprocesseur au moment de la compilation. Le même genre
+ d'annotation est maintenant disponible avec le JDK standard, quoique plus
+ puissant et mieux pris en charge par les outils. IntelliJ IDEA et Eclipse,
+ par exemple, prennent en charge la complétion automatique et la coloration
+ syntaxique des annotations du JDK 5.0. Les annotations sont compilées en
+ bytecode et lues au moment de l'exécution (dans le cas d'Hibernate, au
+ démarrage) en utilisant la réflexion, donc pas besoin de fichiers XML
+ externes.</para>
+
+ <para>La spécification EJB3 reconnaît l'intérêt et le succès du paradigme
+ du mapping objet/relationnel transparent. La spécification EJB3 standardise
+ les APIs de base et les méta-données requises par n'importe quel mécanisme
+ de persistance objet/relationnel. <emphasis>Hibernate EntityManager</emphasis>
+ implémente les interfaces de programmation et les règles de cycle de vie
+ telles que définies par la spécification de persistance EJB3. Avec
+ <emphasis>Hibernate Annotations</emphasis>, ce wrapper implémente une
+ solution de persistance EJB3 complète (et autonome) au-dessus du noyau
+ mature d'Hibernate. Vous pouvez utiliser soit les trois ensembles, soit les
+ annotations sans le cycle de vie et les interfaces de programmations EJB3,
+ ou même Hibernate tout seul, selon les besoins techniques et fonctionnels
+ de votre projet. Vous pouvez à tout moment recourir aux APIs natives
+ d'Hibernate ou même, si besoin est, à celles de JDBC et au SQL.</para>
+
+ <para>Cette version est basée sur la dernière version de la spécification
+ EJB 3.0 / JPA (alias JSP-220) et prend en charge toutes les fonctionnalités
+ de la spécification (dont certaines optionnelles). La plupart des
+ fonctionnalités d'Hibernate et des extensions sont aussi disponibles à
+ travers des annotations spécifiques à Hibernate. Bien que la couverture
+ d'Hibernate en termes de fonctionnalités soit maintenant très grande,
+ certaines sont encore manquantes. Le but ultime est de tout couvrir. Voir la
+ section JIRA "road map" pour plus d'informations.</para>
+
+ <para>Si vous utilisiez une version précédente d'Hibernate Annotations,
+ veuillez regarder <uri>http://www.hibernate.org/371.html</uri> pour un guide
+ de migration.</para>
+ </preface>
+
+ &setup;
+
+ &entity;
+
+ &xml-overriding;
+
+ &validator;
+
+ &lucene;
+</book>
\ No newline at end of file
Added: branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/entity.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/entity.xml 2006-10-27 19:56:30 UTC (rev 10655)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/entity.xml 2006-10-27 20:03:29 UTC (rev 10656)
@@ -0,0 +1,3458 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<chapter id="entity">
+ <title>Entity Beans</title>
+
+ <sect1 id="entity-overview" revision="1">
+ <title>Introduction</title>
+
+ <para>Cette section couvre les annotations entity bean EJB 3.0 (alias JPA)
+ et les extensions spécifiques à Hibernate.</para>
+ </sect1>
+
+ <sect1 id="entity-mapping" revision="2">
+ <title>Mapping avec les annotations EJB3/JPA</title>
+
+ <para>Les entités EJB3 sont des POJOs ordinaires. En fait, ils
+ représentent exactement le même concept que les entités de persistance
+ Hibernate. Leur mapping est défini à travers les annotations du JDK 5.0
+ (une syntaxe de descripteur XML pour la surcharge est définie dans la
+ spécification EJB3). Les annotations peuvent être divisées en deux
+ catégories, les annotations de mapping logique (vous permettant de décrire
+ le modèle objet, les associations de classe, etc) et les annotations de
+ mapping physique (décrivant le schéma physique, les tables, les colonnes,
+ les index, etc). Nous mélangerons les annotations des deux catégories dans
+ les exemples de code.</para>
+
+ <para>Les annotations EJB3 sont dans le package
+ <literal>javax.persistence.*</literal>. La plupart des IDE compatibles JDK 5
+ (comme Eclipse, IntelliJ IDEA et Netbeans) peuvent auto-compléter les
+ interfaces et les attributes d'annotation pour vous (même sans module "EJB3"
+ spécifique, puisque les annotations EJB3 sont des annotations ordinaires de
+ JDK 5).</para>
+
+ <para>Pour plus d'exemples concrets, lisez le tutorial EJB 3.0 de JBoss ou
+ parcourez la suite de tests d'Hibernate Annotations. La plupart des tests
+ unitaires ont été conçus pour représenter un exemple concret et être une
+ source d'inspiration.</para>
+
+ <sect2>
+ <title>Déclarer un entity bean</title>
+
+ <para>Chaque classe POJO persistante liée est un entity bean et est
+ déclarée en utilisant l'annotation <literal>@Entity</literal> (au niveau
+ de la classe) :</para>
+
+ <programlisting>
+ at Entity
+public class Flight implements Serializable {
+ Long id;
+
+ @Id
+ public Long getId() { return id; }
+
+ public void setId(Long id) { this.id = id; }
+}
+</programlisting>
+
+ <para><literal>@Entity</literal> déclare la classe comme un entity bean
+ (ie une classe POJO persistante), <literal>@Id</literal> déclare la
+ propriété identifiante de cet entity bean. Les autres déclarations de
+ mapping sont implicites. Ce concept de déclaration par exception est
+ un composant essentiel de la nouvelle spécification EJB3 et une
+ amélioration majeure. La classe Flight est mappée sur la table Flight, en
+ utilisant la colonne id comme colonne de la clef primaire.</para>
+
+ <para>Selon que vous annotez des champs ou des méthodes, le type d'accès
+ utilisé par Hibernate sera <literal>field</literal> ou
+ <literal>property</literal>. La spécification EJB3 exige que vous
+ déclariez les annotations sur le type d'élément qui sera accédé,
+ c'est-à-dire le getter si vous utilisez l'accès
+ <literal>property</literal>, le champ si vous utilisez l'accès
+ <literal>field</literal>. Mélanger des EJB3 annotations dans les champs et
+ les méthodes devrait être évité. Hibernate devinera le type d'accès de
+ l'identifiant à partir de la position d'<literal>@Id</literal> ou
+ d'<literal>@EmbeddedId</literal>.</para>
+
+ <sect3>
+ <title>Définir la table</title>
+
+ <para><literal>@Table</literal> est positionnée au niveau de la classe ;
+ cela vous permet de définir le nom de la table, du catalogue et du
+ schéma pour le mapping de votre entity bean. Si aucune
+ <literal>@Table</literal> n'est définie les valeurs par défaut sont
+ utilisées : le nom de la classe de l'entité (sans le nom de
+ package).</para>
+
+ <programlisting>
+ at Entity
+ at Table(name="tbl_sky")
+public class Sky implements Serializable {
+...
+ </programlisting>
+
+ <para>L'élément <literal>@Table</literal> contient aussi un attribut
+ <literal>schema</literal> et un attribut <literal>catalog</literal>,
+ si vous avez besoin de les définir. Vous pouvez aussi définir des
+ contraintes d'unicité sur la table en utilisant l'annotation
+ <literal>@UniqueConstraint</literal> en conjonction avec
+ <literal>@Table</literal> (pour une contrainte d'unicité n'impliquant
+ qu'une seule colonne, référez-vous à <literal>@Column</literal>).</para>
+
+ <programlisting>@Table(name="tbl_sky",
+ <emphasis role="bold">uniqueConstraints = {@UniqueConstraint(columnNames={"month", "day"})}</emphasis>
+)</programlisting>
+
+ <para>Une contrainte d'unicité est appliquée au tuple {month, day}.
+ Notez que le tableau <literal>columnNames</literal> fait référence aux
+ noms logiques des colonnes.</para>
+
+ <remark>Le nom logique d'une colonne est défini par l'implémentation
+ de NamingStrategy d'Hibernate. La stratégie de nommage EJB3 par défaut
+ utilise le nom de colonne physique comme nom de colonne logique. Notez
+ qu'il peut être différent du nom de la propriété (si le nom de colonne
+ est explicite). A moins que vous surchargiez la stratégie de nommage,
+ vous ne devriez pas vous soucier de ça.</remark>
+ </sect3>
+
+ <sect3>
+ <title>Versionner pour un contrôle de concurrence optimiste</title>
+
+ <para>Vous pouvez ajouter un contrôle de concurrence optimiste à un
+ entity bean en utilisant l'annotation
+ <literal>@Version</literal> :</para>
+
+ <programlisting>
+ at Entity
+public class Flight implements Serializable {
+...
+ @Version
+ @Column(name="OPTLOCK")
+ public Integer getVersion() { ... }
+} </programlisting>
+
+ <para>La propriété de version sera mappée sur la colonne
+ <literal>OPTLOCK</literal>, et le gestionnaire d'entités l'utilisera
+ pour détecter des conflits lors des mises à jour (prévenant des pertes
+ de données lors de mises à jours que vous pourriez voir avec la
+ stratégie du last-commit-wins).</para>
+
+ <para>La colonne de version peut être un numérique (solution
+ recommandée) ou un timestamp comme pour la spécification EJB3. Hibernate
+ prend en charge n'importe quel type fourni que vous définissez et
+ implémentez avec la classe <classname>UserVersionType</classname>
+ appropriée.</para>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Mapping de simples propriétés</title>
+
+ <sect3>
+ <title>Déclarer des mappings de propriétés élémentaires</title>
+
+ <para>Chaque propriété (champ ou méthode) non statique non transient
+ d'un entity bean est considérée persistante, à moins que vous l'annotiez
+ comme <literal>@Transient</literal>. Ne pas avoir d'annotation pour
+ votre propriété est équivalent à l'annotation <literal>@Basic</literal>.
+ L'annotation <literal>@Basic</literal> vous permet de déclarer la
+ stratégie de récupération pour une propriété :</para>
+
+ <programlisting>public transient int counter; // propriété transient
+
+private String firstname; // propriété persistante
+
+ at Transient
+String getLengthInMeter() { ... } // propriété transient
+
+String getName() {... } // propriété persistante
+
+ at Basic
+int getLength() { ... } // propriété persistante
+
+ at Basic(fetch = FetchType.LAZY)
+String getDetailedComment() { ... } // propriété persistante
+
+ at Temporal(TemporalType.TIME)
+java.util.Date getDepartureTime() { ... } // propriété persistante
+
+ at Enumerated(STRING)
+Starred getNote() { ... } // enum persistée en tant que String dans la base de données</programlisting>
+
+ <para><literal>counter</literal>, un champ transient, et
+ <literal>lengthInMeter</literal>, une méthode annotée comme
+ <literal>@Transient</literal>, seront ignorés par le gestionnaire
+ d'entités. Les propriétés <literal>name</literal>,
+ <literal>length</literal>, et <literal>firstname</literal> sont mappées
+ comme persistantes et à charger immédiatement (ce sont les valeurs
+ par défaut pour les propriétés simples). La valeur de la propriété
+ <literal>detailedComment</literal> sera chargée à partir de la base de
+ données dès que la propriété de l'entité sera accédée pour la première
+ fois. En général vous n'avez pas besoin de marquer de simples propriétés
+ comme "à charger à la demande" (NdT: lazy) (à ne pas confondre avec la
+ récupération d'association "lazy").</para>
+
+ <note>
+ <para>Pour activer la récupération à la demande au niveau de la
+ propriété, vos classes doivent être instrumentées : du bytecode est
+ ajouté au code original pour activer cette fonctionnalité, veuillez
+ vous référer à la documentation de référence d'Hibernate. Si vos
+ classes ne sont pas instrumentées, le chargement à la demande au
+ niveau de la propriété est silencieusement ignoré.</para>
+ </note>
+
+ <para>L'alternative recommandée est d'utiliser la capacité de projection
+ de JPA-QL ou des requêtes Criteria.</para>
+
+ <para>EJB3 prend en charge le mapping de propriété de tous les types
+ élémentaires pris en charge par Hibernate (tous les types de base Java,
+ leur wrapper respectif et les classes sérialisables). Hibernate
+ Annotations prend en charge le mapping des types Enum soit vers une
+ colonne ordinale (en stockant le numéro ordinal de l'enum), soit vers
+ une colonne de type chaîne de caractères (en stockant la chaîne de
+ caractères représentant l'enum) : la représentation de la persistance,
+ par défaut ordinale, peut être surchargée grâce à l'annotation
+ <literal>@Enumerated</literal> comme montré avec la propriété
+ <literal>note</literal> de l'exemple.</para>
+
+ <para>Dans les APIs core de Java, la précision temporelle n'est pas
+ définie. Lors du traitement de données temporelles vous pourriez vouloir
+ décrire la précision attendue dans la base de données. Les données
+ temporelles peuvent avoir une précision de type <literal>DATE</literal>,
+ <literal>TIME</literal>, ou <literal>TIMESTAMP</literal> (c'est-à-dire
+ seulement la date, seulement l'heure, ou les deux). Utilisez
+ l'annotation <literal>@Temporal</literal> pour ajuster cela.</para>
+
+ <para><literal>@Lob</literal> indique que la propriété devrait être
+ persistée dans un Blob ou un Clob selon son type :
+ <classname>java.sql.Clob</classname>,
+ <classname>Character[]</classname>, <classname>char[]</classname> et
+ java.lang.<classname>String</classname> seront persistés dans un Clob.
+ <classname>java.sql.Blob</classname>, <classname>Byte[]</classname>,
+ <classname>byte[] </classname> et les types sérialisables seront
+ persistés dans un Blob.</para>
+
+ <programlisting>
+ at Lob
+public String getFullText() {
+ return fullText;
+}
+
+ at Lob
+public byte[] getFullCode() {
+ return fullCode;
+}
+ </programlisting>
+
+ <para>Si le type de la propriété implémente
+ <classname>java.io.Serializable</classname> et n'est pas un type de
+ base, et si la propriété n'est pas annotée avec <literal>@Lob</literal>,
+ alors le type Hibernate <literal>serializable</literal> est
+ utilisé.</para>
+ </sect3>
+
+ <sect3>
+ <title>Déclarer des attributs de colonne</title>
+
+ <para>La(les) colonne(s) utilisée(s) pour mapper une propriété peuvent
+ être définies en utilisant l'annotation <literal>@Column</literal>.
+ Utilisez-la pour surcharger les valeurs par défaut (voir la
+ spécification EJB3 pour plus d'informations sur les valeurs par défaut).
+ Vous pouvez utilisez cette annotation au niveau de la propriété pour
+ celles qui sont :</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>pas du tout annotées</para>
+ </listitem>
+
+ <listitem>
+ <para>annotées avec <literal>@Basic</literal></para>
+ </listitem>
+
+ <listitem>
+ <para>annotées avec <literal>@Version</literal></para>
+ </listitem>
+
+ <listitem>
+ <para>annotées avec <literal>@Lob</literal></para>
+ </listitem>
+
+ <listitem>
+ <para>annotées avec <literal>@Temporal</literal></para>
+ </listitem>
+
+ <listitem>
+ <para>annotées avec
+ <literal>@org.hibernate.annotations.CollectionOfElements</literal>
+ (pour Hibernate uniquement)</para>
+ </listitem>
+ </itemizedlist>
+
+ <programlisting>
+ at Entity
+public class Flight implements Serializable {
+...
+ at Column(updatable = false, name = "flight_name", nullable = false, length=50)
+public String getName() { ... }
+ </programlisting>
+
+ <para>La propriété <literal>name</literal> est mappée sur la colonne
+ <literal>flight_name</literal>, laquelle ne peut pas avoir de valeur
+ nulle, a une longueur de 50 et ne peut pas être mise à jour (rendant
+ la propriété immuable).</para>
+
+ <para>Cette annotation peut être appliquée aux propriétés habituelles
+ ainsi qu'aux propriétés <literal>@Id</literal> ou
+ <literal>@Version</literal>.</para>
+
+ <programlistingco>
+ <areaspec>
+ <area coords="2 55" id="hm1" />
+
+ <area coords="3 55" id="hm2" />
+
+ <area coords="4 55" id="hm3" />
+
+ <area coords="5 55" id="hm4" />
+
+ <area coords="6 55" id="hm5" />
+
+ <area coords="7 55" id="hm6" />
+
+ <area coords="8 55" id="hm7" />
+
+ <area coords="9 55" id="hm8" />
+
+ <area coords="10 55" id="hm9" />
+
+ <area coords="11 55" id="hm10" />
+ </areaspec>
+
+ <programlisting>@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</programlisting>
+
+ <calloutlist>
+ <callout arearefs="hm1">
+ <para><literal>name</literal> (optionnel) : le nom de la colonne
+ (par défaut le nom de la propriété)</para>
+ </callout>
+
+ <callout arearefs="hm2">
+ <para><literal>unique</literal> (optionnel) : indique si la colonne
+ fait partie d'une contrainte d'unicité ou non (par défaut
+ false)</para>
+ </callout>
+
+ <callout arearefs="hm3">
+ <para><literal>nullable</literal> (optionnel) : indique si la
+ colonne peut avoir une valeur nulle (par défaut false).</para>
+ </callout>
+
+ <callout arearefs="hm4">
+ <para><literal>insertable</literal> (optionnel) : indique si la
+ colonne fera partie de la commande insert (par défaut true)</para>
+ </callout>
+
+ <callout arearefs="hm5">
+ <para><literal>updatable</literal> (optionnel) : indique si la
+ colonne fera partie de la commande update (par défaut true)</para>
+ </callout>
+
+ <callout arearefs="hm6">
+ <para><literal>columnDefinition</literal> (optionnel) : surcharge
+ le fragment DDL sql pour cette colonne en particulier (non
+ portable)</para>
+ </callout>
+
+ <callout arearefs="hm7">
+ <para><literal>table</literal> (optionnel) : définit la table
+ cible (par défaut la table principale)</para>
+ </callout>
+
+ <callout arearefs="hm8">
+ <para><literal><literal>length</literal></literal> (optionnel) :
+ longueur de la colonne (par défaut 255)</para>
+ </callout>
+
+ <callout arearefs="hm8">
+ <para><literal><literal>precision</literal></literal>
+ (optionnel) : précision décimale de la colonne (par défaut
+ 0)</para>
+ </callout>
+
+ <callout arearefs="hm10">
+ <para><literal><literal>scale</literal></literal> (optionnel) :
+ échelle décimale de la colonne si nécessaire (par défaut 0)</para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+ </sect3>
+
+ <sect3>
+ <title>Objets embarqués (alias composants)</title>
+
+ <para>Il est possible de déclarer un composant embarqué à l'intérieur
+ d'une entité et même de surcharger le mapping de ses colonnes. Les
+ classes de composant doivent être annotées au niveau de la classe avec
+ l'annotation <literal>@Embeddable</literal>. Il est possible de
+ surcharger le mapping de colonne d'un objet embarqué pour une entité
+ particulière en utilisant les annotations
+ <literal>@Embedded</literal> et <literal>@AttributeOverride</literal>
+ sur la propriété associée :</para>
+
+ <programlisting>
+ at Entity
+public class Person implements Serializable {
+
+ // Composant persistant utilisant les valeurs par défaut
+ Address homeAddress;
+
+ @Embedded
+ @AttributeOverrides( {
+ @AttributeOverride(name="iso2", column = @Column(name="bornIso2") ),
+ @AttributeOverride(name="name", column = @Column(name="bornCountryName") )
+ } )
+ Country bornIn;
+ ...
+}
+ </programlisting>
+
+ <programlisting>
+ at Embeddable
+public class Address implements Serializable {
+ String city;
+ Country nationality; // par de surcharge ici
+}
+ </programlisting>
+
+ <programlisting>
+ at 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; }
+ ...
+}
+ </programlisting>
+
+ <para>Un objet embarquable hérite du type d'accès de son entité
+ d'appartenance (notez que vous pouvez surcharger cela en utilisant les
+ annotations spécifiques à Hibernate <literal>@AccessType</literal>,
+ voir <xref linkend="entity-hibspec" />).</para>
+
+ <para>L'entity bean <literal>Person</literal> a deux propriétés
+ composant, <literal>homeAddress</literal> et
+ <literal>bornIn</literal>. La propriété <literal>homeAddress</literal>
+ n'a pas été annotée, mais Hibernate devinera que c'est un composant
+ persistant en cherchant l'annotation <literal>@Embeddable</literal>
+ dans la classe Address. Nous surchargeons aussi le mapping d'un nom de
+ colonne (pour <literal>bornCountryName</literal>) avec les annotations
+ <literal>@Embedded</literal> et <literal>@AttributeOverride</literal>
+ pour chaque attribut mappé de <literal>Country</literal>. Comme vous
+ pouvez le voir, <literal>Country</literal> est aussi un composant
+ imbriqué de <literal>Address</literal>, utilisant de nouveau la
+ détection automatique d'Hibernate et les valeurs par défaut EJB3.
+ Surcharger des colonnes d'objets embarqués d'objets (eux-mêmes)
+ embarqués n'est actuellement pas pris en charge par la spécification
+ EJB3, cependant, Hibernate Annotations le prend en charge à travers des
+ expressions séparées par des points.</para>
+
+ <para><programlisting> @Embedded
+ @AttributeOverrides( {
+ @AttributeOverride(name="city", column = @Column(name="fld_city") )
+ @AttributeOverride(name="<emphasis role="bold">nationality.iso2</emphasis>", column = @Column(name="nat_Iso2") ),
+ @AttributeOverride(name="<emphasis role="bold">nationality.name</emphasis>", column = @Column(name="nat_CountryName") )
+ // les colonnes de nationality dans homeAddress sont surchargées
+ } )
+ Address homeAddress;</programlisting>Hibernate Annotations prend en charge
+ une fonctionnalité de plus qui n'est pas explicitement prise en charge
+ par la spécification EJB3. Vous pouvez annoter un objet embarqué avec
+ l'annotation
+ <literal>@MappedSuperclass</literal> pour rendre les propriétés de la
+ classe parente persistantes (voir <literal>@MappedSuperclass</literal>
+ pour plus d'informations).</para>
+
+ <para>Alors que ce n'est pas pris en charge par la spécification EJB3,
+ Hibernate Annotations vous permet d'utiliser les annotations
+ d'association dans un objet embarquable (ie <literal>@*ToOne</literal>
+ ou <literal>@*ToMany</literal>). Pour surcharger les colonnes de
+ l'association vous pouvez utiliser
+ <literal>@AssociationOverride</literal>.</para>
+
+ <para>Si vous voulez avoir le même type d'objet embarquable deux fois
+ dans la même entité, le nom de colonne par défaut ne fonctionnera pas :
+ au moins une des colonnes devra être explicitée. Hibernate va au-delà
+ de la spécification EJB3 et vous permet d'améliorer le mécanisme par
+ défaut avec <classname>NamingStrategy</classname>.
+ <classname>DefaultComponentSafeNamingStrategy</classname> est une petite
+ amélioration par rapport à la stratégie par défaut
+ <classname>EJB3NamingStrategy</classname> qui permet aux objets
+ embarqués de fonctionner avec leur valeur par défaut même s'ils sont
+ utilisés deux fois dans la même entité.</para>
+ </sect3>
+
+ <sect3>
+ <title>Valeurs par défaut des propriétés non annotées</title>
+
+ <para>Si une propriété n'est pas annotée, les règles suivantes
+ s'appliquent :</para>
+
+ <itemizedlist>
+ <listitem>
+ Si la propriété est de type simple, elle est mappée comme @Basic
+ </listitem>
+
+ <listitem>
+ Sinon, si le type de la propriété est annoté comme @Embeddable,
+ elle est mappée comme @Embedded
+ </listitem>
+
+ <listitem>
+ Sinon, si le type de la propriété est Serializable, elle est mappée
+ comme @Basic vers une colonne contenant l'objet sous sa forme
+ sérialisée
+ </listitem>
+
+ <listitem>
+ Sinon, si le type de la propriété est java.sql.Clob ou
+ java.sql.Blob, elle est mappée comme @Lob avec le LobType
+ approprié
+ </listitem>
+ </itemizedlist>
+ </sect3>
+ </sect2>
+
+ <sect2 id="entity-mapping-identifier"
+ xreflabel="Mapper des propriétés identifiantes">
+ <title>Mapper des propriétés identifiantes</title>
+
+ <para>L'annotation <literal>@Id</literal> vous permet de définir quelle
+ propriété identifie votre entity bean. Cette propriété peut être
+ positionnée par l'application elle-même ou générée par Hibernate
+ (préféré). Vous pouvez définir la stratégie de génération de l'identifiant
+ grâce à l'annotation <literal>@GeneratedValue</literal> :</para>
+
+ <itemizedlist>
+ <listitem>
+ AUTO - soit la colonne identity, soit la séquence, soit la table
+ selon la base de données sous-jacente
+ </listitem>
+
+ <listitem>
+ TABLE - table contenant l'id
+ </listitem>
+
+ <listitem>
+ IDENTITY - colonne identity
+ </listitem>
+
+ <listitem>
+ SEQUENCE - séquence
+ </listitem>
+ </itemizedlist>
+
+ <para>Hibernate fournit plus de générateurs d'identifiant que les simples
+ générateurs EJB3. Vérifiez <xref linkend="entity-hibspec" /> pour plus
+ d'informations.</para>
+
+ <para>L'exemple suivant montre un générateur par séquence utilisant la
+ configuration SEQ_STORE (voir plus bas) :</para>
+
+ <programlisting>
+ at Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE")
+public Integer getId() { ... }
+ </programlisting>
+
+ <para>L'exemple suivant utilise le générateur identity :</para>
+
+ <programlisting>
+ at Id @GeneratedValue(strategy=GenerationType.IDENTITY)
+public Long getId() { ... }
+ </programlisting>
+
+ <para>Le générateur <literal>AUTO</literal> est le type préféré pour les
+ applications portables (vers différentes base de données). La
+ configuration de la génération d'identifiant peut être partagée par
+ différents mappings <literal>@Id</literal> avec l'attribut du générateur.
+ Il y a différentes configurations disponibles avec
+ <literal>@SequenceGenerator</literal> et
+ <literal>@TableGenerator</literal>. La portée d'un générateur peut être
+ l'application ou la classe. Les générateurs définis dans les classes ne
+ sont pas visibles à l'extérieur de la classe et peuvent surcharger les
+ générateurs de niveau applicatif. Les générateurs de niveau applicatif
+ sont définis au niveau XML (voir
+ <xref linkend="xml-overriding" />) :</para>
+
+ <programlisting><table-generator name="EMP_GEN"
+ table="GENERATOR_TABLE"
+ pk-column-name="key"
+ value-column-name="hi"
+ pk-column-value="EMP"
+ allocation-size="20"/>
+
+// et l'annotation équivalente
+
+ at 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"/>
+
+// et l'annotation équivalente
+
+ at javax.persistence.SequenceGenerator(
+ name="SEQ_GEN",
+ sequenceName="my_sequence",
+ allocationSize=20
+)
+ </programlisting>
+
+ <para>Si JPA XML (comme <filename>META-INF/orm.xml</filename>) est utilisé
+ pour définir les générateurs, <literal>EMP_GEN</literal> et
+ <literal>SEQ_GEN</literal> sont des générateurs de niveau applicatif.
+ <literal>EMP_GEN</literal> définit un générateur d'identifiant basé sur
+ une table utilisant l'algorithme hilo avec un <literal>max_lo</literal> de
+ 20. La valeur haute est conservée dans une <literal>table</literal>
+ "<literal>GENERATOR_TABLE</literal>". L'information est gardée dans une
+ ligne où la colonne <literal>pkColumnName</literal> ("clef") est égale à
+ <literal>pkColumnValue</literal> "<literal>EMP</literal>" et une colonne
+ <literal>valueColumnName</literal> "<literal>hi</literal>" contient la
+ prochaine valeur haute utilisée.</para>
+
+ <para><literal>SEQ_GEN</literal> définit un générateur par séquence
+ utilisant une séquence nommée <literal>my_sequence</literal>. La taille
+ d'allocation utilisée pour cet algorithme hilo basé sur une séquence est
+ 20. Notez que cette version d'Hibernate Annotations ne gère pas
+ <literal>initialValue</literal> dans le générateur par séquence.
+ La taille par défaut de l'allocation est 50, donc si vous voulez utiliser
+ une séquence et récupérer la valeur chaque fois, vous devez positionner
+ la taille de l'allocation à 1.</para>
+
+ <note>
+ <para>La définition au niveau package n'est plus prise en charge par la
+ spécification EJB 3.0. Vous pouvez cependant utiliser
+ <literal>@GenericGenerator</literal> au niveau du package (voir <xref
+ linkend="entity-hibspec-identifier" />).</para>
+ </note>
+
+ <para>Le prochain exemple montre la définition d'un générateur par
+ séquence dans la portée d'une classe :</para>
+
+ <programlisting>
+ at Entity
+ at javax.persistence.SequenceGenerator(
+ name="SEQ_STORE",
+ sequenceName="my_sequence"
+)
+public class Store implements Serializable {
+ private Long id;
+
+ @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE")
+ public Long getId() { return id; }
+}
+ </programlisting>
+
+ <para>Cette classe utilisera une séquence nommée my_sequence et le
+ générateur SEQ_STORE n'est pas visible dans les autres classes. Notez que
+ vous pouvez regarder les tests unitaires d'Hibernate Annotations dans le
+ package org.hibernate.test.metadata.id pour plus d'exemples.</para>
+
+ <para>Vous pouvez définir une clef primaire composée à travers différentes
+ syntaxes :</para>
+
+ <itemizedlist>
+ <listitem>
+ annote la propriété du composant comme @Id et rend la classe du
+ composant @Embeddable
+ </listitem>
+
+ <listitem>
+ annote la propriété du composant comme @EmbeddedId
+ </listitem>
+
+ <listitem>
+ annote la classe comme @IdClass et annote chaque propriété de
+ l'entité impliquée dans la clef primaire avec @Id
+ </listitem>
+ </itemizedlist>
+
+ <para>Bien qu'assez commun pour le développeur EJB2,
+ <literal>@IdClass</literal> est probablement nouveau pour les utilisateurs
+ d'Hibernate. La classe de la clef primaire composée correspond aux
+ multiples champs ou propriétés de l'entité ; de plus, les noms des champs
+ ou propriétés de la clef primaire et ceux de l'entité doivent
+ correspondre ; et enfin, leur type doit être le même. Regardons un
+ exemple :</para>
+
+ <programlisting>@Entity
+<emphasis role="bold">@IdClass(FootballerPk.class)</emphasis>
+public class Footballer {
+ // partie de la clef
+ <emphasis role="bold">@Id</emphasis> public String getFirstname() {
+ return firstname;
+ }
+
+ public void setFirstname(String firstname) {
+ this.firstname = firstname;
+ }
+
+ // partie de la clef
+ <emphasis role="bold">@Id</emphasis> public String getLastname() {
+ return lastname;
+ }
+
+ public void setLastname(String lastname) {
+ this.lastname = lastname;
+ }
+
+ public String getClub() {
+ return club;
+ }
+
+ public void setClub(String club) {
+ this.club = club;
+ }
+
+ // implémentation appropriée de equals() et hashCode()
+}
+
+ at Embeddable
+public class FootballerPk implements Serializable {
+ // même nom et même type que dans Footballer
+ public String getFirstname() {
+ return firstname;
+ }
+
+ public void setFirstname(String firstname) {
+ this.firstname = firstname;
+ }
+
+ // même nom et même type que dans Footballer
+ public String getLastname() {
+ return lastname;
+ }
+
+ public void setLastname(String lastname) {
+ this.lastname = lastname;
+ }
+
+ // implémentation appropriée de equals() et hashCode()
+}
+</programlisting>
+
+ <para>Comme vous pouvez le voir, <literal>@IdClass</literal> pointe vers
+ la classe de la clef primaire correspondante.</para>
+
+ <para>Bien que ce ne soit pas pris en charge par la spécification EJB3,
+ Hibernate vous permet de définir des associations à l'intérieur d'un
+ identifiant composé. Pour cela, utilisez simplement les annotations
+ habituelles.</para>
+
+ <programlisting>@Entity
+ at AssociationOverride( name="id.channel", joinColumns = @JoinColumn(name="chan_id") )
+public class TvMagazin {
+ @EmbeddedId public TvMagazinPk id;
+ @Temporal(TemporalType.TIME) Date time;
+}
+
+ at Embeddable
+public class TvMagazinPk implements Serializable {
+ @ManyToOne
+ public Channel channel;
+ public String name;
+ @ManyToOne
+ public Presenter presenter;
+}
+</programlisting>
+ </sect2>
+
+ <sect2>
+ <title>Mapper l'héritage</title>
+
+ <para>EJB3 prend en charge les trois types d'héritage :</para>
+
+ <itemizedlist>
+ <listitem>
+ Stratégie d'une table par classe concrète : l'élément
+ <union-class> dans Hibernate
+ </listitem>
+
+ <listitem>
+ Stratégie d'une seule table par hiérarchie de classe : l'élément
+ <subclass> dans Hibernate
+ </listitem>
+
+ <listitem>
+ Stratégie d'une table par classe fille : l'élément
+ <joined-subclass> dans Hibernate
+ </listitem>
+ </itemizedlist>
+
+ <para>La stratégie choisie est déclarée au niveau de la classe de l'entité
+ la plus haute dans la hiérarhie en utilisant l'annotation
+ <literal>@Inheritance</literal>.</para>
+
+ <note>
+ <para>Annoter des interfaces n'est pour le moment pas pris en
+ charge.</para>
+ </note>
+
+ <sect3>
+ <title>Une table par classe concrète</title>
+
+ <para>Cette stratégie a beaucoup d'inconvénients (surtout avec les
+ requêtes polymorphiques et les associations) expliqués dans la
+ spécification EJB3, la documentation de référence d'Hibernate, Hibernate
+ in Action, et plusieurs autres endroits. Hibernate en contourne la
+ plupart en implémentant cette stratégie en utilisant des requêtes
+ <literal>SQL UNION</literal>. Elle est habituellement utilisée pour le
+ niveau le plus haut d'une hiérarchie d'héritage :</para>
+
+ <programlisting>
+ at Entity
+ at Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
+public class Flight implements Serializable {
+ </programlisting>
+
+ <para>Cette stratégie prend en charge les associations de un vers
+ plusieurs bidirectionnelles. Cette stratégie ne prend pas en charge
+ la stratégie de générateur <literal>IDENTITY</literal> : l'identifiant
+ doit être partagé par plusieurs tables. Par conséquent, lors de
+ l'utilisation de cette stratégie, vous ne devriez pas utilisez
+ <literal>AUTO</literal> ni <literal>IDENTITY</literal>.</para>
+ </sect3>
+
+ <sect3>
+ <title>Une seule table par hiérarchie de classe</title>
+
+ <para>Toutes les propriétés de toutes les classes parentes et classes
+ filles sont mappées dans la même table, les instances sont différenciées
+ par une colonne spéciale discriminante :</para>
+
+ <programlisting>
+ at Entity
+ at Inheritance(strategy=InheritanceType.SINGLE_TABLE)
+ at DiscriminatorColumn(
+ name="planetype",
+ discriminatorType=DiscriminatorType.STRING
+)
+ at DiscriminatorValue("Plane")
+public class Plane { ... }
+
+ at Entity
+ at DiscriminatorValue("A320")
+public class A320 extends Plane { ... }
+ </programlisting>
+
+ <para><classname>Plane</classname> est la classe parente, elle définit
+ la stratégie d'héritage <literal>InheritanceType.SINGLE_TABLE</literal>.
+ Elle définit aussi la colonne discriminante avec l'annotation
+ <literal>@DiscriminatorColumn</literal>, une colonne discriminante peut
+ aussi définir le type du discriminant. Finalement, l'annotation
+ <literal>@DiscriminatorValue</literal> définit la valeur utilisée pour
+ différencier une classe dans la hiérarchie. Tous ces attributs ont des
+ valeurs par défaut sensées. Le nom par défaut de la colonne
+ discriminante est <literal>DTYPE</literal>. La valeur discriminante par
+ défaut est le nom de l'entité (comme défini dans
+ <literal>@Entity.name</literal>) avec le type
+ <literal>DiscriminatorType.STRING</literal>. <classname>A320</classname>
+ est une classe fille ; vous devez seulement définir la valeur
+ discriminante si vous ne voulez pas utiliser la valeur par défaut. La
+ stratégie et le type du discriminant sont implicites.</para>
+
+ <para><literal>@Inheritance</literal> et
+ <literal>@DiscriminatorColumn</literal> devraient seulement être
+ définies sur l'entité la plus haute de la hiérarchie.</para>
+ </sect3>
+
+ <sect3>
+ <title>Une table par classe fille</title>
+
+ <para>Les annotations <literal> @PrimaryKeyJoinColumn</literal> et
+ <literal>@PrimaryKeyJoinColumns</literal> définissent la (les) clef(s)
+ primaire(s) de la table de la classe fille jointe :</para>
+
+ <programlisting>
+ at Entity
+ at Inheritance(strategy=InheritanceType.JOINED)
+public class Boat implements Serializable { ... }
+
+ at Entity
+public class Ferry extends Boat { ... }
+
+ at Entity
+ at PrimaryKeyJoinColumn(name="BOAT_ID")
+public class AmericaCupClass extends Boat { ... }
+ </programlisting>
+
+ <para>Toutes les entités ci-dessus utilisent la stratégie
+ <literal>JOINED</literal>, la table <literal>Ferry</literal> est jointe
+ avec la table <literal>Boat</literal> en utilisant les mêmes noms de
+ clef primaire. La table <literal>AmericaCupClass</literal> est jointe
+ avec <literal>Boat</literal> en utilisant la condition de jointure
+ <code>Boat.id = AmericaCupClass.BOAT_ID</code>.</para>
+ </sect3>
+
+ <sect3>
+ <title>Héritage de propriétés des classes parentes</title>
+
+ <para>Il est parfois utile de partager des propriétés communes à travers
+ une classe technique ou métier sans l'inclure comme une entité
+ habituelle (c'est-à-dire aucune table spécifique pour cette entité).
+ Pour cela, vous pouvez les mapper comme
+ <literal>@MappedSuperclass</literal>.</para>
+
+ <programlisting>@MappedSuperclass
+public class BaseEntity {
+ @Basic
+ @Temporal(TemporalType.TIMESTAMP)
+ public Date getLastUpdate() { ... }
+ public String getLastUpdater() { ... }
+ ...
+}
+
+ at Entity class Order extends BaseEntity {
+ @Id public Integer getId() { ... }
+ ...
+}</programlisting>
+
+ <para>En base de données, cette hiérarchie sera représentée comme une
+ table <literal>Order</literal> ayant les colonnes <literal>id</literal>,
+ <literal>lastUpdate</literal> et <literal>lastUpdater</literal>.
+ Les mappings de propriété de la classe parente embarquée sont copiés
+ dans les classes filles de l'entité. Souvenez-vous que la classe parente
+ embarquable n'est cependant pas la racine de la hiérarchie.</para>
+
+ <note>
+ <para>Les propriétés des classes parentes non mappées comme
+ <literal>@MappedSuperclass</literal> sont ignorées.</para>
+ </note>
+
+ <note>
+ <para>Le type d'accès (champ ou méthode) est hérité de l'entité
+ racine, à moins que vous utilisiez l'annotation Hibernate
+ <literal>@AccessType</literal>.</para>
+ </note>
+
+ <note>
+ <para>La même notion peut être appliquée aux objets
+ <literal>@Embeddable</literal> pour persister des propriétés de leurs
+ classes parentes. Vous avez aussi besoin d'utiliser
+ <literal>@MappedSuperclass</literal> pour faire ça (cependant cela ne
+ devrait pas être considéré comme une fonctionnalité EJB3
+ standard).</para>
+ </note>
+
+ <note>
+ <para>Il est permis de marquer une classe comme
+ <literal>@MappedSuperclass</literal> dans le milieu d'une hiérarchie
+ d'héritage mappée.</para>
+ </note>
+
+ <note>
+ <para>Toute classe de la hiérarchie non annotée avec
+ <literal>@MappedSuperclass</literal> ou <literal>@Entity</literal>
+ sera ignorée.</para>
+ </note>
+
+ <para>Vous pouvez surcharger des colonnes définies dans des entités
+ parentes au niveau de l'entité racine en utilisant l'annotation
+ <literal>@AttributeOverride</literal>.</para>
+
+ <programlisting>@MappedSuperclass
+public class FlyingObject implements Serializable {
+
+ public int getAltitude() {
+ return altitude;
+ }
+
+ @Transient
+ public int getMetricAltitude() {
+ return metricAltitude;
+ }
+
+ @ManyToOne
+ public PropulsionType getPropulsion() {
+ return metricAltitude;
+ }
+ ...
+}
+
+ at Entity
+ at AttributeOverride( name="altitude", column = @Column(name="fld_altitude") )
+ at AssociationOverride( name="propulsion", joinColumns = @JoinColumn(name="fld_propulsion_fk") )
+public class Plane extends FlyingObject {
+ ...
+}</programlisting>
+
+ <para>La propriété <literal>altitude</literal> sera persistée dans la
+ colonne <literal>fld_altitude</literal> de la table
+ <literal>Plane</literal> et l'association <literal>propulsion</literal>
+ sera matérialisée dans la colonne de clef étrangère
+ <literal>fld_propulsion_fk</literal>.</para>
+
+ <para>Vous pouvez définir <literal>@AttributeOverride</literal>(s) et
+ <literal>@AssociationOverride</literal>(s) sur des classes
+ <literal>@Entity</literal>, des classes
+ <literal>@MappedSuperclass</literal> et des propriétés pointant vers un
+ objet <literal>@Embeddable</literal>.</para>
+ </sect3>
+ </sect2>
+
+ <sect2 id="entity-mapping-association">
+ <title>Mapper des associations/relations d'entity beans</title>
+
+ <sect3>
+ <title>One-to-one</title>
+
+ <para>Vous pouvez associer des entity beans avec une relation one-to-one
+ en utilisant <literal>@OneToOne</literal>. Il y a trois cas pour les
+ associations one-to-one : soit les entités associées partagent les mêmes
+ valeurs de clef primaire, soit une clef étrangère est détenue par une
+ des entités (notez que cette colonne de clef étrangère dans la base de
+ données devrait être avoir une contrainte d'unicité pour simuler la
+ cardinalité one-to-one), soit une table d'association est utilisée pour
+ stocker le lien entre les 2 entités (une contrainte d'unicité doit être
+ définie sur chaque clef étrangère pour assurer la cardinalité un à
+ un).</para>
+
+ <para>Tout d'abord, nous mappons une véritable association one-to-one en
+ utilisant des clefs primaires partagées :</para>
+
+ <programlisting>
+ at Entity
+public class Body {
+ @Id
+ public Long getId() { return id; }
+
+ @OneToOne(cascade = CascadeType.ALL)
+ @PrimaryKeyJoinColumn
+ public Heart getHeart() {
+ return heart;
+ }
+ ...
+}
+ </programlisting>
+
+ <programlisting>
+ at Entity
+public class Heart {
+ @Id
+ public Long getId() { ...}
+}
+ </programlisting>
+
+ <para>L'association un à un est activée en utilisant l'annotation
+ <literal>@PrimaryKeyJoinColumn</literal>.</para>
+
+ <para>Dans l'exemple suivant, les entités associées sont liées à travers
+ une clef étrangère :</para>
+
+ <programlisting>
+ at Entity
+public class Customer implements Serializable {
+ @OneToOne(cascade = CascadeType.ALL)
+ <emphasis role="bold">@JoinColumn(name="passport_fk")</emphasis>
+ public Passport getPassport() {
+ ...
+ }
+
+ at Entity
+public class Passport implements Serializable {
+ @OneToOne(<emphasis role="bold">mappedBy = "passport"</emphasis>)
+ public Customer getOwner() {
+ ...
+}
+ </programlisting>
+
+ <para>Un <classname>Customer</classname> est lié à un
+ <classname>Passport</classname>, avec une colonne de clef étrangère
+ nommée <literal>passport_fk</literal> dans la table
+ <literal>Customer</literal>. La colonne de jointure est déclarée avec
+ l'annotation <literal>@JoinColumn</literal> qui ressemble à l'annotation
+ <literal>@Column</literal>. Elle a un paramètre de plus nommé
+ <literal>referencedColumnName</literal>. Ce paramètre déclare la colonne
+ dans l'entité cible qui sera utilisée pour la jointure. Notez que lors
+ de l'utilisation de <literal>referencedColumnName</literal> vers une
+ colonne qui ne fait pas partie de la clef primaire, la classe associée
+ doit être <classname>Serializable</classname>. Notez aussi que
+ <literal>referencedColumnName</literal> doit être mappé sur une
+ propriété ayant une seule colonne lorsqu'elle pointe vers une colonne
+ qui ne fait pas partie de la clef primaire (d'autres cas pourraient ne
+ pas fonctionnner).</para>
+
+ <para>L'association peut être bidirectionnelle. Dans une relation
+ bidirectionnelle, une des extrémités (et seulement une) doit être la
+ propriétaire : la propriétaire est responsable de la mise à jour des
+ colonnes de l'association. Pour déclarer une extrémité comme
+ <emphasis>non</emphasis> responsable de la relation, l'attribut
+ <literal>mappedBy</literal> est utilisé.
+ <literal>mappedBy</literal> référence le nom de la propriété de
+ l'association du côté du propriétaire. Dans notre cas, c'est
+ <literal>passport</literal>. Comme vous pouvez le voir, vous ne devez
+ (absolument) pas déclarer la colonne de jointure puisqu'elle a déjà été
+ déclarée du côté du propriétaire.</para>
+
+ <para>Si aucune <literal>@JoinColumn</literal> n'est déclarée du côté du
+ propriétaire, les valeurs par défaut s'appliquent. Une(des) colonne(s)
+ de jointure sera(ont) créée(s) dans la table propriétaire, et son(leur)
+ nom sera la concaténation du nom de la relation du côté propriétaire,
+ <keycap>_</keycap> (underscore), et le nom de la (des) colonne(s) de la
+ clef primaire du propriétaire. Dans cet exemple
+ <literal>passport_id</literal> parce que le nom de la propriété est
+ <literal>passport</literal> et la colonne identifiante de
+ <literal>Passport</literal> est <literal>id</literal>.</para>
+
+ <para>La troisième possibilité (utilisant une table d'association) est
+ très exotique.</para>
+
+ <programlisting>
+ at Entity
+public class Customer implements Serializable {
+ @OneToOne(cascade = CascadeType.ALL)
+ <emphasis role="bold">@JoinTable(name = "CustomerPassports"
+ joinColumns = @JoinColumn(name="customer_fk"),
+ inverseJoinColumns = @JoinColumns(name="passport_fk")</emphasis>
+ )
+ public Passport getPassport() {
+ ...
+ }
+
+ at Entity
+public class Passport implements Serializable {
+ @OneToOne(<emphasis role="bold">mappedBy = "passport"</emphasis>)
+ public Customer getOwner() {
+ ...
+}
+ </programlisting>
+
+ <para>Un <classname>Customer</classname> est lié à un
+ <classname>Passport</classname> à travers une table d'association
+ nommée <literal>CustomerPassports</literal> ; cette table d'association
+ a une colonne de clef étrangère nommée <literal>passport_fk</literal>
+ pointant vers la table <literal>Passport</literal> (matérialisée par
+ l'attribut <literal>inverseJoinColumn</literal>), et une colonne de clef
+ étrangère nommée <literal>customer_fk</literal> pointant vers la table
+ <literal>Customer</literal> (matérialisée par l'attribut
+ <literal>joinColumns</literal>).</para>
+
+ <para>Vous devez déclarer le nom de la table de jointure et les colonnes
+ de jointure explicitement dans un tel mapping.</para>
+ </sect3>
+
+ <sect3>
+ <title>Many-to-one</title>
+
+ <para>Les associations Many-to-one sont déclarées au niveau de la
+ propriété avec l'annotation <literal>@ManyToOne</literal> :</para>
+
+ <programlisting>
+ at Entity()
+public class Flight implements Serializable {
+ <emphasis role="bold">@ManyToOne</emphasis>( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
+ @JoinColumn(name="COMP_ID")
+ public Company getCompany() {
+ return company;
+ }
+ ...
+}
+ </programlisting>
+
+ <para>L'attribut <literal>@JoinColumn</literal> est optionnel, la valeur
+ par défaut est comme l'association un à un, la concaténation du nom
+ de la relation du côté propriétaire, <keycap>_</keycap>
+ (underscore), et le nom de la colonne de la clef primaire du côté
+ propriétaire. Dans cet exemple, <literal>company_id</literal> parce que
+ le nom de la propriété est <literal>company</literal> et la colonne
+ identifiante de Company est <literal>id</literal>.</para>
+
+ <para><literal>@ManyToOne</literal> a un paramètre nommé
+ <literal>targetEntity</literal> qui décrit le nom de l'entité cible.
+ Généralement, vous ne devriez pas avoir besoin de ce paramètre puisque
+ la valeur par défaut (le type de la propriété qui stocke l'association)
+ est correcte dans la plupart des cas. Il est cependant utile lorsque
+ vous souhaitez retourner une interface plutôt qu'une entité
+ normale.</para>
+
+ <programlisting>
+ at Entity()
+public class Flight implements Serializable {
+ @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE}, <emphasis
+ role="bold">targetEntity=CompanyImpl.class</emphasis> )
+ @JoinColumn(name="COMP_ID")
+ public Company getCompany() {
+ return company;
+ }
+ ...
+}
+
+public interface Company {
+ ...
+ </programlisting>
+
+ <para>Vous pouvez sinon mapper une association plusieurs à un avec une
+ table d'association. Cette association décrite par l'annotation
+ <literal>@JoinTable</literal> contiendra une clef étrangère référençant
+ la table de l'entité (avec
+ <literal>@JoinTable.joinColumns</literal>) et une clef étrangère
+ référençant la table de l'entité cible (avec
+ <literal>@JoinTable.inverseJoinColumns</literal>).</para>
+
+ <programlisting>
+ at Entity()
+public class Flight implements Serializable {
+ @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
+ <emphasis role="bold">@JoinTable(name="Flight_Company",
+ joinColumns = @JoinColumn(name="FLIGHT_ID"),
+ inverseJoinColumns = @JoinColumns(name="COMP_ID")
+ )</emphasis>
+ public Company getCompany() {
+ return company;
+ }
+ ...
+}
+ </programlisting>
+ </sect3>
+
+ <sect3 id="entity-mapping-association-collections">
+ <title>Collections</title>
+
+ <sect4 id="entity-mapping-association-collections-overview"
+ revision="1">
+ <title>Vue d'ensemble</title>
+
+ <para>Vous pouvez mapper des <classname>Collection</classname>s, des
+ <literal>List</literal>s (ie des listes ordonnées, pas des listes
+ indexées), des <literal>Map</literal>s et des
+ <classname>Set</classname>s. La spécification EJB3 décrit comment
+ mapper une liste ordonnée (ie une liste ordonnée au chargement) en
+ utilisant l'annotation <literal>@javax.persistence.OrderBy</literal> :
+ pour ordonner la collection, cette annotation prend en paramètre une
+ liste de propriétés (de l'entité cible) séparées par des virgules
+ (p. ex. <code>firstname asc, age desc</code>) ; si la chaîne de
+ caractères est vide, la collection sera ordonnée par les identifiants.
+ Pour le moment <literal>@OrderBy</literal> fonctionne seulement sur
+ des collections n'ayant pas de table d'association. Pour les
+ véritables collections indexées, veuillez vous référer à
+ <xref linkend="entity-hibspec" />. EJB3 vous permet de mapper des
+ <literal>Map</literal>s en utilisant comme clef une des propriétés de
+ l'entité cible avec <literal>@MapKey(name="myProperty")</literal>
+ (myProperty est un nom de propriété de l'entité cible). Lorsque vous
+ utilisez <literal>@MapKey</literal> sans nom de propriété, la clef
+ primaire de l'entité cible est utilisée. La clef de la map utilise la
+ même colonne que celle pointée par la propriété : il n'y a pas de
+ colonne supplémentaire définie pour la clef de la map, et c'est normal
+ puisque la clef de la map représente en fait un propriété de la cible.
+ Faites attention qu'une fois chargée, la clef n'est plus synchronisée
+ avec la propriété, en d'autres mots, si vous modifiez la valeur de la
+ propriété, la clef ne sera pas changée automatiquement dans votre
+ modèle Java (pour une véritable prise en charge des maps veuillez vous
+ référer à <xref linkend="entity-hibspec" />). Beaucoup de gens
+ confondent les capacités de <literal><map></literal> et celles
+ de <literal>@MapKey</literal>. Ce sont deux fonctionnalités
+ différentes. <literal>@MapKey</literal> a encore quelques limitations,
+ veuillez vous référer au forum ou au système de suivi de bogues JIRA
+ pour plus d'informations.</para>
+
+ <para>Hibernate a plusieurs notions de collections.</para>
+
+ <para></para>
+
+ <table>
+ <title>Sémantique des collections</title>
+
+ <tgroup cols="3">
+ <colspec colname="c1" />
+
+ <colspec colname="c2" />
+
+ <colspec colname="c3" colnum="2" />
+
+ <thead>
+ <row>
+ <entry>Sémantique</entry>
+
+ <entry>Représentation Java</entry>
+
+ <entry>Annotations</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>Sémantique de Bag</entry>
+
+ <entry>java.util.List, java.util.Collection</entry>
+
+ <entry>@org.hibernate.annotations.CollectionOfElements ou
+ @OneToMany ou @ManyToMany</entry>
+ </row>
+
+ <row>
+ <entry>Sémantique de Bag avec une clef primaire (sans les
+ limitations de la sémantique de Bag)</entry>
+
+ <entry>java.util.List, java.util.Collection</entry>
+
+ <entry>(@org.hibernate.annotations.CollectionOfElements ou
+ @OneToMany ou @ManyToMany) et @CollectionId</entry>
+ </row>
+
+ <row>
+ <entry>Sémantique de List</entry>
+
+ <entry>java.util.List</entry>
+
+ <entry>(@org.hibernate.annotations.CollectionOfElements ou
+ @OneToMany ou @ManyToMany) et
+ @org.hibernate.annotations.IndexColumn</entry>
+ </row>
+
+ <row>
+ <entry>Sémantique de Set</entry>
+
+ <entry>java.util.Set</entry>
+
+ <entry>@org.hibernate.annotations.CollectionOfElements ou
+ @OneToMany ou @ManyToMany</entry>
+ </row>
+
+ <row>
+ <entry>Sémantique de Map</entry>
+
+ <entry>java.util.Map</entry>
+
+ <entry>(@org.hibernate.annotations.CollectionOfElements ou
+ @OneToMany ou @ManyToMany) et (rien ou
+ @org.hibernate.annotations.MapKey/MapKeyManyToMany pour une
+ véritable prise en charge des maps, ou
+ @javax.persistence.MapKey</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <remark>Donc spécifiquement, les collections java.util.List sans
+ @org.hibernate.annotations.IndexColumn vont être considérées commes
+ des bags.</remark>
+
+ <para>Les collections de types primitifs, de types core ou d'objets
+ embarqués ne sont pas prises en charge par la spécification EJB3.
+ Cependant Hibernate Annotations les autorise
+ (voir <xref linkend="entity-hibspec" />).</para>
+
+ <programlisting>@Entity public class City {
+ @OneToMany(mappedBy="city")
+ <emphasis role="bold">@OrderBy("streetName")</emphasis>
+ public List<Street> getStreets() {
+ return streets;
+ }
+...
+}
+
+ at Entity public class Street {
+ <emphasis role="bold">public String getStreetName()</emphasis> {
+ return streetName;
+ }
+
+ @ManyToOne
+ public City getCity() {
+ return city;
+ }
+ ...
+}
+
+
+ at Entity
+public class Software {
+ @OneToMany(mappedBy="software")
+ <emphasis role="bold">@MapKey(name="codeName")</emphasis>
+ public Map<String, Version> getVersions() {
+ return versions;
+ }
+...
+}
+
+ at Entity
+ at Table(name="tbl_version")
+public class Version {
+ <emphasis role="bold">public String getCodeName()</emphasis> {...}
+
+ @ManyToOne
+ public Software getSoftware() { ... }
+...
+}</programlisting>
+
+ <para>Donc <literal>City</literal> a une collection de
+ <literal>Street</literal>s qui sont ordonnées par
+ <literal>streetName</literal> (de <literal>Street</literal>) lorsque
+ la collection est chargée. <literal>Software</literal> a une map de
+ <literal>Version</literal>s dont la clef est
+ <literal>codeName</literal> de <literal>Version</literal>.</para>
+
+ <para>A moins que la collection soit une "generic", vous devrez
+ définir <literal>targetEntity</literal>. C'est un attribut de
+ l'annotation qui prend comme valeur la classe de l'entité
+ cible.</para>
+ </sect4>
+
+ <sect4 id="entity-mapping-association-collection-onetomany"
+ revision="2">
+ <title>One-to-many</title>
+
+ <para>Les associations one-to-many sont déclarées au niveau propriété
+ avec l'annotation <literal>@OneToMany</literal>. Les associations un
+ à plusieurs peuvent être bidirectionnelles.</para>
+
+ <sect5>
+ <title>Relation bidirectionnelle</title>
+
+ <para>Puisque les associations plusieurs à un sont (presque)
+ toujours l'extrémité propriétaire de la relation bidirectionnelle
+ dans la spécification EJB3, l'association un à plusieurs est
+ annotée par <literal>@OneToMany(mappedBy=...)</literal>.</para>
+
+ <programlisting>@Entity
+public class Troop {
+ @OneToMany(mappedBy="troop")
+ public Set<Soldier> getSoldiers() {
+ ...
+}
+
+ at Entity
+public class Soldier {
+ @ManyToOne
+ @JoinColumn(name="troop_fk")
+ public Troop getTroop() {
+ ...
+} </programlisting>
+
+ <para><classname>Troop</classname> a une relation bidirectionnelle
+ un à plusieurs avec <literal>Soldier</literal> à travers la
+ propriété <literal>troop</literal>. Vous ne devez pas définir
+ de mapping physique à l'extrémité de
+ <literal>mappedBy</literal>.</para>
+
+ <para>Pour mapper une relation bidirectionnelle un à plusieurs, avec
+ l'extrémité one-to-many comme extrémité propriétaire, vous devez
+ enlever l'élément <literal>mappedBy</literal> et marquer
+ l'annotation <literal>@JoinColumn</literal> de l'extrémité plusieurs
+ à un comme ne pouvant pas être insérée et ni mise à jour. Cette
+ solution n'est certainement pas optimisée et produira quelques
+ commandes UPDATE supplémentaires.</para>
+
+ <programlisting>@Entity
+public class Troop {
+ @OneToMany
+ @JoinColumn(name="troop_fk") // nous avons besoin de dupliquer l'information physique
+ public Set<Soldier> getSoldiers() {
+ ...
+}
+
+ at Entity
+public class Soldier {
+ @ManyToOne
+ @JoinColumn(name="troop_fk", insertable=false, updatable=false)
+ public Troop getTroop() {
+ ...
+}</programlisting>
+ </sect5>
+
+ <sect5>
+ <title>Relation unidirectionnelle</title>
+
+ <para>Une relation un à plusieurs unidirectionnelle utilisant une
+ colonne de clef étrangère de l'entité propriétaire n'est pas si
+ commune, réellement recommandée. Nous vous conseillons
+ fortement d'utiliser une table de jointure pour cette sorte
+ d'association (comme expliqué dans la prochaine section). Cette
+ sorte d'association est décrite à travers
+ <literal>@JoinColumn</literal>.</para>
+
+ <programlisting>
+ at Entity
+public class Customer implements Serializable {
+ @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
+ @JoinColumn(name="CUST_ID")
+ public Set<Ticket> getTickets() {
+ ...
+}
+
+ at Entity
+public class Ticket implements Serializable {
+ ... // pas de relation bidirectionnelle
+}
+ </programlisting>
+
+ <para><literal>Customer</literal> décrit une relation
+ unidirectionnelle avec <literal>Ticket</literal> en utilisant la
+ colonne de jointure <literal>CUST_ID</literal>.</para>
+ </sect5>
+
+ <sect5>
+ <title>Relation unidirectionnel avec une table de jointure</title>
+
+ <para>Une relation unidirectionnelle un à plusieurs avec une table
+ de jointure est largement préférée. Cette association est décrite
+ à travers l'annotation <literal>@JoinTable</literal>.</para>
+
+ <programlisting>
+ at Entity
+public class Trainer {
+ @OneToMany
+ @JoinTable(
+ name="TrainedMonkeys",
+ joinColumns = { @JoinColumn( name="trainer_id") },
+ inverseJoinColumns = @JoinColumn( name="monkey_id")
+ )
+ public Set<Monkey> getTrainedMonkeys() {
+ ...
+}
+
+ at Entity
+public class Monkey {
+ ... // pas de relation bidirectionnelle
+}
+ </programlisting>
+
+ <para><literal>Trainer</literal> décrit une relation
+ unidirectionelle avec <classname>Monkey</classname> en utilisant la
+ table de jointure <classname>TrainedMonkeys</classname>, avec une
+ clef étrangère <literal>trainer_id</literal> vers
+ <literal>Trainer</literal> (<literal>joinColumns</literal>) et une
+ clef étrangère <literal>monkey_id</literal> vers
+ <literal>Monkey</literal>
+ (<literal>inversejoinColumns</literal>).</para>
+ </sect5>
+
+ <sect5 id="entity-mapping-association-collection-manytomany-default"
+ revision="1">
+ <title>Valeurs par défaut</title>
+
+ <para>Si aucun mapping physique n'est déclaré, une relation
+ unidirectionnelle un vers plusieurs utilise une table de jointure.
+ Le nom de la table est la concaténation du nom de la table
+ propriétaire, <keycap>_</keycap>, et le nom de la table de l'autre
+ extrémité. Le nom des colonnes de la clef étrangère référençant la
+ table propriétaire est la concaténation de la table propriétaire,
+ <keycap>_</keycap>, et le nom des colonnes de la clef primaire. Le
+ nom des colonnes de la clef étrangère référençant l'autre extrémité
+ est la concaténation du nom de la propriété du propriétaire,
+ <keycap>_</keycap>, et le nom des colonnes de la clef primaire de
+ l'autre extrémité. Une contrainte d'unicité est ajoutée sur la
+ clef étrangère référençant la table de l'autre extrémité pour
+ réfléter le un à plusieurs.</para>
+
+ <programlisting>
+ at Entity
+public class Trainer {
+ @OneToMany
+ public Set<Tiger> getTrainedTigers() {
+ ...
+}
+
+ at Entity
+public class Tiger {
+ ... // non bidirectionnelle
+}
+ </programlisting>
+
+ <para><classname>Trainer</classname> décrit une relation
+ unidirectionnelle avec <classname>Tiger</classname> utilisant la
+ table de jointure <literal>Trainer_Tiger</literal>, avec une clef
+ étrangère <literal>trainer_id</literal> vers
+ <literal>Trainer</literal> (nom de la table, <keycap>_</keycap>,
+ identifiant de trainer) et une clef étrangère
+ <literal>trainedTigers_id</literal> vers <literal>Monkey</literal>
+ (nom de la propriété, <keycap>_</keycap>, colonne de la clef
+ primaire de Tiger).</para>
+ </sect5>
+ </sect4>
+
+ <sect4 id="eentity-mapping-association-collection-manytomany"
+ revision="">
+ <title>Many-to-many</title>
+
+ <sect5>
+ <title>Définition</title>
+
+ <para>Une association many-to-many est définie logiquement en
+ utilisant l'annotation <literal>@ManyToMany</literal>. Vous devez
+ aussi décrire la table d'association et les conditions de jointure
+ en utilisant l'annotation <literal>@JoinTable</literal>. Si
+ l'association est bidirectionnelle, une extrémité doit être la
+ propriétaire et l'autre doit être marquée comme "inverse" (ie
+ qu'elle sera ignorée lors de la mise à jour des valeurs de la
+ relation dans la table d'association) :</para>
+
+ <programlisting>
+ at Entity
+public class Employer implements Serializable {
+ @ManyToMany(
+ targetEntity=org.hibernate.test.metadata.manytomany.Employee.class,
+ cascade={CascadeType.PERSIST, CascadeType.MERGE}
+ )
+ @JoinTable(
+ name="EMPLOYER_EMPLOYEE",
+ joinColumns={@JoinColumn(name="EMPER_ID")},
+ inverseJoinColumns={@JoinColumn(name="EMPEE_ID")}
+ )
+ public Collection getEmployees() {
+ return employees;
+ }
+ ...
+}
+ </programlisting>
+
+ <programlisting>
+ at Entity
+public class Employee implements Serializable {
+ @ManyToMany(
+ cascade={CascadeType.PERSIST, CascadeType.MERGE},
+ mappedBy="employees"
+ targetEntity=Employer.class
+ )
+ public Collection getEmployers() {
+ return employers;
+ }
+}
+ </programlisting>
+
+ <para>Nous avons déjà montré les déclarations des relations
+ "many" et détaillé les attributs de ces associations. Allons
+ plus en profondeur dans la description de
+ <literal>@JoinTable</literal> ; elle définit un
+ <literal>name</literal>, un tableau de colonnes de jointure (un
+ tableau dans une annotation est défini par {A, B, C}), et un tableau
+ de colonnes de jointure inverse. Ces dernières sont les colonnes
+ de la table d'association qui référencent la clef primaire de
+ <classname>Employee</classname> ("l'autre extrémité").</para>
+
+ <para>Comme vu précédemment, l'autre extrémité ne doit pas décrire
+ le mapping physique : un simple argument
+ <literal>mappedBy</literal> contenant le nom de la propriété de
+ l'extrémité propriétaire suffit à relier les deux.</para>
+ </sect5>
+
+ <sect5>
+ <title>Valeurs par défaut</title>
+
+ <para>Comme d'autres annotations, la plupart des valeurs d'une
+ relation plusieurs à plusieurs sont inférées. Si aucun mapping
+ physique n'est décrit dans une relation plusieurs à plusieurs
+ unidirectionnelle, alors les règles suivantes s'appliquent. Le nom
+ de la table est la concaténation du nom de la table propriétaire,
+ <keycap>_</keycap> et le nom de la table de l'autre extrémité. Le
+ nom des colonnes de la clef étrangère référençant la table
+ propriétaire est la concaténation du nom de la table propriétaire,
+ <keycap>_</keycap> et le nom des colonnes de la clef primaire
+ de cette table. Le nom des colonnes de la clef étrangère référençant
+ l'autre extrémité est la concaténation du nom de la propriété du
+ propriétaire, <keycap>_</keycap> et le nom des colonnes de la
+ clef primaire de l'autre extrémité. Ce sont les mêmes règles que
+ celles utilisées pour une relation un à plusieurs
+ unidirectionnelle.</para>
+
+ <programlisting>
+ at Entity
+public class Store {
+ @ManyToMany(cascade = CascadeType.PERSIST)
+ public Set<City> getImplantedIn() {
+ ...
+ }
+}
+
+ at Entity
+public class City {
+ ... // pas de relation bidirectionnelle
+}
+ </programlisting>
+
+ <para>La table <literal>Store_City</literal> est utilisée comme
+ table de jointure. La colonne <literal>Store_id</literal> est
+ une clef étrangère vers la table <literal>Store</literal>. La
+ colonne <literal>implantedIn_id</literal> est une clef étrangère
+ vers la table <literal>City</literal>.</para>
+
+ <para>Si aucun mapping physique n'est décrit dans une relation
+ plusieurs à plusieurs bidirectionnelle, alors les règles suivantes
+ s'appliquent. Le nom de la table est la concaténation du nom de la
+ table propriétaire, <keycap>_</keycap> et le nom de la table de
+ l'autre extrémité. Le nom des colonnes de la clef étrangère
+ référençant la table propriétaire est la concaténation du nom de la
+ propriété de l'autre extrémité, <keycap>_</keycap> et le nom des
+ colonnes de la clef primaire du propriétaire. Le nom des colonnes de
+ la clef étrangère référençant l'autre extrémité est la concaténation
+ du nom de la propriété du propriétaire, <keycap>_</keycap> et le nom
+ des colonnes de la clef primaire de l'autre extrémité. Ce sont les
+ mêmes règles que celles utilisées pour une relation un à plusieurs
+ unidirectionnelle.</para>
+
+ <programlisting>
+ at Entity
+public class Store {
+ @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
+ public Set<Customer> getCustomers() {
+ ...
+ }
+}
+
+ at Entity
+public class Customer {
+ @ManyToMany(mappedBy="customers")
+ public Set<Store> getStores() {
+ ...
+ }
+}
+ </programlisting>
+
+ <para>La table <literal>Store_Customer</literal> est utilisée comme
+ table de jointure. La colonne <literal>stores_id</literal> est une
+ clef étrangère vers la table <literal>Store</literal>. La colonne
+ <literal>customers_id</literal> est une clef étrangère vers la table
+ <literal>Customer</literal>.</para>
+ </sect5>
+ </sect4>
+ </sect3>
+
+ <sect3>
+ <title>Persistance transitive avec les opérations en cascade</title>
+
+ <para>Vous avez probablement remarqué l'attribut
+ <literal>cascade</literal> prenant comme valeur un tableau de
+ <classname>CascadeType</classname>s. Le concept de cascade dans EJB3 est
+ similaire à la persistance transitive et les opérations en cascade dans
+ Hibernate, mais avec une sémantique légèrement différente et les types
+ de cascade suivants :</para>
+
+ <itemizedlist>
+ <listitem>
+ CascadeType.PERSIST : effectue en cascade l'opération de
+ persistance (création) sur les entités associées si persist() est
+ appelée ou si l'entité est supervisée (par le gestionnaire
+ d'entités)
+ </listitem>
+
+ <listitem>
+ CascadeType.MERGE : effectue en cascade l'opération de fusion sur
+ les entités associées si merge() est appélée ou si l'entité est
+ supervisée
+ </listitem>
+
+ <listitem>
+ CascadeType.REMOVE : effectue en cascade l'opération de
+ suppression sur les entités associées si delete() est appelée
+ </listitem>
+
+ <listitem>
+ CascadeType.REFRESH : effectue en cascade l'opération de
+ rafraîchissement sur les entités associées si refresh() est appelée
+ </listitem>
+
+ <listitem>
+ CascadeType.ALL : tous ceux du dessus
+ </listitem>
+ </itemizedlist>
+
+ <para>Veullez vous référer au chapitre 6.3 de la spécification EJB3 pour
+ plus d'informations sur les opérations en cascade et la sémantique des
+ opérations de création/fusion.</para>
+ </sect3>
+
+ <sect3>
+ <title>Récupération d'associations</title>
+
+ <para>Vous avez la possibilité de récupérer les entités associées soit
+ immédiatement ("eager"), soit à la demande ("lazy"). Le paramètre
+ <literal>fetch</literal> peut être positionné à
+ <literal>FetchType.LAZY</literal> ou à
+ <literal>FetchType.EAGER</literal>. <literal>EAGER</literal> essaiera
+ d'utiliser une jointure externe pour rappatrier l'objet associé,
+ alors que <literal>LAZY</literal> est la valeur par défaut et rapportera
+ les données lorsque l'objet associé sera accédé pour la première fois.
+ JPA-QL a aussi un mot clef <literal>fetch</literal> qui vous permet de
+ surcharger le type de récupération pour une requête particulière. C'est
+ très utile pour améliorer les performances et décider au cas par
+ cas.</para>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Mapper des clefs primaires et étrangères composées</title>
+
+ <para>Les clefs primaires composées utilisent une classe embarquée comme
+ représentation de la clef primaire, donc vous devriez utiliser les
+ annotations <literal>@Id</literal> et <literal>@Embeddable</literal>.
+ Alternativement, vous pouvez utiliser l'annotation
+ <literal>@EmbeddedId</literal>. Notez que la classe dépendante doit être
+ sérialisable et implementer
+ <methodname>equals()</methodname>/<methodname>hashCode()</methodname>.
+ Vous pouvez aussi utiliser <literal>@IdClass</literal> comme décrit dans
+ <xref linkend="entity-mapping-identifier" />.</para>
+
+ <programlisting>
+ at Entity
+public class RegionalArticle implements Serializable {
+
+ @Id
+ public RegionalArticlePk getPk() { ... }
+}
+
+ at Embeddable
+public class RegionalArticlePk implements Serializable { ... }
+ </programlisting>
+
+ <para>ou alternativement</para>
+
+ <programlisting>
+ at Entity
+public class RegionalArticle implements Serializable {
+
+ @EmbeddedId
+ public RegionalArticlePk getPk() { ... }
+}
+
+public class RegionalArticlePk implements Serializable { ... }
+ </programlisting>
+
+ <para><literal>@Embeddable</literal> hérite le type d'accès de son entité
+ d'appartenance à moins que l'annotation spécifique Hibernate
+ <literal>@AccessType</literal> soit utilisée. Les clefs étrangères
+ composées (si les valeurs par défaut ne sont pas utilisées) sont définies
+ sur les associations en utilisant l'élément
+ <literal>@JoinColumns</literal>, lequel est simplement un tableau de
+ <literal>@JoinColumn</literal>s. Il est considéré comme une bonne pratique
+ d'exprimer <literal>referencedColumnNames</literal> explicitement. Sinon,
+ Hibernate supposera que vous utilisez le même ordre de colonnes que dans
+ la déclaration de la clef primaire.</para>
+
+ <programlisting>
+ at Entity
+public class Parent implements Serializable {
+ @Id
+ public ParentPk id;
+ public int age;
+
+ @OneToMany(cascade=CascadeType.ALL)
+ @JoinColumns ({
+ @JoinColumn(name="parentCivility", referencedColumnName = "isMale"),
+ @JoinColumn(name="parentLastName", referencedColumnName = "lastName"),
+ @JoinColumn(name="parentFirstName", referencedColumnName = "firstName")
+ })
+ public Set<Child> children; //unidirectionnelle
+ ...
+}
+ </programlisting>
+
+ <programlisting>
+ at Entity
+public class Child implements Serializable {
+ @Id @GeneratedValue
+ public Integer id;
+
+ @ManyToOne
+ @JoinColumns ({
+ @JoinColumn(name="parentCivility", referencedColumnName = "isMale"),
+ @JoinColumn(name="parentLastName", referencedColumnName = "lastName"),
+ @JoinColumn(name="parentFirstName", referencedColumnName = "firstName")
+ })
+ public Parent parent; // unidirectionnelle
+}
+ </programlisting>
+
+ <programlisting>
+ at Embeddable
+public class ParentPk implements Serializable {
+ String firstName;
+ String lastName;
+ ...
+}
+ </programlisting>
+
+ <para>Notez l'usage explicite de
+ <literal>referencedColumnName</literal>.</para>
+ </sect2>
+
+ <sect2>
+ <title>Mapper des tables secondaires</title>
+
+ <para>Vous pouvez mapper un simple entity bean vers plusieurs tables en
+ utilisant les annotations de niveau classe
+ <literal>@SecondaryTable</literal> ou
+ <literal>@SecondaryTables</literal>. Pour dire qu'une colonne est dans
+ une table particulière, utlisez le paramètre <literal>table</literal> de
+ <literal>@Column</literal> ou <literal>@JoinColumn</literal>.</para>
+
+ <programlisting>
+ at Entity
+ at Table(name="MainCat")
+<emphasis role="bold">@SecondaryTables({
+ @SecondaryTable(name="Cat1", pkJoinColumns={
+ @PrimaryKeyJoinColumn(name="cat_id", referencedColumnName="id")
+ ),
+ @SecondaryTable(name="Cat2", uniqueConstraints={@UniqueConstraint(columnNames={"storyPart2"})})
+})</emphasis>
+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;
+ }
+
+ <emphasis role="bold">@Column(table="Cat1")</emphasis>
+ public String getStoryPart1() {
+ return storyPart1;
+ }
+
+ <emphasis role="bold">@Column(table="Cat2")</emphasis>
+ public String getStoryPart2() {
+ return storyPart2;
+ }
+</programlisting>
+
+ <para>Dans cet exemple, <literal>name</literal> sera dans
+ <literal>MainCat</literal>. <literal>storyPart1</literal> sera dans
+ <literal>Cat1</literal> et <literal>storyPart2</literal> sera dans
+ <literal>Cat2</literal>. <literal>Cat1</literal> sera joint à
+ <literal>MainCat</literal> avec <literal>cat_id</literal> comme clef
+ étrangère, et <literal>Cat2</literal> avec <literal>id</literal> (ie
+ le même nom de colonne que la colonne identifiante de
+ <literal>MainCat</literal>). De plus, une contrainte d'unicité sur
+ <literal>storyPart2</literal> a été renseignée.</para>
+
+ <para>Regardez le tutoriel EJB3 de JBoss ou la suite de tests
+ unitaires d'Hibernate Annotations pour plus d'exemples.</para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="entity-mapping-query">
+ <title>Mapper des requêtes</title>
+
+ <sect2 id="entity-mapping-query-hql"
+ revision="1">
+ <title>Mapper des requêtes JPAQL/HQL</title>
+
+ <para>Vous pouvez mapper des requêtes JPA-QL/HQL en utilisant les
+ annotations. <literal>@NamedQuery</literal> et
+ <literal>@NamedQueries</literal> peuvent être définies au niveau de la
+ classe ou dans un fichier JPA XML. Cependant, leurs définitions sont
+ globales au scope de la session factory/entity manager factory. Une
+ requête nommée est définie par son nom et la chaîne de caractères de la
+ requête réelle.</para>
+
+ <programlisting><entity-mappings>
+ <named-query name="plane.getAll">
+ <query>select p from Plane p</query>
+ </named-query>
+ ...
+</entity-mappings>
+...
+
+ at Entity
+ at NamedQuery(name="night.moreRecentThan", query="select n from Night n where n.date >= :date")
+public class Night {
+ ...
+}
+
+public class MyDao {
+ doStuff() {
+ Query q = s.getNamedQuery("night.moreRecentThan");
+ q.setDate( "date", aMonthAgo );
+ List results = q.list();
+ ...
+ }
+ ...
+}
+ </programlisting>
+
+ <para>Vous pouvez aussi fournir des indications de fonctionnement à une
+ requête à travers un tableau de <literal>QueryHint</literal>s avec
+ l'attribut <literal>hints</literal>.</para>
+
+ <para>Les indications de fonctionnement Hibernate disponibles
+ sont :</para>
+
+ <para></para>
+
+ <table>
+ <title>Indications de fonctionnement d'une requête</title>
+
+ <tgroup cols="2">
+ <thead>
+ <colspec colname="c1" />
+
+ <colspec colname="c2" colnum="2" />
+
+ <row>
+ <entry>Indication</entry>
+
+ <entry colname="c2">description</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>org.hibernate.cacheable</entry>
+
+ <entry>Indique si la requête devrait interagir avec le cache de
+ second niveau (par défaut à false)</entry>
+ </row>
+
+ <row>
+ <entry>org.hibernate.cacheRegion</entry>
+
+ <entry>Nom de la région du cache (si indéfinie, la valeur par
+ défaut est utilisée)</entry>
+ </row>
+
+ <row>
+ <entry>org.hibernate.timeout</entry>
+
+ <entry>Timeout des requêtes</entry>
+ </row>
+
+ <row>
+ <entry>org.hibernate.fetchSize</entry>
+
+ <entry>Taille des result sets par fetch</entry>
+ </row>
+
+ <row>
+ <entry>org.hibernate.flushMode</entry>
+
+ <entry>Mode de flush utilisé pour cette requête</entry>
+ </row>
+
+ <row>
+ <entry>org.hibernate.cacheMode</entry>
+
+ <entry>Mode de cache utilisé pour cette requête</entry>
+ </row>
+
+ <row>
+ <entry>org.hibernate.readOnly</entry>
+
+ <entry>Indique si les entités chargées par cette requête devraient
+ être en lecture seule ou pas (par défaut à false)</entry>
+ </row>
+
+ <row>
+ <entry>org.hibernate.comment</entry>
+
+ <entry>Commentaire de la requête, ajouté au SQL généré</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </sect2>
+
+ <sect2 id="entity-mapping-query-native" revision="2">
+ <title>Mapper des requêtes natives</title>
+
+ <para>Vous pouvez aussi mapper une requête native (ie une requête SQL).
+ Pour ce faire, vous devez décrire la structure de l'ensemble de résultat
+ SQL en utilisant <literal>@SqlResultSetMapping</literal> (ou
+ <literal>@SqlResultSetMappings</literal> si vous prévoyez de définir
+ plusieurs mappings de résultats). Comme <literal>@NamedQuery</literal>, un
+ <literal>@SqlResultSetMapping</literal> peut être défini au niveau de la
+ classe ou dans un fichier XML JPA. Cependant sa portée est globale à
+ l'application.</para>
+
+ <para>Comme vous le verrez, un paramètre de
+ <literal>resultSetMapping</literal> est défini dans
+ <literal>@NamedNativeQuery</literal>, il représente le nom du
+ <literal>@SqlResultSetMapping</literal> défini. Le mapping de l'ensemble
+ des résultats déclare les entités récupérées par cette requête native.
+ Chaque champ de l'entité est lié à un alias SQL (nom de colonne). Tous les
+ champs de l'entité (dont ceux des classes filles) et les colonnes des
+ clefs étrangères relatives aux entités doivent être présents dans la
+ requête SQL. Les définitions des champs sont optionnelles, si elles ne
+ sont pas fournies, elles mappent le même nom de colonne que celui déclaré
+ sur la propriété de la classe.</para>
+
+ <para><programlisting>@NamedNativeQuery(name="night&area", query="select night.id nid, night.night_duration, "
+ + " night.night_date, area.id aid, night.area_id, area.name "
+ + "from Night night, Area area where night.area_id = area.id", <emphasis
+ role="bold">resultSetMapping="joinMapping"</emphasis>)
+ at SqlResultSetMapping(name="joinMapping", entities={
+ @EntityResult(entityClass=org.hibernate.test.annotations.query.Night.class, fields = {
+ @FieldResult(name="id", column="nid"),
+ @FieldResult(name="duration", column="night_duration"),
+ @FieldResult(name="date", column="night_date"),
+ @FieldResult(name="area", column="area_id"),
+ discriminatorColumn="disc"
+ }),
+ @EntityResult(entityClass=org.hibernate.test.annotations.query.Area.class, fields = {
+ @FieldResult(name="id", column="aid"),
+ @FieldResult(name="name", column="name")
+ })
+ }
+)</programlisting></para>
+
+ <para>Dans l'exemple ci-dessus, la requête nommée
+ <literal>night&area</literal> utilise le mapping de résultats
+ <literal>joinMapping</literal>. Ce mapping retourne 2 entités,
+ <literal>Night</literal> et <literal>Area</literal>, chaque propriété est
+ déclarée et associée à un nom de colonne, en fait le nom de colonne
+ récupéré par la requête. Voyons maintenant une déclaration implicite de
+ mapping propriété/colonne.</para>
+
+ <programlisting>@Entity
+<emphasis role="bold">@SqlResultSetMapping(name="implicit", entities=@EntityResult(entityClass=org.hibernate.test.annotations.query.SpaceShip.class))
+ at NamedNativeQuery(name="implicitSample", query="select * from SpaceShip", resultSetMapping="implicit")</emphasis>
+public class SpaceShip {
+ private String name;
+ private String model;
+ private double speed;
+
+ @Id
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Column(name="model_txt")
+ public String getModel() {
+ return model;
+ }
+
+ public void setModel(String model) {
+ this.model = model;
+ }
+
+ public double getSpeed() {
+ return speed;
+ }
+
+ public void setSpeed(double speed) {
+ this.speed = speed;
+ }
+}</programlisting>
+
+ <para>Dans cet exemple, nous décrivons seulement le membre de l'entité du
+ mapping de résultats. Le mapping de propriété/colonne est fait en
+ utilisant les valeurs de mapping de l'entité. Dans ce cas, la propriété
+ <literal>model</literal> est liée à la colonne
+ <literal>model_txt</literal>. Si l'association à une entité concernée
+ implique une clef primaire composée, un élément
+ <literal>@FieldResult</literal> devrait être utilisé pour chaque colonne
+ de la clef étrangère. Le nom de <literal>@FieldResult</literal> est
+ composé du nom de la propriété pour la relation, suivi par un point ("."),
+ suivi par le nom ou le champ ou la propriété de la clef primaire.</para>
+
+ <programlisting>@Entity
+ at SqlResultSetMapping(name="compositekey",
+ entities=@EntityResult(entityClass=org.hibernate.test.annotations.query.SpaceShip.class,
+ fields = {
+ @FieldResult(name="name", column = "name"),
+ @FieldResult(name="model", column = "model"),
+ @FieldResult(name="speed", column = "speed"),
+<emphasis role="bold"> @FieldResult(name="captain.firstname", column = "firstn"),
+ @FieldResult(name="captain.lastname", column = "lastn"),</emphasis>
+ @FieldResult(name="dimensions.length", column = "length"),
+ @FieldResult(name="dimensions.width", column = "width")
+ }),
+ columns = { @ColumnResult(name = "surface"),
+ @ColumnResult(name = "volume") } )
+
+ at NamedNativeQuery(name="compositekey",
+ query="select name, model, speed, lname as lastn, fname as firstn, length, width, length * width as surface from SpaceShip",
+ resultSetMapping="compositekey")
+} )
+public class SpaceShip {
+ private String name;
+ private String model;
+ private double speed;
+ private Captain captain;
+ private Dimensions dimensions;
+
+ @Id
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @ManyToOne(fetch= FetchType.LAZY)
+ @JoinColumns( {
+ @JoinColumn(name="fname", referencedColumnName = "firstname"),
+ @JoinColumn(name="lname", referencedColumnName = "lastname")
+ } )
+ public Captain getCaptain() {
+ return captain;
+ }
+
+ public void setCaptain(Captain captain) {
+ this.captain = captain;
+ }
+
+ public String getModel() {
+ return model;
+ }
+
+ public void setModel(String model) {
+ this.model = model;
+ }
+
+ public double getSpeed() {
+ return speed;
+ }
+
+ public void setSpeed(double speed) {
+ this.speed = speed;
+ }
+
+ public Dimensions getDimensions() {
+ return dimensions;
+ }
+
+ public void setDimensions(Dimensions dimensions) {
+ this.dimensions = dimensions;
+ }
+}
+
+ at Entity
+ at IdClass(Identity.class)
+public class Captain implements Serializable {
+ private String firstname;
+ private String lastname;
+
+ @Id
+ public String getFirstname() {
+ return firstname;
+ }
+
+ public void setFirstname(String firstname) {
+ this.firstname = firstname;
+ }
+
+ @Id
+ public String getLastname() {
+ return lastname;
+ }
+
+ public void setLastname(String lastname) {
+ this.lastname = lastname;
+ }
+}
+</programlisting>
+
+ <note>
+ <para>Si vous regardez la propriété dimension, vous verrez qu'Hibernate
+ prend en charge la notation avec les points pour les objets embarqués
+ (vous pouvez même avoir des objets embarqués imbriqués). Les
+ implémentations EJB3 n'ont pas à prendre en charge cette fonctionnalité,
+ mais nous le faisons :-)</para>
+ </note>
+
+ <para>Si vous récupérez une simple entité et si vous utilisez le mapping
+ par défaut, vous pouvez utiliser l'attribut <literal>resultClass</literal>
+ à la place de <literal>resultSetMapping</literal> :</para>
+
+ <programlisting><emphasis role="bold">@NamedNativeQuery(name="implicitSample", query="select * from SpaceShip",
+ resultClass=SpaceShip.class)</emphasis>
+public class SpaceShip {</programlisting>
+
+ <para>Dans certaines de vos requêtes natives, vous devrez retourner des
+ valeurs scalaires, par exemple lors de la construction de requêtes de
+ rapport. Vous pouvez les mapper dans
+ <literal>@SqlResultsetMapping</literal> avec
+ <literal>@ColumnResult</literal>. En fait, vous pouvez même mélanger des
+ retours d'entités et de valeurs scalaires dans la même requête native (ce
+ n'est cependant probablement pas commun).</para>
+
+ <programlisting><emphasis role="bold">@SqlResultSetMapping(name="scalar", columns=@ColumnResult(name="dimension"))
+ at NamedNativeQuery(name="scalar", query="select length*width as dimension from SpaceShip", resultSetMapping="scalar")</emphasis></programlisting>
+
+ <para>Une autre indication de fonctionnement spécifique aux requêtes
+ natives a été présentée : <literal>org.hibernate.callable</literal>
+ laquelle peut être à true ou à false fausse selon que la requête est une
+ procédure stockée ou pas.</para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="entity-hibspec" xreflabel="Extensions d'Hibernate Annotation">
+ <title>Extensions d'Hibernate Annotation</title>
+
+ <para>Hibernate 3.1 offre une variété d'annotations supplémentaires que vous
+ pouvez mélanger/faire correspondre avec des entités EJB3. Elles ont été
+ conçues comme une extension naturelle aux annotations EJB3.</para>
+
+ <para>Pour aller plus loin que les capacités d'EJB3, Hibernate fournit des
+ annotations spécifiques qui correspondent aux fonctionnalités d'Hibernate.
+ Le package <classname>org.hibernate.annotations</classname> contient toutes
+ ces extensions d'annotations.</para>
+
+ <sect2 id="entity-hibspec-entity" revision="2">
+ <title>Entité</title>
+
+ <para>Vous pouvez finement paramétrer certaines des actions faites par
+ Hibernate sur les entités au-delà de ce qu'offre la spécification
+ EJB3.</para>
+
+ <para><classname>@org.hibernate.annotations.Entity</classname> ajoute des
+ méta-données supplémentaires qui peuvent être nécessaires au-delà de ce
+ qui est défini dans l'annotation <literal>@Entity</literal>
+ standard :<itemizedlist>
+ <listitem>
+ mutable : indique si l'entité est modifiable ou non
+ </listitem>
+
+ <listitem>
+ dynamicInsert : autorise le SQL dynamique pour les insertions
+ </listitem>
+
+ <listitem>
+ dynamicUpdate : autorise le SQL dynamique pour les mise à jour
+ </listitem>
+
+ <listitem>
+ selectBeforeUpdate : spécifie qu'Hibernate ne devrait jamais
+ exécuter un UPDATE SQL à moins qu'il ne soit certain qu'un objet
+ est réellement modifié
+ </listitem>
+
+ <listitem>
+ polymorphism : indique si le polymorphisme d'entité est de type
+ PolymorphismType.IMPLICIT (valeur par défaut) ou
+ PolymorphismType.EXPLICIT
+ </listitem>
+
+ <listitem>
+ persister : autorise la surcharge de l'implémentation de
+ persistance fournie par défaut
+ </listitem>
+
+ <listitem>
+ optimisticLock : stratégie de verrouillage optmiste
+ (OptimisticLockType.VERSION,
+ OptimisticLockType.NONE, OptimisticLockType.DIRTY ou
+ OptimisticLockType.ALL)
+ </listitem>
+ </itemizedlist></para>
+
+ <para><note>
+ <para>@javax.persistence.Entity est encore obligatoire,
+ @org.hibernate.annotations.Entity ne la remplace pas.</para>
+ </note></para>
+
+ <para>Voici quelques extensions d'annotations Hibernate
+ supplémentaires.</para>
+
+ <para><literal>@org.hibernate.annotations.BatchSize</literal> vous permet
+ de définir la taille du batch lors de la récupération d'instances de
+ cette entité (p. ex. <literal>@BatchSize(size=4)</literal>). Lors du
+ chargement d'une entité donnée, Hibernate chargera alors toutes les
+ entités non initialisées du même type dans le contexte de la persistance
+ jusqu'à la taille du batch.</para>
+
+ <para><literal>@org.hibernate.annotations.Proxy</literal> définit les
+ attributs de chargement de l'entité. lazy (valeur par défaut) définit si
+ la classe est chargée à la demande ou non. proxyClassName est l'interface
+ utilisée pour générer le proxy (par défaut, la classe elle-même).</para>
+
+ <para><literal>@org.hibernate.annotations.Where</literal> définit une
+ clause WHERE SQL optionnelle utilisée lorsque des instances de cette
+ classe sont récupérées.</para>
+
+ <para><literal>@org.hibernate.annotations.Check</literal> déclare une
+ contrainte de vérification optionnelle définie dans l'expression
+ DDL.</para>
+
+ <para><literal>@OnDelete(action=OnDeleteAction.CASCADE)</literal> sur des
+ classes filles jointes : utilise une commande SQL DELETE en cascade lors
+ de la suppression plutôt que le mécanisme habituel d'Hibernate.</para>
+
+ <para><literal>@Table(appliesTo="tableName", indexes = {
+ @Index(name="index1", columnNames={"column1", "column2"} ) } )</literal>
+ crée les index définis sur les colonnes de la table
+ <literal>tableName</literal>. Cela peut s'appliquer sur une table primaire
+ ou une table secondaire. L'annotation <literal>@Tables</literal> vous
+ permet d'avoir des index sur des tables différentes. Cette annotation est
+ attendue là où <literal>@javax.persistence.Table</literal> ou
+ <literal>@javax.persistence.SecondaryTable</literal>(s) sont
+ déclarées.</para>
+
+ <note>
+ <para><literal>@org.hibernate.annotations.Table</literal> est un
+ complément, pas un remplacement de
+ <literal>@javax.persistence.Table</literal>. Surtout, si vous souhaitez
+ changer le nom par défaut d'une table, vous devez utiliser
+ <literal>@javax.persistence.Table</literal>, pas
+ <literal>@org.hibernate.annotations.Table</literal>.</para>
+ </note>
+
+ <para><programlisting>@Entity
+ at BatchSize(size=5)
+ at org.hibernate.annotations.Entity(
+ selectBeforeUpdate = true,
+ dynamicInsert = true, dynamicUpdate = true,
+ optimisticLock = OptimisticLockType.ALL,
+ polymorphism = PolymorphismType.EXPLICIT)
+ at Where(clause="1=1")
+ at org.hibernate.annotations.Table(name="Forest", indexes = { @Index(name="idx", columnNames = { "name", "length" } ) } )
+public class Forest { ... }</programlisting><programlisting>@Entity
+ at Inheritance(
+ strategy=InheritanceType.JOINED
+)
+public class Vegetable { ... }
+
+ at Entity
+ at OnDelete(action=OnDeleteAction.CASCADE)
+public class Carrot extends Vegetable { ... }</programlisting></para>
+ </sect2>
+
+ <sect2 id="entity-hibspec-identifier" revision="1">
+ <title>Identifiant</title>
+
+ <para><literal>@org.hibernate.annotations.GenericGenerator</literal> vous
+ permet de définir un générateur d'identifiants Hibernate
+ spécifique.</para>
+
+ <para><programlisting>@Id @GeneratedValue(generator="system-uuid")
+ at GenericGenerator(name="system-uuid", strategy = "uuid")
+public String getId() {
+
+ at Id @GeneratedValue(generator="hibseq")
+ at GenericGenerator(name="hibseq", strategy = "seqhilo",
+ parameters = {
+ @Parameter(name="max_lo", value = "5"),
+ @Parameter(name="sequence", value="heybabyhey")
+ }
+)
+public Integer getId() {</programlisting></para>
+
+ <para><literal>strategy</literal> est le nom court de la stratégie du
+ générateur Hibernate3 ou le nom pleinement qualifié de la classe d'une
+ implémentation de <classname>IdentifierGenerator</classname>. Vous pouvez
+ ajouter des paramètres avec l'attribut
+ <literal>parameters</literal>.</para>
+
+ <para>Contrairement à son pendant standard,
+ <literal>@GenericGenerator</literal> peut ête utilisée dans les
+ annotations au niveau du package, en faisant ainsi un générateur de niveau
+ applicatif (comme s'il était dans un fichier JPA XML).</para>
+
+ <programlisting>@GenericGenerator(name="hibseq", strategy = "seqhilo",
+ parameters = {
+ @Parameter(name="max_lo", value = "5"),
+ @Parameter(name="sequence", value="heybabyhey")
+ }
+)
+package org.hibernate.test.model</programlisting>
+ </sect2>
+
+ <sect2 id="entity-hibspec-property" revision="2">
+ <title>Propriété</title>
+
+ <sect3>
+ <title>Type d'accès</title>
+
+ <para>Le type d'accès est déduit de la position de
+ <literal>@Id</literal> ou de <literal>@EmbeddedId</literal> dans la
+ hiérarchie de l'entité. Les entités filles, les objets embarqués et les
+ entités parentes mappés héritent du type d'accès de l'entité
+ racine.</para>
+
+ <para>Dans Hibernate, vous pouvez surcharger le type d'accès
+ pour :</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>utiliser une stratégie d'accès personnalisée</para>
+ </listitem>
+
+ <listitem>
+ <para>paramétrer finement le type d'accès au niveau de la classe ou
+ au niveau de la propriété</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Une annocation @AccessType a été présentée pour prendre en charge
+ ce comportement. Vous pouvez définir le type d'accès sur :</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>une entité</para>
+ </listitem>
+
+ <listitem>
+ <para>une classe parente</para>
+ </listitem>
+
+ <listitem>
+ <para>un objet embarqué</para>
+ </listitem>
+
+ <listitem>
+ <para>une propriété</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Le type d'accès est surchargé pour l'élément annoté, si surchargé
+ sur une classe, toutes les propriétés de la classe donnée héritent du
+ type d'accès. Pour les entités racines, le type d'accès est considéré
+ par défaut comme celui de la hiérarchie entière (surchargeable au niveau
+ de la classe ou de la propriété).</para>
+
+ <para>Si le type d'accès est marqué comme "propriété", les getters sont
+ parcourus pour examiner les annotations, si le type d'accès est marqué
+ comme "champ", ce sont les champs qui sont parcourus pour les
+ annotations. Sinon les éléments marqués avec @Id ou @embeddedId sont
+ scannés.</para>
+
+ <para>Vous pouvez surcharger une type d'accès pour une propriété, mais
+ l'élément annoté ne sera pas influencé : par exemple, une entité ayant
+ un type d'accès <literal>field</literal>, peut annoter un champ avec
+ <literal>@AccessType("property")</literal>, le type d'accès sera alors
+ "property" pour cet attribut, des annotations devront encore être
+ portées sur les champs.</para>
+
+ <para>Si une classe parente ou un objet embarquable n'est pas annoté, le
+ type d'accès de l'entité racine est utilisé (même si un type d'accès a
+ été défini sur une classe parente ou un objet embarquable
+ intermédiaire). Le principe de la poupée russe ne s'applique pas.</para>
+
+ <programlisting>@Entity
+public class Person implements Serializable {
+ @Id @GeneratedValue // type d'accès "champ"
+ Integer id;
+
+ @Embedded
+ @AttributeOverrides({
+ @AttributeOverride(name = "iso2", column = @Column(name = "bornIso2")),
+ @AttributeOverride(name = "name", column = @Column(name = "bornCountryName"))
+ })
+ Country bornIn;
+}
+
+ at Embeddable
+<emphasis role="bold">@AccessType("property")</emphasis> // surcharge le type d'accès pour toutes les propriétés dans Country
+public class Country implements Serializable {
+ private String iso2;
+ private String name;
+
+ public String getIso2() {
+ return iso2;
+ }
+
+ public void setIso2(String iso2) {
+ this.iso2 = iso2;
+ }
+
+ @Column(name = "countryName")
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
+</programlisting>
+ </sect3>
+
+ <sect3>
+ <title>Formule</title>
+
+ <para>Parfois, vous voulez effectuer certains calculs par la base de
+ données plutôt que par la JVM, ou vous pourriez aussi vouloir créer une
+ sorte de colonne virtuelle. Vous pouvez utilisez un fragment SQL (alias
+ une formule) plutôt que de mapper un propriété sur une colonne. Cette
+ sorte de propriété est en lecture seule (sa valeur est calculée par
+ votre formule).</para>
+
+ <programlisting>@Formula("obj_length * obj_height * obj_width")
+public long getObjectVolume()</programlisting>
+
+ <para>Le fragment SQL peut être aussi complexe que vous le souhaitez,
+ même avec des sous-selects inclus.</para>
+ </sect3>
+
+ <sect3>
+ <title>Type</title>
+
+ <para><literal>@org.hibernate.annotations.Type</literal> surcharge le
+ type Hibernate utilisé par défaut : ce n'est généralement pas nécessaire
+ puisque le type est correctement inféré par Hibernate. Veuillez vous
+ référer au guide de référence Hibernate pour plus d'informations sur les
+ types Hibernate.</para>
+
+ <para><literal>@org.hibernate.annotations.TypeDef</literal> et
+ <literal>@org.hibernate.annotations.TypeDefs</literal> vous permettent
+ de déclarer des définitions de type. Ces annotations sont placées au
+ niveau de la classe ou du package. Notez que ces définitions seront
+ globales pour la session factory (même au niveau de la classe) et que la
+ définition du type doit être définie avant n'importe quelle
+ utilisation.</para>
+
+ <programlisting>@TypeDefs(
+ {
+ @TypeDef(
+ name="caster",
+ typeClass = CasterStringType.class,
+ parameters = {
+ @Parameter(name="cast", value="lower")
+ }
+ )
+ }
+)
+package org.hibernate.test.annotations.entity;
+
+...
+public class Forest {
+ @Type(type="caster")
+ public String getSmallText() {
+ ...
+}
+ </programlisting>
+
+ <para>Lors de l'utilisation d'un type utilisateur composé, vous devrez
+ exprimer les définitions des colonnes. L'annotation
+ <literal>@Columns</literal> a été mise en place dans ce but.</para>
+
+ <programlisting>@Type(type="org.hibernate.test.annotations.entity.MonetaryAmountUserType")
+ at 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;
+ ...
+}</programlisting>
+ </sect3>
+
+ <sect3>
+ <title>Index</title>
+
+ <para>Vous pouvez définir un index sur une colonne particulière en
+ utilisant l'annotation <literal>@Index</literal> sur une propriété d'une
+ colonne, l'attribut columnNames sera ignoré.</para>
+
+ <programlisting>@Column(secondaryTable="Cat1")
+ at Index(name="story1index")
+public String getStoryPart1() {
+ return storyPart1;
+}</programlisting>
+ </sect3>
+
+ <sect3>
+ <title>@Parent</title>
+
+ <para>A l'intérieur d'un objet embarquable, vous pouvez définir
+ une des propriétés comme un pointeur vers l'élément
+ propriétaire.</para>
+
+ <programlisting>@Entity
+public class Person {
+ @Embeddable public Address address;
+ ...
+}
+
+ at Embeddable
+public class Address {
+ @Parent public Person owner;
+ ...
+}
+
+
+person == person.address.owner</programlisting>
+ </sect3>
+
+ <sect3>
+ <title>Propriétés générées</title>
+
+ <para>Certaines propriétés sont générées au moment de l'insertion ou de
+ la mise à jour par votre base de données. Hibernate peut traiter de
+ telles propriétés et déclencher un select subséquent pour lire ces
+ propriétés.</para>
+
+ <programlisting>@Entity
+public class Antenna {
+ @Id public Integer id;
+ @Generated(GenerationTime.ALWAYS) @Column(insertable = false, updatable = false)
+ public String longitude;
+
+ @Generated(GenerationTime.INSERT) @Column(insertable = false)
+ public String latitude;
+}</programlisting>
+
+ <para>Quand vous annotez votre propriété avec
+ <literal>@Generated</literal>, vous devez vous assurer que l'insertion
+ et la mise à jour n'entreront pas en conflit avec la stratégie de
+ génération que vous avez choisie. Lorsque GenerationTime.INSERT est
+ choisi, la propriété ne doit pas contenir de colonnes insérables ;
+ lorsque GenerationTime.ALWAYS est choisi, la propriété ne doit pas
+ contenir de colonnes qui puissent être insérées ou mises à jour.</para>
+
+ <para>Les propriétés <literal>@Version</literal> ne peuvent pas (par
+ conception) être <literal>@Generated(INSERT)</literal>, elles doivent
+ être <literal>NEVER</literal> ou <literal>ALWAYS</literal>.</para>
+ </sect3>
+ </sect2>
+
+ <sect2 id="entity-hibspec-inheritance" revision="1">
+ <title>Héritage</title>
+
+ <para>SINGLE_TABLE est une stratégie très puissante mais parfois, et
+ surtout pour des systèmes pré-existants, vous ne pouvez pas ajouter une
+ colonne discriminante supplémentaire. Pour cela Hibernate a mis en place
+ la notion de formule discriminante :
+ <literal>@DiscriminatorFormula</literal> est une remplaçcant de
+ <literal>@DiscriminatorColumn</literal> et utilise un fragment SQL en tant
+ que formule pour la résolution du discriminant (pas besoin d'avoir une
+ colonne dédiée).</para>
+
+ <programlisting>@Entity
+ at DiscriminatorForumla("case when forest_type is null then 0 else forest_type end")
+public class Forest { ... }</programlisting>
+
+ <para>Par défaut, lors du requêtage sur les entités les plus hautes,
+ Hibernate ne met pas de restriction sur la colonne discriminante. Ceci
+ peut être un inconvénient si cette colonne contient des valeurs qui ne sont
+ pas mappées dans votre hiérarchie (avec
+ <literal>@DiscriminatorValue</literal>). Pour contourner ca, vous pouvez
+ utilser <literal>@ForceDiscriminator</literal> (au niveau de la classe,
+ à côté de <literal>@DiscriminatorColumn</literal>). Hibernate listera
+ alors les valeurs disponibles lors du chargement des entités.</para>
+ </sect2>
+
+ <sect2 id="entity-hibspec-singleassoc">
+ <title>Annotations concernant les simples associations</title>
+
+ <para>Par défaut, lorsqu'Hibernate ne peut pas résoudre l'association
+ parce que l'élément associé attendu n'est pas dans la base de données
+ (mauvais identifiant sur la colonne de l'association), une exception est
+ levée par Hibernate. Cela pourrait être un inconvénient pour des schémas
+ pré-existants et mal maintenus. Vous pouvez demander à Hibernate d'ignorer
+ de tels éléments plutôt que de lever une exception en utilisant
+ l'annotation <literal>@NotFound</literal>. Cette annotation peut être
+ utilisée sur une association <literal>@OneToOne</literal> (avec une clef
+ étrangère), <literal>@ManyToOne</literal>, <literal>@OneToMany</literal>
+ ou <literal>@ManyToMany</literal>.</para>
+
+ <programlisting>@Entity
+public class Child {
+ ...
+ @ManyToOne
+ @NotFound(action=NotFoundAction.IGNORE)
+ public Parent getParent() { ... }
+ ...
+}</programlisting>
+
+ <para>Parfois vous voulez déléguer à votre base de données la suppression
+ en cascade lorsqu'une entité donnée est supprimée.</para>
+
+ <programlisting>@Entity
+public class Child {
+ ...
+ @ManyToOne
+ @OnDelete(action=OnDeleteAction.CASCADE)
+ public Parent getParent() { ... }
+ ...
+}</programlisting>
+
+ <para>Dans ce cas, Hibernate génère une contrainte de suppression en
+ cascade au niveau de la base de données.</para>
+
+ <para>Les contraintes de clef étrangère, bien que générées par Hibernate,
+ ont un nom justement illisible. Vous pouvez surcharger le nom de la
+ contrainte par l'utilisation de <literal>@ForeignKey</literal>.</para>
+
+ <programlisting>@Entity
+public class Child {
+ ...
+ @ManyToOne
+ <emphasis role="bold">@ForeignKey(name="FK_PARENT")</emphasis>
+ public Parent getParent() { ... }
+ ...
+}
+
+alter table Child add constraint FK_PARENT foreign key (parent_id) references Parent</programlisting>
+
+ <sect3>
+ <title>Options de chargement et modes de récupération</title>
+
+ <para>EJB3 arrive avec l'option <literal>fetch</literal> pour définir
+ le chargement à la demande et les modes de récupération, cependant
+ Hibernate a beaucoup plus d'options dans ce domaine. Pour finement
+ paramétrer le chargement à la demande et les stratégies de récupération,
+ quelques annotations supplémentaires ont été mises en place :</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><literal>@LazyToOne</literal> : définit l'option de chargement
+ à la demande sur les associations <literal>@ManyToOne</literal> et
+ <literal>@OneToOne</literal>. <literal>LazyToOneOption</literal>
+ peut être <literal>PROXY</literal> (ie utiliser un chargement à la
+ demande basé sur un proxy), <literal>NO_PROXY</literal> (utilise
+ un chargement à la demande sur l'ajout de bytecode - notez qu'un
+ temps de construction du bytecode est nécessaire) et
+ <literal>FALSE</literal> (association sans chargement à la
+ demande) ;</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>@LazyCollection</literal> : définit l'option de
+ chargement à la demande sur les associations
+ <literal>@ManyToMany</literal> et <literal>@OneToMany</literal>.
+ LazyCollectionOption peut être <literal>TRUE</literal> (la
+ collection est chargée à la demande lorsque son état est accédé),
+ <literal>EXTRA</literal> (la collection est chargée à la demande et
+ toutes les opérations essaieront d'éviter le chargement de la
+ collection, c'est surtout utile pour de grosses collections lorsque
+ le chargement de tous les éléments n'est pas nécessaire) et
+ <literal>FALSE</literal> (association sans chargement à la
+ demande) ;</para>
+ </listitem>
+
+ <listitem>
+ <para><literal>@Fetch</literal> : définit une stratégie de
+ récupération utilisée pour charger l'association.
+ <literal>FetchMode</literal> peut être
+ <literal>SELECT</literal> (un select est déclenché lorsque
+ l'association a besoin d'être chargée), <literal>SUBSELECT</literal>
+ (disponible uniquement pour des collections, utilise une stratégie
+ de sous select - veuillez vous référer à la documentation de
+ référence d'Hibernate pour plus d'informations) ou
+ <literal>JOIN</literal> (utilise un JOIN SQL pour charger
+ l'association lors du chargement de l'entité propriétaire).
+ <literal>JOIN</literal> surcharge n'importe quel attribut de
+ chargement à la demande (une association chargée avec la stratégie
+ <literal>JOIN</literal> ne peut pas être chargée à la
+ demande).</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Les annotations Hibernate surchargent les options de récupération
+ EJB3.</para>
+
+ <table>
+ <title>Chargement à la demande et options de récupération
+ équivalentes</title>
+
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>Annotations</entry>
+
+ <entry>Chargement à la demande</entry>
+
+ <entry>Récupération</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>@[One|Many]ToOne](fetch=FetchType.LAZY)</entry>
+
+ <entry>@LazyToOne(PROXY)</entry>
+
+ <entry>@Fetch(SELECT)</entry>
+ </row>
+
+ <row>
+ <entry>@[One|Many]ToOne](fetch=FetchType.EAGER)</entry>
+
+ <entry>@LazyToOne(FALSE)</entry>
+
+ <entry>@Fetch(JOIN)</entry>
+ </row>
+
+ <row>
+ <entry>@ManyTo[One|Many](fetch=FetchType.LAZY)</entry>
+
+ <entry>@LazyCollection(TRUE)</entry>
+
+ <entry>@Fetch(SELECT)</entry>
+ </row>
+
+ <row>
+ <entry>@ManyTo[One|Many](fetch=FetchType.EAGER)</entry>
+
+ <entry>@LazyCollection(FALSE)</entry>
+
+ <entry>@Fetch(JOIN)</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </sect3>
+ </sect2>
+
+ <sect2 id="entity-hibspec-collection" revision="2">
+ <title>Annotations concernant les collections</title>
+
+ <sect3 id="entity-hibspec-collection-enhance" revision="2">
+ <title>Améliorer les configurations des collections</title>
+
+ <para>Il est possible de configurer :<itemizedlist>
+ <listitem>
+ la taille des batchs pour les collections en utilisant @BatchSize
+ </listitem>
+
+ <listitem>
+ la clause where, en utilisant @Where (appliquée à l'entité cible)
+ ou @WhereJoinTable (appliquée à la table de l'association)
+ </listitem>
+
+ <listitem>
+ la clause de vérification, en utilsant @Check
+ </listitem>
+
+ <listitem>
+ la clause SQL order by, en utilisant @OrderBy
+ </listitem>
+
+ <listitem>
+ la stratégie de suppression en cascade avec
+ @OnDelete(action=OnDeleteAction.CASCADE)
+ </listitem>
+ </itemizedlist></para>
+
+ <para>Vous pouvez aussi déclarer un comparateur de tri, utilisez
+ l'annotation <literal>@Sort</literal>. Exprimez le type de comparateur
+ que vous voulez entre "non trié" (NdT : unsorted), "ordre naturel"
+ (NdT : natural) ou un comparateur personnalisé. Si vous voulez utilisez
+ votre propre implémentation de comparateur, vous devrez indiquer la
+ classe d'implémentation en utilisant l'attribut
+ <literal>comparator</literal>. Notez que vous avez besoin d'utiliser
+ l'interface <classname>SortedSet</classname> ou
+ <classname>SortedMap</classname>.</para>
+
+ <programlisting> @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
+ @JoinColumn(name="CUST_ID")
+ @Sort(type = SortType.COMPARATOR, comparator = TicketComparator.class)
+ @Where(clause="1=1")
+ @OnDelete(action=OnDeleteAction.CASCADE)
+ public SortedSet<Ticket> getTickets() {
+ return tickets;
+ }</programlisting>
+
+ <para>Veuillez vous référer aux descriptions précédentes de ces
+ annotations pour plus d'informations.</para>
+
+ <para>Les contraintes de clef étrangère, bien que générées par
+ Hibernate, ont un nom illisible. Vous pouvez surcharger le nom de la
+ contrainte en utilisant <literal>@ForeignKey</literal>. Notez que cette
+ annotation doit être placée du côté possédant la relation,
+ <literal>inverseName</literal> référençant la contrainte de l'autre
+ côté.</para>
+
+ <programlisting>@Entity
+public class Woman {
+ ...
+ @ManyToMany(cascade = {CascadeType.ALL})
+ <emphasis role="bold">@ForeignKey(name = "TO_WOMAN_FK", inverseName = "TO_MAN_FK")</emphasis>
+ public Set<Man> getMens() {
+ return mens;
+ }
+}
+
+alter table Man_Woman add constraint TO_WOMAN_FK foreign key (woman_id) references Woman
+alter table Man_Woman add constraint TO_MAN_FK foreign key (man_id) references Man</programlisting>
+ </sect3>
+
+ <sect3 id="entity-hibspec-collection-extratype" revision="1">
+ <title>Types de collection extra</title>
+
+ <sect4>
+ <title>List</title>
+
+ <para>Outre EJB3, Hibernate Annotations prend en charge les véritables
+ <classname>List</classname> et <classname>Array</classname>. Mappez
+ votre collection de la même manière que d'habitude et ajoutez
+ l'annotation @<literal>IndexColumn</literal>. Cette annotation vous
+ permet de décrire la colonne qui contiendra l'index. Vous pouvez aussi
+ déclarer la valeur de l'index en base de données qui représente le
+ premier élément (alias index de base). La valeur habituelle est
+ <literal>0</literal> ou <literal>1</literal>.</para>
+
+ <programlisting>@OneToMany(cascade = CascadeType.ALL)
+ at IndexColumn(name = "drawer_position", base=1)
+public List<Drawer> getDrawers() {
+ return drawers;
+}</programlisting>
+
+ <note>
+ <para>Si vous oubliez de positionner
+ <literal>@IndexColumn</literal>, la sémantique du bag est appliquée.
+ Si vous voulez la sémantique du bag sans ses limitations, considérez
+ l'utilisation de <literal>@CollectionId</literal>.</para>
+ </note>
+ </sect4>
+
+ <sect4>
+ <title>Map</title>
+
+ <para>Hibernate Annotations prend aussi en charge le mapping de
+ véritables Maps, si <literal>@javax.persistence.MapKey</literal> n'est
+ pas positionnée, Hibernate mappera l'élément clef ou l'objet
+ embarquable dans ses propres colonnes. Pour surcharger les colonnes
+ par défaut, vous pouvez utiliser
+ <literal>@org.hibernate.annotations.MapKey</literal> si votre clef est
+ un type de base (par défaut à <literal>mapkey</literal>) ou un objet
+ embarquable, ou vous pouvez utiliser
+ <literal>@org.hibernate.annotations.MapKeyManyToMany</literal> si
+ votre clef est une entité.</para>
+ </sect4>
+
+ <sect4 id="entity-hibspec-collection-extratype-indexbidir">
+ <title>Associations bidirectionnelle avec des collections indexées</title>
+
+ <para>Une association bidirectionnelle où une extrémité est
+ représentée comme une <literal>@IndexColumn</literal> ou une
+ <literal>@org.hibernate.annotations.MapKey[ManyToMany]</literal>
+ requiert une considération spéciale. S'il y a une propriété de la
+ classe enfante qui mappe la colonne de l'index, pas de problème, nous
+ pouvons continuer en utilisant <literal>mappedBy</literal> sur le
+ mapping de la collection :</para>
+
+ <programlisting>@Entity
+public class Parent {
+ @OneToMany(mappedBy="parent")
+ @org.hibernate.annotations.MapKey(columns=@Column(name="name"))
+ private Map<String, Child> children;
+ ...
+}
+
+ at Entity
+public class Parent {
+ ...
+ @Basic
+ private String name;
+
+ @ManyToOne
+ @JoinColumn(name="parent_id", nullable=false)
+ private Parent parent;
+ ...
+}</programlisting>
+
+ <para>Mais s'il n'y a pas de telle propriété sur la classe enfante,
+ nous ne pouvons pas penser que l'association est vraiment
+ bidirectionnelle (il y a des informations disponibles à une extrémité
+ qui ne sont pas disponibles à l'autre). Dans ce cas, nous ne pouvons
+ pas mapper la collection avec <literal>mappedBy</literal>. A la place,
+ nous pourrions utiliser le mapping suivant :</para>
+
+ <programlisting>@Entity
+public class Parent {
+ @OneToMany
+ @org.hibernate.annotations.MapKey(columns=@Column(name="name"))
+ @JoinColumn(name="parent_id", nullable=false)
+ private Map<String, Child> children;
+ ...
+}
+
+ at Entity
+public class Parent {
+ ...
+ @ManyToOne
+ @JoinColumn(name="parent_id", insertable=false, updatable=false, nullable=false)
+ private Parent parent;
+ ...
+}</programlisting>
+
+ <para>Notez que dans ce mapping, l'extrémité de l'association dont la
+ valeur est une collection est responsable des mises à jour pour la
+ clef étrangère.</para>
+ </sect4>
+
+ <sect4>
+ <title>Bag avec une clef primaire</title>
+
+ <para>Une autre fonctionnalité intéressante est la possibilité de
+ définir une clef primaire subrogée à une collection bag. Ceci enlève
+ pas mal d'inconvénients des bags : mise à jour et suppression
+ sont efficaces, plus d'un bag <literal>EAGER</literal> par requête ou
+ par entité. Cette clef primaire sera contenue dans une colonne
+ supplémentaire de votre table de collection mais ne sea pas visible
+ par l'application Java. @CollectionId est utilisée pour marquer une
+ collection comme "id bag", ca permet aussi de surcharger les colonnes
+ de la clef primaire, le type de la clef primaire et la stratégie du
+ générateur. La stratégie peut être <literal>identity</literal>, ou
+ n'importe quel nom de générateur défini de votre application.</para>
+
+ <programlisting>@Entity
+ at TableGenerator(name="ids_generator", table="IDS")
+public class Passport {
+ ...
+
+ @ManyToMany(cascade = CascadeType.ALL)
+ @JoinTable(name="PASSPORT_VISASTAMP")
+ <emphasis role="bold">@CollectionId(
+ columns = @Column(name="COLLECTION_ID"),
+ type=@Type(type="long"),
+ generator = "ids_generator"
+ )</emphasis>
+ private Collection<Stamp> visaStamp = new ArrayList();
+ ...
+}</programlisting>
+ </sect4>
+
+ <sect4>
+ <title>Collection d'éléments ou d'éléments composés</title>
+
+ <para>Hibernate Annotations prend aussi en charge les collections de
+ types core (Integer, String, Enums, ...), les collections d'objets
+ embarquables et même les tableaux de types primitifs. Ce sont des
+ collections d'éléments.</para>
+
+ <para>Une collection d'éléments doit être annotée comme
+ <literal>@CollectionOfElements</literal> (en tant que remplaçant de
+ <literal>@OneToMany</literal>). Pour définir la table de la
+ collection, l'annotation <literal>@JoinTable</literal> est utilisée
+ sur la propriété de l'association, <literal>joinColumns</literal>
+ définit les colonnes de jointure entre la table de l'entité primaire
+ et la table de la collection (inverseJoincolumn est inutile et
+ devrait être laissé à vide). Pour une collection de types core ou un
+ tableau de types primitifs, vous pouvez surcharger la définition de la
+ colonne de l'élément en utilisant <literal>@Column</literal> sur la
+ propriété de l'association. Vous pouvez aussi surcharger les colonnes
+ d'une collection d'objets embarquables en utilisant
+ <literal>@AttributeOverride</literal>. Pour atteindre l'élément de la
+ collection, vous avez besoin d'ajouter "element" au nom de l'attribut
+ surchargé (p. ex. "element" pour les types core, ou "element.serial"
+ pour la propriété serial d'un élément embarqué). Pour atteindre
+ l'index/clef d'une collection, ajoutez "key" à la place.</para>
+
+ <programlisting>@Entity
+public class Boy {
+ private Integer id;
+ private Set<String> nickNames = new HashSet<String>();
+ private int[] favoriteNumbers;
+ private Set<Toy> favoriteToys = new HashSet<Toy>();
+ private Set<Character> characters = new HashSet<Character>();
+
+ @Id @GeneratedValue
+ public Integer getId() {
+ return id;
+ }
+
+ <emphasis role="bold">@CollectionOfElements
+ public Set<String></emphasis> getNickNames() {
+ return nickNames;
+ }
+
+ <emphasis role="bold">@CollectionOfElements
+ @JoinTable(
+ table=@Table(name="BoyFavoriteNumbers"),
+ joinColumns = @JoinColumn(name="BoyId")
+ )
+ @Column(name="favoriteNumber", nullable=false)</emphasis>
+ @IndexColumn(name="nbr_index")
+ public int[] getFavoriteNumbers() {
+ return favoriteNumbers;
+ }
+
+ <emphasis role="bold">@CollectionOfElements
+ @AttributeOverride( name="element.serial", column=@Column(name="serial_nbr") )</emphasis>
+ public Set<Toy> getFavoriteToys() {
+ return favoriteToys;
+ }
+
+ <emphasis role="bold">@CollectionOfElements
+ public Set<Character></emphasis> getCharacters() {
+ return characters;
+ }
+ ...
+}
+
+public enum Character {
+ GENTLE,
+ NORMAL,
+ AGGRESSIVE,
+ ATTENTIVE,
+ VIOLENT,
+ CRAFTY
+}
+
+ at Embeddable
+public class Toy {
+ public String name;
+ public String serial;
+ public Boy owner;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getSerial() {
+ return serial;
+ }
+
+ public void setSerial(String serial) {
+ this.serial = serial;
+ }
+
+ <emphasis role="bold">@Parent</emphasis>
+ public Boy getOwner() {
+ return owner;
+ }
+
+ public void setOwner(Boy owner) {
+ this.owner = owner;
+ }
+
+ public boolean equals(Object o) {
+ if ( this == o ) return true;
+ if ( o == null || getClass() != o.getClass() ) return false;
+
+ final Toy toy = (Toy) o;
+
+ if ( !name.equals( toy.name ) ) return false;
+ if ( !serial.equals( toy.serial ) ) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = name.hashCode();
+ result = 29 * result + serial.hashCode();
+ return result;
+ }
+}</programlisting>
+
+ <para>Sur une collection d'objets embarquables, l'objet embarquable
+ peut avoir une propriété annotée avec <literal>@Parent</literal>.
+ Cette propriété pointera alors vers l'entité contenant la
+ collection.</para>
+
+ <note>
+ <para>Les versions précédentes d'Hibernate Annotations utilisaient
+ <literal>@OneToMany</literal> pour marquer une collection
+ d'éléments. Suite à des incohérences sémantiques, nous avons mis en
+ place l'annotation <literal>@CollectionOfElements</literal>. Pour
+ marquer des collections d'éléments, l'ancienne façon fonctionne
+ encore mais elle est considérée comme "deprecated" et ne sera plus
+ prise en charge dans les futures versions.</para>
+ </note>
+ </sect4>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Cache</title>
+
+ <para>Pour optimiser vos accès à la base de données, vous pouvez activer
+ le cache de second niveau d'Hibernate. Ce cache est configurable par
+ entité et par collection.</para>
+
+ <para><literal>@org.hibernate.annotations.Cache</literal> définit la
+ stratégie de cache et la région du cache de second niveau donné. Cette
+ annotation peut être appliquée à une entité racine (pas les entités
+ filles), et sur les collections.</para>
+
+ <programlisting>@Entity
+ at Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
+public class Forest { ... }</programlisting>
+
+ <programlisting> @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
+ @JoinColumn(name="CUST_ID")
+ @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
+ public SortedSet<Ticket> getTickets() {
+ return tickets;
+ }</programlisting>
+
+ <para></para>
+
+ <programlistingco>
+ <areaspec>
+ <area coords="2 55" id="hm1" />
+
+ <area coords="3 55" id="hm2" />
+
+ <area coords="4 55" id="hm3" />
+ </areaspec>
+
+ <programlisting>@Cache(
+ CacheConcurrencyStrategy usage();
+ String region() default "";
+ String include() default "all";
+)</programlisting>
+
+ <calloutlist>
+ <callout arearefs="hm1">
+ <para>usage : la stratégie de concurrence du cache donné (NONE,
+ READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, TRANSACTIONAL) ;</para>
+ </callout>
+
+ <callout arearefs="hm2">
+ <para>region (optionnel) : la région du cache (par défaut le nom
+ complet de la classe avec le nom du package, ou le nom complet du
+ rôle de la collection) ;</para>
+ </callout>
+
+ <callout arearefs="hm3">
+ <para><literal>include</literal> (optionnel) : "all" pour inclure
+ toutes les propriétés, "non-lazy" pour inclure seulement les
+ propriétés qui ne sont pas chargées à la demande (valeur par
+ défaut : all).</para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+ </sect2>
+
+ <sect2 id="entity-hibspec-filters">
+ <title>Filtres</title>
+
+ <para>Hibernate a la capacité d'appliquer des filtres arbitraires à la
+ partie supérieure de vos données. Ces filtres sont appliqués au moment de
+ l'exécution sur une session donnée. Vous avez tout d'abord besoin de les
+ définir.</para>
+
+ <para><literal>@org.hibernate.annotations.FilterDef</literal> ou
+ <literal>@FilterDefs</literal> déclarent des définitions de filtre
+ utilisées par les filtres ayant le même nom. Une définition de filtre a
+ un name() et un tableau de parameters(). Un paramètre vous permettra
+ d'ajuster le comportement du filtre au moment de l'exécution. Chaque
+ paramètre est défini par une <literal>@ParamDef</literal> qui a un nom et
+ un type. Vous pouvez aussi définir un paramètre defaultCondition() pour
+ une <literal>@ParamDef</literal> donnée pour positionner la condition par
+ défaut à utiliser lorsqu'aucune n'est définie dans chaque
+ <literal>@Filter</literal> individuelle. Une <literal>@FilterDef</literal>
+ peut être définie au niveau de la classe ou du package.</para>
+
+ <para>Nous avons besoin de définir la clause du filtre SQL appliqué au
+ chargement de l'entité ou au chargement de la collection.
+ <literal>@Filter</literal> est utilisée et placée sur l'entité ou
+ l'élément de la collection.</para>
+
+ <para><programlisting>@Entity
+ at FilterDef(name="minLength", parameters={ @ParamDef( name="minLength", type="integer" ) } )
+ at Filters( {
+ @Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length"),
+ @Filter(name="minLength", condition=":minLength <= length")
+} )
+public class Forest { ... }</programlisting></para>
+
+ <para>Lorsque la collection utilise une table d'association comme
+ représentation relationnelle, vous pourriez vouloir appliquer la condition
+ du filtre à la table de l'association elle-même ou à la table de l'entité
+ cible. Pour appliquer la contrainte sur l'entité cible, utilisez
+ l'annotation habituelle <literal>@Filter</literal>. Cependant, si vous
+ voulez ciblez la table d'association, utilisez l'annotation
+ <literal>@FilterJoinTable</literal>.</para>
+
+ <programlisting> @OneToMany
+ @JoinTable
+ // filtre sur la table de l'entité cible
+ @Filter(name="betweenLength", condition=":minLength <= length and :maxLength >= length")
+ // filtre sur la table d'association
+ @FilterJoinTable(name="security", condition=":userlevel >= requredLevel")
+ public Set<Forest> getForests() { ... }</programlisting>
+ </sect2>
+
+ <sect2 id="entity-hibspec-query">
+ <title>Requête</title>
+
+ <para>Puisqu'Hibernate a plus de fonctionnalités sur les requêtes nommées
+ que définies dans la spécification EJB3,
+ <literal>@org.hibernate.annotations.NamedQuery</literal>,
+ <literal>@org.hibernate.annotations.NamedQueries</literal>,
+ <literal>@org.hibernate.annotations.NamedNativeQuery</literal> et
+ <literal>@org.hibernate.annotations.NamedNativeQueries</literal> ont été
+ mis en place. Elles ajoutent des attributs à la version standard et
+ peuvent être utilisées comme remplaçant :</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>flushMode : définit le mode de flush de la requête (Always,
+ Auto, Commit ou Never)</para>
+ </listitem>
+
+ <listitem>
+ <para>cacheable : indique si la requête devrait être cachée ou
+ non</para>
+ </listitem>
+
+ <listitem>
+ <para>cacheRegion : région du cache utilisée si la requête est
+ cachée</para>
+ </listitem>
+
+ <listitem>
+ <para>fetchSize : taille de l'expression de récupération JDBC pour
+ cette requête</para>
+ </listitem>
+
+ <listitem>
+ <para>timeout : timeout de la requête</para>
+ </listitem>
+
+ <listitem>
+ <para>callable : pour les requêtes natives seulement, mettre à true
+ pour les procédures stockées</para>
+ </listitem>
+
+ <listitem>
+ <para>comment : si les commentaires sont activés, le commentaire vu
+ lorsque la requête est envoyée vers la base de données</para>
+ </listitem>
+
+ <listitem>
+ <para>cacheMode : mode d'intéraction du cache (get, ignore, normal,
+ put ou refresh)</para>
+ </listitem>
+
+ <listitem>
+ <para>readOnly : indique si les éléments récupérés à partir de la
+ requête sont en lecture seule ou pas</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Ces indications de fonctionnement peuvent être positionnées sur
+ les annotations standards <literal>@javax.persistence.NamedQuery</literal>
+ avec l'annotation <literal>@QueryHint</literal>. Un autre avantage clef
+ est la possibilité de positionner ces annotations au niveau du
+ package.</para>
+ </sect2>
+ </sect1>
+</chapter>
Added: branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/lucene.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/lucene.xml 2006-10-27 19:56:30 UTC (rev 10655)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/lucene.xml 2006-10-27 20:03:29 UTC (rev 10656)
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<chapter id="lucene" revision="1">
+ <title>Intégration de Lucene avec Hibernate</title>
+
+ <para>Lucene est une bibliothèque de la fondation Apache fournissant un moteur
+ de recherche en Java hautement performant. Hibernate Annotations inclut un
+ ensemble d'annotations qui vous permettent de marquer n'importe quel objet
+ du modèle de données comme indexable et de laisser Hibernate maintenir un
+ index Lucene de toutes les instances persistées via Hibernate.</para>
+
+ <para>Hibernate Lucene est un projet en cours et de nouvelles fonctionnalités
+ sont en préparation. Donc attendez-vous à certains changements avec les
+ versions ultérieures.</para>
+
+ <section id="lucene-mapping">
+ <title>Mapper les entités sur l'index</title>
+
+ <para>Tout d'abord, nous devons déclarer une classe persistante comme
+ étant indexable. Ceci se fait en annotant la classe avec
+ <literal>@Indexed</literal> :</para>
+
+ <programlisting>@Entity
+ at Indexed(index="indexes/essays")
+public class Essay {
+ ...
+}</programlisting>
+
+ <para>L'attribut <literal>index</literal> indique à Hibernate quel est le
+ nom du répertoire Lucene (en général un répertoire de votre système de
+ fichiers). Si vous souhaitez définir un répertoire de départ pour tous vos
+ index Lucene, vous pouvez utiliser la propriété
+ <literal>hibernate.lucene.default.indexDir</literal> dans votre fichier de
+ configuration.</para>
+
+ <para>Les index Lucene contiennent quatre types de champs :
+ <emphasis>keyword</emphasis>, <emphasis>text</emphasis>,
+ <emphasis>unstored</emphasis> et <emphasis>unindexed</emphasis>. Hibernate
+ Annotations fournit des annotations pour marquer une propriété d'une entité
+ comme étant d'un des trois premiers types.</para>
+
+ <programlisting>@Entity
+ at Indexed(index="indexes/essays")
+public class Essay {
+ ...
+
+ @Id
+ @Keyword(id=true)
+ public Long getId() { return id; }
+
+ @Text(name="Abstract")
+ public String getSummary() { return summary; }
+
+ @Lob
+ @Unstored
+ public String getText() { return text; }
+
+}</programlisting>
+
+ <para>Ces annotations définissent un index avec trois champs :
+ <literal>id</literal>, <literal>Abstract</literal> et
+ <literal>text</literal>. Notez que par défaut le nom du champ n'a plus de
+ majuscules, en suivant la spécification JavaBean.</para>
+
+ <para>Note : vous <emphasis>devez</emphasis> spécifier
+ <literal>@Keyword(id=true)</literal> sur la propriété identifiante de
+ votre entité.</para>
+
+ <para>Lucene a la notion of <emphasis>boost factor</emphasis>. C'est un
+ moyen de donner plus de poids à un champ ou à un élément indexé durant la
+ procédure d'indexation. Vous pouvez utiliser <literal>@Boost</literal> au
+ niveau du champ ou de la classe.</para>
+
+ <para>La classe analyste utilisée pour indexer les éléments est
+ configurable par la propriété
+ <literal>hibernate.lucene.analyzer</literal>. Si aucune n'est définie,
+ <classname>org.apache.lucene.analysis.standard.StandardAnalyzer</classname>
+ est utilisée par défaut.</para>
+ </section>
+
+ <section id="lucene-configuration">
+ <title>Configuration</title>
+
+ <section id="lucene-configuration-directory">
+ <title>Configuration du directory</title>
+
+ <para>Lucene a une notion de Directory où l'index est stocké.
+ L'implémentation de Directory peut être personnalisée mais Lucene arrive,
+ avec deux implémentations prêtes à l'emploi complètes, une sur un système
+ de fichiers et une en mémoire. Hibernate Lucene a la notion de
+ <literal>DirectoryProvider</literal> qui gère la configuration et
+ l'initialisation du Directory Lucene.</para>
+
+ <table>
+ <title>Liste des Directory Providers intégrés</title>
+
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry align="center">Classe</entry>
+
+ <entry align="center">Description</entry>
+
+ <entry align="center">Propriétés</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>org.hibernate.lucene.store.FSDirectoryProvider</entry>
+
+ <entry>Directory base sur le système de fichiers. Le répertoire
+ utilisé sera
+ <indexBase>/<<literal>@Index.name</literal>></entry>
+
+ <entry><literal>indexBase</literal> : répertoire de départ</entry>
+ </row>
+
+ <row>
+ <entry>org.hibernate.lucene.store.RAMDirectoryProvider</entry>
+
+ <entry>Directory utilisant la mémoire, le directory sera
+ uniquement identifié par l'élément
+ <literal>@Index.name</literal></entry>
+
+ <entry>aucune</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>Si les directory providers intégrés ne répondent pas à vos besoins,
+ vous pouvez écrire votre propre directory provider en implémentant
+ l'interface
+ <classname>org.hibernate.store.DirectoryProvider</classname>.</para>
+
+ <para>Chaque entité indexée est associée à un index Lucene (un index peut
+ être partagé par différentes entités mais ce n'est pas le cas en général).
+ Vous pouvez configurer l'index à travers des propriétés préfixées par
+ <literal><literal>hibernate.lucene.<indexname></literal></literal>.
+ Les propriétés par défaut héritées par tous les index peuvent être
+ définies en utilisant le préfixe hibernate.lucene.default.</para>
+
+ <para>Pour définir le directory provider d'un index donné, utilisez
+ <literal>hibernate.lucene.<indexname>.directory_provider</literal>.</para>
+
+ <programlisting>hibernate.lucene.default.directory_provider org.hibernate.lucene.store.FSDirectoryProvider
+hibernate.lucene.default.indexDir=/usr/lucene/indexes
+
+hibernate.lucene.Rules.directory_provider org.hibernate.lucene.store.RAMDirectoryProvider
+</programlisting>
+
+ <para>appliqué à</para>
+
+ <programlisting>@Indexed(name="Status")
+public class Status { ... }
+
+ at Indexed(name="Rules")
+public class Rule { ... }</programlisting>
+
+ <para>Ceci créera un directory système de fichiers dans
+ <filename>/usr/lucene/indexes/Status</filename> où les entités Status
+ seront indexées, et utilisera un directory mémoire nommé
+ <literal>Rules</literal> où les entités Rule seront indexées.</para>
+
+ <para>Donc vous pouvez facilement définir des règles générales comme le
+ directory provider et le répertoire de départ, et surcharger ces valeurs
+ par défaut plus tard pour chaque index.</para>
+
+ <para>En écrivant votre propre DirectoryProvider, vous pouvez aussi
+ bénéficier de ce mécanisme de configuration.</para>
+ </section>
+
+ <section id="lucene-configuration-event">
+ <title>Activer l'indexation automatique</title>
+
+ <para>Finalement, nous activons le <literal>LuceneEventListener</literal>
+ pour les trois événements Hibernate qui ont lieu après que les changements
+ sont validés dans la base de données.</para>
+
+ <programlisting><hibernate-configuration>
+ ...
+ <event type="post-commit-update"
+ <listener
+ class="org.hibernate.lucene.event.LuceneEventListener"/>
+ </event>
+ <event type="post-commit-insert"
+ <listener
+ class="org.hibernate.lucene.event.LuceneEventListener"/>
+ </event>
+ <event type="post-commit-delete"
+ <listener
+ class="org.hibernate.lucene.event.LuceneEventListener"/>
+ </event>
+</hibernate-configuration></programlisting>
+ </section>
+ </section>
+</chapter>
\ No newline at end of file
Added: branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/setup.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/setup.xml 2006-10-27 19:56:30 UTC (rev 10655)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/setup.xml 2006-10-27 20:03:29 UTC (rev 10656)
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<chapter>
+ <title id="setup" revision="1">Configurer un projet avec des annotations</title>
+
+ <section id="setup-requirements">
+ <title>Prérequis</title>
+
+ <itemizedlist>
+ <listitem>
+ <para>Téléchargez et installez la distribution Hibernate Annotations à
+ partir du site web d'Hibernate.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>Cette version requiert Hibernate 3.2.0.GA ou
+ supérieur. N'utilisez pas cette version d'Hibernate Annotations avec
+ une version plus ancienne d'Hibernate 3.x !</emphasis></para>
+ </listitem>
+
+ <listitem>
+ <para>Cette version est connue pour fonctionner avec le noyau 3.2.0.CR5
+ et 3.2.0.GA d'Hibernate.</para>
+ </listitem>
+
+ <listitem>
+ <para>Assurez-vous que vous avez le JDK 5.0 d'installé. Vous pouvez
+ bien sûr continuer à utiliser XDoclet et avoir certains des avantages
+ des méta-données basées sur les annotations avec des versions plus
+ anciennes du JDK. Notez que ce document décrit seulement les annotations
+ du JDK 5.0 et que vous devez vous référer à la documentation de XDoclet
+ pour plus d'informations.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="setup-configuration">
+ <title>Configuration</title>
+
+ <para>Tout d'abord, paramétrez votre classpath (après avoir créer un nouveau
+ projet dans votre IDE favori) :<itemizedlist>
+ <listitem>
+ <para>Copiez toutes les bibliothèques du noyau Hibernate3 et toutes
+ les bibliothèques tierces requises (voir lib/README.txt dans
+ Hibernate).</para>
+ </listitem>
+
+ <listitem>
+ <para>Copiez aussi <filename>hibernate-annotations.jar</filename> et
+ <filename>lib/ejb3-persistence.jar</filename> de la distribution
+ Hibernate Annotations dans votre classpath.</para>
+ </listitem>
+
+ <listitem>
+ <para>Pour utiliser <xref linkend="lucene" />, ajouter le fichier jar
+ de lucene.</para>
+ </listitem>
+ </itemizedlist></para>
+
+ <para>Nous recommandons aussi un petit wrapper pour démarrer Hibernate dans
+ un bloc statique d'initialisation, connu en tant que
+ <classname>HibernateUtil</classname>. Vous pourriez avoir vu cette classe
+ sous diverses formes dans d'autres parties de la documentation Hibernate.
+ Pour prendre en charge Annotation vous devez modifier cette classe d'aide
+ de la manière suivante :<programlisting>package hello;
+
+import org.hibernate.*;
+import org.hibernate.cfg.*;
+import test.*;
+import test.animals.Dog;
+
+public class HibernateUtil {
+
+private static final SessionFactory sessionFactory;
+
+ static {
+ try {
+
+ sessionFactory = new <emphasis role="bold">AnnotationConfiguration()</emphasis>.buildSessionFactory();
+ } catch (Throwable ex) {
+ // Log exception!
+ throw new ExceptionInInitializerError(ex);
+ }
+ }
+
+ public static Session getSession()
+ throws HibernateException {
+ return sessionFactory.openSession();
+ }
+}
+ </programlisting></para>
+
+ <para>La partie intéressante ici est l'utilisation de
+ <classname>AnnotationConfiguration</classname>. Les packages et les classes
+ annotées sont déclarés dans votre fichier de configuration XML habituel
+ (généralement <filename>hibernate.cfg.xml</filename>). Voici un équivalent
+ de la déclaration ci-dessus :</para>
+
+ <programlisting><!DOCTYPE hibernate-configuration PUBLIC
+ "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+
+ <hibernate-configuration>
+ <session-factory>
+ <emphasis role="bold"><mapping package="test.animals"/>
+ <mapping class="test.Flight"/>
+ <mapping class="test.Sky"/>
+ <mapping class="test.Person"/>
+ <mapping class="test.animals.Dog"/></emphasis>
+<emphasis role="bold"> <mapping resource="test/animals/orm.xml"/></emphasis>
+ </session-factory>
+ </hibernate-configuration>
+ </programlisting>
+
+ <para>Notez que vous pouvez mélanger l'utilisation du fichier hbm.xml et
+ celle des annotations. L'élément de ressource peut être un fichier hbm ou
+ un descripteur de déploiement XML EJB3. Cette distinction est transparente
+ pour votre procédure de configuration.</para>
+
+ <para>Alternativement, vous pouvez définir les classes annotées et des
+ packages en utilisant l'API :</para>
+
+ <programlisting> sessionFactory = new <emphasis role="bold">AnnotationConfiguration()
+ .addPackage("test.animals") // le nom complet du package
+ .addAnnotatedClass(Flight.class)
+ .addAnnotatedClass(Sky.class)
+ .addAnnotatedClass(Person.class)
+ .addAnnotatedClass(Dog.class)</emphasis>
+<emphasis role="bold"> .addResource("test/animals/orm.xml")</emphasis>
+ .buildSessionFactory();</programlisting>
+
+ <para>Vous pouvez aussi utiliser Hibernate EntityManager qui a son propre
+ mécanisme de configuration. Veullez vous référer à la documentation de ce
+ projet pour plus de détails.</para>
+
+ <para>Il n'y a pas d'autres différences dans la façon d'utiliser les APIs
+ d'Hibernate, excepté ce changement de routine de démarrage ou le fichier
+ de configuration. Vous pouvez utiliser votre méthode de configuration
+ favorite pour d'autres propriétés (<filename>hibernate.properties</filename>,
+ <filename>hibernate.cfg.xml</filename>, utilisation des APIs, etc). Vous
+ pouvez même mélanger les classes persistantes annotées et des déclarations
+ <filename>hbm.cfg.xml</filename> classiques avec la même
+ <classname>SessionFactory</classname>. Vous ne pouvez cependant pas déclarer
+ une classe plusieurs fois (soit avec les annotations, soit avec un fichier
+ hbm.xml). Vous ne pouvez pas non plus mélanger des stratégies de
+ configuration (hbm vs annotations) dans une hiérarchie d'entités
+ mappées.</para>
+
+ <para>Pour faciliter la procédure de migration de fichiers hbm vers les
+ annotations, le mécanisme de configuration détecte la duplication de mappings
+ entre les annotations et les fichiers hbm. Les classes décrites dans les
+ fichiers hbm se voient alors affecter une priorité plus grande que les
+ classes annotées. Vous pouvez changer cette priorité avec la propriété
+ <literal>hibernate.mapping.precedence</literal>. La valeur par défaut est :
+ <literal>hbm, class</literal> ; la changer en : <literal>class, hbm</literal>
+ donne alors la priorité aux classes annotées lorsqu'un conflit
+ survient.</para>
+ </section>
+</chapter>
\ No newline at end of file
Added: branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/validator.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/validator.xml 2006-10-27 19:56:30 UTC (rev 10655)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/validator.xml 2006-10-27 20:03:29 UTC (rev 10656)
@@ -0,0 +1,569 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<chapter id="validator">
+ <title>Hibernate Validator</title>
+
+ <para>Les annotations sont une manière très commode et élégante pour spécifier
+ des contraintes invariantes sur un modèle de données. Vous pouvez, par
+ exemple, indiquer qu'une propriété ne devrait pas être nulle, que le solde
+ d'un compte devrait être strictement positif, etc. Ces contraintes de modèle
+ de données sont déclarées dans le bean lui-même en annotant ses propriétés.
+ Un validateur peut alors les lire et vérifier les violations de contraintes.
+ Le mécanisme de validation peut être exécuté dans différentes couches de
+ votre application (présentation, accès aux données) sans devoir dupliquer
+ ces règles. Hibernate Validator a été conçu dans ce but.</para>
+
+ <para>Hibernate Validator fonctionne sur deux niveaux. D'abord, il est capable
+ de vérifier des violations de contraintes sur les instances d'une classe en
+ mémoire. Ensuite, il peut appliquer les contraintes au méta-modèle d'Hibernate
+ et les incorporer au schéma de base de données généré.</para>
+
+ <para>Chaque annotation de contrainte est associée à l'implémentation du
+ validateur responsable de vérifier la contrainte sur l'instance de l'entité.
+ Un validateur peut aussi (optionnellement) appliquer la contrainte au
+ méta-modèle d'Hibernate, permettant à Hibernate de générer le DDL qui
+ exprime la contrainte. Avec le listener d'événements approprié, vous pouvez
+ exécuter l'opération de vérification lors des insertions et des mises à jour
+ effectuées par Hibernate. Hibernate Validator n'est pas limité à Hibernate.
+ Vous pouvez facilement l'utiliser n'importe où dans votre application.</para>
+
+ <para>Lors de la vérification des instances à l'exécution, Hibernate Validator
+ retourne des informations à propos des violations de contraintes dans un
+ tableau de <classname>InvalidValue</classname>s. Parmi d'autres informations,
+ <classname>InvalidValue</classname> contient un message de description
+ d'erreur qui peut inclure les valeurs des paramètres associés à l'annotation
+ (p. ex. la limite de taille), et des chaînes de caractères qui peuvent être
+ externalisées avec un <classname>ResourceBundle</classname>.</para>
+
+ <sect1 id="validator-constraints">
+ <title>Contraintes</title>
+
+ <sect2>
+ <title>Qu'est-ce qu'une contrainte ?</title>
+
+ <para>Une contrainte est représentée par une annotation. Une contrainte a
+ généralement des attributs utilisés pour paramétrer les limites des
+ contraintes. La contrainte s'applique à l'élément annoté.</para>
+ </sect2>
+
+ <sect2>
+ <title>Contraintes intégrées</title>
+
+ <para>Hibernate Validator arrive avec des contraintes intégrées,
+ lesquelles couvrent la plupart des vérifications de données de base. Comme
+ nous le verrons plus tard, vous n'êtes pas limité à celles-ci, vous pouvez
+ écrire vos propres contraintes en une minute.</para>
+
+ <table>
+ <title>Contraintes intégrées</title>
+
+ <tgroup cols="4">
+ <colspec align="center" />
+
+ <thead>
+ <row>
+ <entry>Annotation</entry>
+
+ <entry>S'applique à</entry>
+
+ <entry>Vérification à l'exécution</entry>
+
+ <entry>Impact sur les méta-données d'Hibernate</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>@Length(min=, max=)</entry>
+
+ <entry>propriété (String)</entry>
+
+ <entry>vérifie si la longueur de la chaîne de caractères est
+ comprise dans l'intervalle</entry>
+
+ <entry>la longueur de la colonne sera positionnée à max</entry>
+ </row>
+
+ <row>
+ <entry>@Max(value=)</entry>
+
+ <entry>propriété (nombre ou chaîne de caractères représentant un
+ nombre)</entry>
+
+ <entry>vérifie si la valeur est inférieure ou égale à max</entry>
+
+ <entry>ajoute une contrainte de vérification sur la
+ colonne</entry>
+ </row>
+
+ <row>
+ <entry>@Min(value=)</entry>
+
+ <entry>propriété (nombre ou chaîne de caractères représentant un
+ nombre)</entry>
+
+ <entry>vérifie si la valeur est supérieure ou égale à max</entry>
+
+ <entry>ajoute une contrainte de vérification sur la
+ colonne</entry>
+ </row>
+
+ <row>
+ <entry>@NotNull</entry>
+
+ <entry>propriété</entry>
+
+ <entry>vérifie si la valeur n'est pas nulle</entry>
+
+ <entry>les colonnes sont marquées "not null"</entry>
+ </row>
+
+ <row>
+ <entry>@Past</entry>
+
+ <entry>propriété (Date ou Calendar)</entry>
+
+ <entry>vérifie si la date est dans le passé</entry>
+
+ <entry>ajoute une contrainte de vérification sur la
+ colonne</entry>
+ </row>
+
+ <row>
+ <entry>@Future</entry>
+
+ <entry>propriété (Date ou Calendar)</entry>
+
+ <entry>vérifie si la date est dans le futur</entry>
+
+ <entry>aucun</entry>
+ </row>
+
+ <row>
+ <entry>@Pattern(regex="regexp", flag=)</entry>
+
+ <entry>propriété (String)</entry>
+
+ <entry>vérifie si la propriété correspond à l'expression
+ rationnelle donnée (pour "flag", voir
+ <classname> java.util.regex.Pattern</classname>)</entry>
+
+ <entry>aucun</entry>
+ </row>
+
+ <row>
+ <entry>@Range(min=, max=)</entry>
+
+ <entry>propriété (nombre ou chaîne de caractères représentant un
+ nombre)</entry>
+
+ <entry>vérifie si la valeur est comprise entre min et max
+ (inclus)</entry>
+
+ <entry>ajoute une contrainte de vérification sur la
+ colonne</entry>
+ </row>
+
+ <row>
+ <entry>@Size(min=, max=)</entry>
+
+ <entry>propriété (tableau, collection, map)</entry>
+
+ <entry>vérifie si la taille de l'élément est comprise entre min et
+ max (inclus)</entry>
+
+ <entry>aucun</entry>
+ </row>
+
+ <row>
+ <entry>@AssertFalse</entry>
+
+ <entry>propriété</entry>
+
+ <entry>vérifie que la méthode est évaluée à faux (utile pour les
+ contraintes exprimées dans le code plutôt que dans les
+ annotations)</entry>
+
+ <entry>aucun</entry>
+ </row>
+
+ <row>
+ <entry>@AssertTrue</entry>
+
+ <entry>propriété</entry>
+
+ <entry>vérifie que la méthode est évaluée à vrai (utile pour les
+ contraintes exprimées dans le code plutôt que dans les
+ annotations)</entry>
+
+ <entry>aucun</entry>
+ </row>
+
+ <row>
+ <entry>@Valid</entry>
+
+ <entry>propriété (objet)</entry>
+
+ <entry>exécute la validation récursivement sur l'objet associé.
+ Si l'objet est une Collection ou un tableau, les éléments sont
+ validés récursivement. Si l'objet est une Map, les éléments
+ valeur sont validés récursivement.</entry>
+
+ <entry>aucun</entry>
+ </row>
+
+ <row>
+ <entry>@Email</entry>
+
+ <entry>propriété (String)</entry>
+
+ <entry>vérifie si la chaîne de caractères est conforme à la
+ spécification d'une adresse e-mail</entry>
+
+ <entry>aucun</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </sect2>
+
+ <sect2 id="validator-constraints-error" xreflabel="Messages d'erreur">
+ <title>Messages d'erreur</title>
+
+ <para>Hibernate Validator arrive avec un ensemble de messages d'erreur par
+ défaut traduits dans environ dix langues (si la vôtre n'en fait pas
+ partie, veuillez nous envoyer un patch). Vous pouvez surcharger ces
+ messages en créant un <filename>ValidatorMessages.properties</filename>
+ (ou <filename>ValidatorMessages_loc.properties</filename>) et en
+ surchargeant les clefs dont vous avez besoin. Vous pouvez même ajouter
+ votre propre ensemble de messages supplémentaire lorsque vous écrivez
+ vos annotations de validation. Si Hibernate Validator ne peut pas trouver
+ une clef à partir de votre resourceBundle ou de votre ValidatorMessage,
+ il se repliera sur les valeurs intégrées par défaut.</para>
+
+ <para>Alternativement vous pouvez fournir un
+ <classname>ResourceBundle</classname> pendant la vérification par
+ programmation des règles de validation sur un bean, ou si vous voulez un
+ mécanisme d'interpolation complètement différent, vous pouvez fournir une
+ implémentation de
+ <literal>org.hibernate.validator.MessageInterpolator</literal> (lisez la
+ JavaDoc pour plus d'informations).</para>
+ </sect2>
+
+ <sect2>
+ <title>Ecrire vos propres contraintes</title>
+
+ <para>Etendre l'ensemble de contraintes intégrées est extrêment facile.
+ N'importe quelle contrainte est constituée deux morceaux : le
+ <emphasis>descripteur</emphasis> de contrainte (l'annotation) et le
+ <emphasis>validateur</emphasis> de contrainte (la classe
+ d'implémentation). Voici un simple descripteur personnalisé :</para>
+
+ <programlisting>@ValidatorClass(CapitalizedValidator.class)
+ at Target(METHOD)
+ at Retention(RUNTIME)
+ at Documented
+public @interface Capitalized {
+ CapitalizeType type() default Capitalize.FIRST;
+ String message() default "has incorrect capitalization";
+}</programlisting>
+
+ <para><literal>type</literal> est un paramètre décrivant comment la
+ propriété devrait être mise en majuscule. Ceci est un paramètre
+ utilisateur complètement dépendant du fonctionnement de
+ l'annotation.</para>
+
+ <para><literal>message</literal> est la chaîne de caractères par défaut
+ utilisée pour décrire la violation de contrainte et est obligatoire. Vous
+ pouvez mettre la chaîne de caractères dans le code ou bien l'externaliser
+ en partie ou complètement avec le mécanisme ResourceBundle Java. Les
+ valeurs des paramètres sont injectées à l'intérieur du message quand
+ la chaîne de caractères <literal>{parameter}</literal> est trouvée (dans
+ notre exemple <literal>Capitalization is not {type}</literal> générerait
+ <literal>Capitalization is not FIRST</literal>), externaliser toute la
+ chaîne dans <filename>ValidatorMessages.properties</filename> est
+ considéré comme une bonne pratique. Voir <xref
+ linkend="validator-constraints-error" />.</para>
+
+ <programlisting>@ValidatorClass(CapitalizedValidator.class)
+ at Target(METHOD)
+ at Retention(RUNTIME)
+ at Documented
+public @interface Capitalized {
+ CapitalizeType type() default Capitalize.FIRST;
+ String message() default "{validator.capitalized}";
+}
+
+...
+#in ValidatorMessages.properties
+validator.capitalized=<literal>Capitalization is not {type}</literal></programlisting>
+
+ <para>Comme vous pouvez le voir la notation {} est récursive.</para>
+
+ <para>Pour lier un descripteur à l'implémentation de son validateur, nous
+ utilisons la méta-annotation <literal>@ValidatorClass</literal>. Le
+ paramètre de la classe du validateur doit nommer une classe qui implémente
+ <literal>Validator<ConstraintAnnotation></literal>.</para>
+
+ <para>Nous devons maintenant implémenter le validateur (ie
+ l'implémentation vérifiant la règle). Une implémentation de validation
+ peut vérifier la valeur d'une propriété (en implémentant
+ <literal>PropertyConstraint</literal>) et/ou peut modifier les
+ méta-données de mapping d'Hibernate pour exprimer la contrainte au niveau
+ de la base de données (en implémentant
+ <literal>PersistentClassConstraint</literal>).</para>
+
+ <programlisting>public class CapitalizedValidator
+ implements Validator<Capitalized>, PropertyConstraint {
+ private CapitalizeType type;
+
+ // partie du contrat de Validator<Annotation>,
+ // permet d'obtenir et d'utiliser les valeurs de l'annotation
+ public void initialize(Capitalized parameters) {
+ type = parameters.type();
+ }
+
+ // partie du contrat de la contrainte de la propriété
+ public boolean isValid(Object value) {
+ if (value==null) return true;
+ if ( !(value instanceof String) ) return false;
+ String string = (String) value;
+ if (type == CapitalizeType.ALL) {
+ return string.equals( string.toUpperCase() );
+ }
+ else {
+ String first = string.substring(0,1);
+ return first.equals( first.toUpperCase();
+ }
+ }
+}</programlisting>
+
+ <para>La méthode <literal>isValid()</literal> devrait retourner false si
+ la contrainte a été violée. Pour plus d'exemples, référez-vous aux
+ implémentations intégrées du validateur.</para>
+
+ <para>Nous avons seulement vu la validation au niveau propriété, mais vous
+ pouvez écrire une annotation de validation au niveau d'un bean. Plutôt
+ que de recevoir l'instance de retour d'une propriété, le bean lui-même
+ sera passé au validateur. Pour activer la vérification de validation,
+ annotez juste le bean lui-même. Un petit exemple peut être trouvé dans la
+ suite de tests unitaires.</para>
+ </sect2>
+
+ <sect2>
+ <title>Annoter votre modèle de données</title>
+
+ <para>Maintenant que vous vous êtes familiarisés avec les annotations, la
+ syntaxe devrait être connue.</para>
+
+ <programlisting>public class Address {
+ private String line1;
+ private String line2;
+ private String zip;
+ private String state;
+ private String country;
+ private long id;
+
+ // une chaîne non nulle de 20 caractères maximum
+ @Length(max=20)
+ @NotNull
+ public String getCountry() {
+ return country;
+ }
+
+ // une chaîne de caractères non nulle
+ @NotNull
+ public String getLine1() {
+ return line1;
+ }
+
+ // pas de contrainte
+ public String getLine2() {
+ return line2;
+ }
+
+ // une chaîne non nulle de 3 caractères maximum
+ @Length(max=3) @NotNull
+ public String getState() {
+ return state;
+ }
+
+ // une chaîne non nulle de 5 caractères maximum représentant un nombre
+ // si la chaîne de caractères est plus longue, le message sera recherché
+ // dans le resource bundle avec la clef 'long'
+ @Length(max=5, message="{long}")
+ @Pattern(regex="[0-9]+")
+ @NotNull
+ public String getZip() {
+ return zip;
+ }
+
+ // devrait toujours être vrai
+ @AssertTrue
+ public boolean isValid() {
+ return true;
+ }
+
+ // un nombre entre 1 et 2000
+ @Id @Min(1)
+ @Range(max=2000)
+ public long getId() {
+ return id;
+ }
+}</programlisting>
+
+ <para>Bien que l'exemple montre seulement la validation de propriétés
+ publiques, vous pouvez aussi annoter des champs avec n'importe quelle
+ visibilité.</para>
+
+ <programlisting>@MyBeanConstraint(max=45)
+public class Dog {
+ @AssertTrue private boolean isMale;
+ @NotNull protected String getName() { ... };
+ ...
+}</programlisting>
+
+ <para>Vous pouvez aussi annoter des inferfaces. Hibernate Validator
+ vérifiera toutes les classes parentes et les interfaces héritées ou
+ implémentées par un bean donné pour lire les annotations appropriées du
+ validateur.</para>
+
+ <programlisting>public interface Named {
+ @NotNull String getName();
+ ...
+}
+
+public class Dog implements Named {
+
+ @AssertTrue private boolean isMale;
+
+ public String getName() { ... };
+
+}</programlisting>
+
+ <para>La propriété "name" sera vérifiée pour la nullité lorsque le bean
+ Dog sera validé.</para>
+ </sect2>
+ </sect1>
+
+ <sect1>
+ <title>Utiliser le framework Validator</title>
+
+ <para>Hibernate Validator est destiné à être utilisé pour implémenter une
+ validation de données à plusieurs couches, où nous exprimons des contraintes
+ à un seul endroit (le modèle de données annoté) et les appliquons aux
+ différents niveaux de l'application.</para>
+
+ <sect2>
+ <title>Validation au niveau du schéma de la base de données</title>
+
+ <para>Par défaut, Hibernate Annotations traduira les contraintes que vous
+ avez définies sur vos entités en méta-données de mapping. Par exemple, si
+ une propriété de votre entité est annotée avec
+ <literal>@NotNull</literal>, ses colonnes seront déclarées comme
+ <literal>not null</literal> dans le schéma DDL généré par
+ Hibernate.</para>
+ </sect2>
+
+ <sect2>
+ <title>La validation basée sur les événements Hibernate</title>
+
+ <para>Hibernate Validator a deux listeners d'événements Hibernate
+ intégrés. Quand un <literal>PreInsertEvent</literal> ou un
+ <literal>PreUpdateEvent</literal> survient, les listeners vérifieront
+ toutes les contraintes de l'instance de l'entité et lèveront une exception
+ si une contrainte est violée. Fondamentalement, les objets seront vérifiés
+ avant les insertions et avant les mises à jour effectuées par Hibernate.
+ C'est le plus commode et la manière la plus simple d'activer le processus
+ de validation. Sur une violation de contrainte, l'événement lèvera une
+ exception d'exécution <classname>InvalidStateException</classname> (NdT :
+ c'est une RuntimeException) laquelle contient un tableau
+ d'<literal>InvalidValue</literal>s décrivant chaque échec.</para>
+
+ <programlisting><hibernate-configuration>
+ ...
+ <event type="pre-update">
+ <listener
+ class="org.hibernate.validator.event.ValidatePreUpdateEventListener"/>
+ </event>
+ <event type="pre-insert">
+ <listener
+ class="org.hibernate.validator.event.ValidatePreInsertEventListener"/>
+ </event>
+</hibernate-configuration></programlisting>
+
+ <note>
+ <para>Lors de l'utilisation d'Hibernate Entity Manager, le framework
+ Validation est activé par défaut. Si les beans ne sont pas annotés avec
+ des annotations de validation, il n'y a pas de coût en terme de
+ performance.</para>
+ </note>
+ </sect2>
+
+ <sect2>
+ <title>La validation au niveau applicatif</title>
+
+ <para>Hibernate Validator peut être utilisé n'importe où dans le code de
+ votre application.</para>
+
+ <programlisting>ClassValidator personValidator = new ClassValidator( Person.class );
+ClassValidator addressValidator = new ClassValidator( Address.class, ResourceBundle.getBundle("messages", Locale.ENGLISH) );
+
+InvalidValue[] validationMessages = addressValidator.getInvalidValues(address);</programlisting>
+
+ <para>Les deux premières lignes préparent Hibernate Validator pour la
+ vérification de classes. La première s'appuie sur les messages d'erreur
+ intégrés à Hibernate Validator (voir
+ <xref linkend="validator-constraints-error" />), la seconde utilise un
+ resource bundle pour ses messages. Il est considéré comme une bonne
+ pratique d'exécuter ces lignes une fois et de cacher les instances de
+ validateur.</para>
+
+ <para>La troisième ligne valide en fait l'instance
+ <literal>Address</literal> et retourne un tableau
+ d'<literal>InvalidValue</literal>s. Votre logique applicative sera alors
+ capable de réagir aux échecs.</para>
+
+ <para>Vous pouvez aussi vérifier une propriété particulière plutôt que
+ tout le bean. Ceci pourrait être utile lors d'interactions avec
+ l'utilisateur propriété par propriété.</para>
+
+ <programlisting>ClassValidator addressValidator = new ClassValidator( Address.class, ResourceBundle.getBundle("messages", Locale.ENGLISH) );
+
+// récupère seulement les valeurs invalides de la propriété "city"
+InvalidValue[] validationMessages = addressValidator.getInvalidValues(address, "city");
+
+// récupère seulement les valeurs potentielles invalides de la propriété "city"
+InvalidValue[] validationMessages = addressValidator.getPotentialInvalidValues("city", "Paris")</programlisting>
+ </sect2>
+
+ <sect2>
+ <title>Informations de validation</title>
+
+ <para>Comme un transporteur d'informations de validation, Hibernate
+ fournit un tableau d'<classname>InvalidValue</classname>s. Chaque
+ <literal>InvalidValue</literal> a un groupe de méthodes décrivant les
+ problèmes individuels.</para>
+
+ <para><methodname>getBeanClass()</methodname> récupère le type du bean
+ ayant échoué.</para>
+
+ <para><methodname>getBean()</methodname> récupère l'instance du bean ayant
+ échoué (s'il y en a, c'est-à-dire pas lors de l'utilisation de
+ <methodname>getPotentianInvalidValues()</methodname>).</para>
+
+ <para><methodname>getValue()</methodname> récupère la valeur ayant
+ échouée.</para>
+
+ <para><methodname>getMessage()</methodname> récupère le message d'erreur
+ internationalisé.</para>
+
+ <para><methodname>getRootBean()</methodname> récupère l'instance du bean
+ racine ayant généré le problème (utile en conjonction avec
+ <literal>@Valid</literal>), est nulle si getPotentianInvalidValues() est
+ utilisée.</para>
+
+ <para><literal>getPropertyPath()</literal> récupère le chemin (séparé par
+ des points) de la propriété ayant échouée à partir du bean racine.</para>
+ </sect2>
+ </sect1>
+</chapter>
\ No newline at end of file
Added: branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/xml-overriding.xml
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/xml-overriding.xml 2006-10-27 19:56:30 UTC (rev 10655)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/modules/xml-overriding.xml 2006-10-27 20:03:29 UTC (rev 10656)
@@ -0,0 +1,413 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<chapter id="xml-overriding">
+ <title>Surcharger des méta-données à travers du XML</title>
+
+ <para>La cible primaire pour les méta-données dans EJB3 sont les annotations,
+ mais la spécification EJB3 fournit un moyen de surcharger ou remplacer les
+ méta-données définies par des annotations à travers un descripteur de
+ déploiement XML. Dans la version courante, seule la surcharge des annotations
+ pure EJB3 est prise en charge. Si vous souhaitez utiliser des caractéristiques
+ spécifiques à Hibernate dans des entités, vous devrez utiliser les annotations
+ ou vous replier sur les fichiers hbm. Vous pouvez bien sûr mélanger et faire
+ correspondre des entités annotées et des entités décrites dans des fichiers
+ hbm.</para>
+
+ <para>La suite de test unitaires montre des exemples supplémentaires de
+ fichier XML.</para>
+
+ <section id="xml-overriding-principles">
+ <title>Principes</title>
+
+ <para>La structure du descripteur de déploiement XML a été conçue pour
+ refléter celle des annotations. Donc si vous connaissez la structure des
+ annotations, utiliser le schéma XML sera facile pour vous.</para>
+
+ <para>Vous pouvez définir un ou plusieurs fichiers XML décrivant vos
+ méta-données, ces fichiers seront fusionnés par le moteur de surcharge.</para>
+
+ <section>
+ <title>Méta-données de niveau global</title>
+
+ <para>Vous pouvez définir des méta-données de niveau global disponibles
+ pour tous les fichiers XML. Vous ne devez pas définir ces méta-données
+ plus d'une fois par déploiement.</para>
+
+ <programlisting><?xml version="1.0" encoding="UTF-8"?>
+
+<entity-mappings
+ xmlns="http://java.sun.com/xml/ns/persistence/orm"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd"
+ version="1.0">
+
+ <persistence-unit-metadata>
+ <xml-mapping-metadata-complete/>
+ <persistence-unit-defaults>
+ <schema>myschema</schema>
+ <catalog>mycatalog</catalog>
+ <cascade-persist/>
+ </persistence-unit-defaults>
+ </persistence-unit-metadata></programlisting>
+
+ <para><literal>xml-mapping-metadata-complete</literal> signifie que toutes
+ les entités, classes mères mappées et méta-données devraient être
+ récupérées à partir du XML (c'est-à-dire ignorer les annotations).</para>
+
+ <para><literal>schema / catalog</literal> surchargera toutes les
+ définitions par défaut de schéma et de catalogue dans les méta-données
+ (XML et annotations).</para>
+
+ <para><literal>cascade-persist</literal> signifie que toutes les
+ associations ont PERSIST comme type de cascade. Nous vous recommandons de
+ ne pas utiliser cette fonctionnalité.</para>
+ </section>
+
+ <section id="xml-overriding-principles-entity" revision="1">
+ <title>Méta-données de niveau entité</title>
+
+ <para>Vous pouvez définir ou surcharger des informations de méta-données
+ sur une entité donnée.</para>
+
+ <programlistingco>
+ <areaspec>
+ <area coords="3 85" id="aa1" />
+
+ <area coords="9 85" id="aa2" />
+
+ <area coords="10 85" id="aa3" />
+
+ <area coords="11 85" id="aa4" />
+
+ <area coords="17 85" id="aa5" />
+
+ <area coords="23 85" id="aa6" />
+
+ <area coords="24 85" id="aa7" />
+
+ <area coords="25 85" id="aa8" />
+
+ <area coords="26 85" id="aa9" />
+
+ <area coords="31 85" id="aa10" />
+ </areaspec>
+
+ <programlisting><?xml version="1.0" encoding="UTF-8"?>
+
+<entity-mappings
+ xmlns="http://java.sun.com/xml/ns/persistence/orm"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd"
+ version="1.0">
+
+ <package>org.hibernate.test.reflection.java.xml</package>
+ <entity class="Administration" access="PROPERTY" metadata-complete="true">
+ <table name="tbl_admin">
+ <unique-constraint>
+ <column-name>firstname</column-name>
+ <column-name>lastname</column-name>
+ </unique-constraint>
+ </table>
+ <secondary-table name="admin2">
+ <primary-key-join-column name="admin_id" referenced-column-name="id"/>
+ <unique-constraint>
+ <column-name>address</column-name>
+ </unique-constraint>
+ </secondary-table>
+ <id-class class="SocialSecurityNumber"/>
+ <inheritance strategy="JOINED"/>
+ <sequence-generator name="seqhilo" sequence-name="seqhilo"/>
+ <table-generator name="table" table="tablehilo"/>
+ ...
+ </entity>
+
+ <entity class="PostalAdministration">
+ <primary-key-join-column name="id"/>
+ ...
+ </entity>
+</entity-mappings></programlisting>
+
+ <calloutlist>
+ <callout arearefs="aa1">
+ <para><literal>entity-mappings</literal> : entity-mappings est
+ l'élément racine pour tous les fichiers XML. Vous devez déclarer le
+ schéma xml, le fichier du schéma est inclus dans le fichier
+ hibernate-annotations.jar, aucun accès à internet ne sera effectué
+ par Hibernate Annotations.</para>
+ </callout>
+
+ <callout arearefs="aa2">
+ <para><literal>package</literal> (optionnel) : package par défaut
+ utilisé pour tous les noms de classes sans package dans le fichier
+ de descripteur de déploiement donné.</para>
+ </callout>
+
+ <callout arearefs="aa3">
+ <para><literal>entity</literal> : décrit une entité.</para>
+
+ <para><literal>metadata-complete</literal> définit si la description
+ des méta-données pour cet élément est complète ou pas (en d'autres
+ mots, si les annotations présentes au niveau de la classe devraient
+ être prises en compte ou pas).</para>
+
+ <para>Une entité doit avoir un attribut <literal>class</literal>
+ référençant une classe java à laquelle s'applique les
+ méta-données.</para>
+
+ <para>Vous pouvez surcharger un nom d'entité avec l'attribut
+ <literal>name</literal>, si aucun n'est défini et si une annotation
+ <literal>@Entity.name</literal> est présente, alors elle est
+ utilisée (et établit que les méta-données ne sont pas
+ complètes).</para>
+
+ <para>Pour un élément avec des méta-données complètes (voir
+ ci-dessous), vous pouvez définir un attribut
+ <literal>access</literal> (soit <literal>FIELD</literal>, soit
+ <literal>PROPERTY</literal> (valeur par défaut)). Pour un élément
+ avec des méta-données incomplètes, si <literal>access</literal>
+ n'est pas défini, la position de @Id permettra de le déterminer, si
+ <literal>access</literal> est défini, sa valeur est utilisée.</para>
+ </callout>
+
+ <callout arearefs="aa4">
+ <para><literal>table</literal> : vous pouvez déclarer des propriétés
+ de table (nom, schéma, catalogue), si aucune n'est définie,
+ l'annotation java est utilisée.</para>
+
+ <para>Vous pouvez définir une ou plusieurs contraintes d'unicité
+ comme dans l'exemple.</para>
+ </callout>
+
+ <callout arearefs="aa5">
+ <para><literal>secondary-table</literal> : définit une table
+ secondaire très semblable à une table habituelle excepté que vous
+ pouvez définir les colonnes de clef primaire / clef étrangère avec
+ l'élément <literal>primary-key-join-column</literal>. Sur des
+ méta-données incomplètes, les annotations de table secondaire sont
+ utilisées seulement s'il n'y a pas de <literal>secondary-table</literal>
+ de défini, sinon les annotations sont ignorées.</para>
+ </callout>
+
+ <callout arearefs="aa6">
+ <para><literal>id-class</literal> : définit la classe identifiante
+ comme le fait <literal>@IdClass</literal>.</para>
+ </callout>
+
+ <callout arearefs="aa7">
+ <para><literal>inheritance</literal> : définit la stratégie
+ d'héritage (<literal>JOINED</literal>,
+ <literal>TABLE_PER_CLASS</literal>,
+ <literal>SINGLE_TABLE</literal>) ; disponible seulement au niveau de
+ l'élément racine.</para>
+ </callout>
+
+ <callout arearefs="aa8">
+ <para><literal>sequence-generator</literal> : définit un générateur
+ de séquence.</para>
+ </callout>
+
+ <callout arearefs="aa9">
+ <para><literal>table-generator</literal> : définit un générateur de
+ table.</para>
+ </callout>
+
+ <callout arearefs="aa10">
+ <para><literal><literal>primary-key-join-column</literal></literal> :
+ définit la colonne de jointure sur la clef primaire pour les
+ entités filles lorsque la stratégie d'héritage utilisée est
+ JOINED.</para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <programlistingco>
+ <areaspec>
+ <area coords="11 85" id="ab1" />
+
+ <area coords="18 85" id="ab2" />
+
+ <area coords="22 85" id="ab3" />
+
+ <area coords="28 85" id="ab4" />
+
+ <area coords="34 85" id="ab5" />
+ </areaspec>
+
+ <programlisting><?xml version="1.0" encoding="UTF-8"?>
+
+<entity-mappings
+ xmlns="http://java.sun.com/xml/ns/persistence/orm"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd"
+ version="1.0">
+
+ <package>org.hibernate.test.reflection.java.xml</package>
+ <entity class="Music" access="PROPERTY" metadata-complete="true">
+ <discriminator-value>Generic</discriminator-value>
+ <discriminator-column length="34"/>
+ ...
+ </entity>
+
+ <entity class="PostalAdministration">
+ <primary-key-join-column name="id"/>
+ <named-query name="adminById">
+ <query>select m from Administration m where m.id = :id</query>
+ <hint name="org.hibernate.timeout" value="200"/>
+ </named-query>
+ <named-native-query name="allAdmin" result-set-mapping="adminrs">
+ <query>select *, count(taxpayer_id) as taxPayerNumber
+ from Administration, TaxPayer
+ where taxpayer_admin_id = admin_id group by ...</query>
+ <hint name="org.hibernate.timeout" value="200"/>
+ </named-native-query>
+ <sql-result-set-mapping name="adminrs">
+ <entity-result entity-class="Administration">
+ <field-result name="name" column="fld_name"/>
+ </entity-result>
+ <column-result name="taxPayerNumber"/>
+ </sql-result-set-mapping>
+ <attribute-override name="ground">
+ <column name="fld_ground" unique="true" scale="2"/>
+ </attribute-override>
+ <association-override name="referer">
+ <join-column name="referer_id" referenced-column-name="id"/>
+ </association-override>
+ ...
+ </entity>
+</entity-mappings></programlisting>
+
+ <calloutlist>
+ <callout arearefs="ab1">
+ <para><literal>discriminator-value /
+ discriminator-column</literal> : définissent la colonne et la valeur
+ discriminantes lorsque la stratégie d'héritage choisie est
+ SINGLE_TABLE.</para>
+ </callout>
+
+ <callout arearefs="ab2">
+ <para><literal>named-query</literal> : définit les requêtes nommées
+ et potentiellement les indices qui leur sont associés. Ces
+ définitions sont ajoutées à celles définies dans les annotations,
+ si deux définitions ont le même nom, la version XML a la
+ priorité.</para>
+ </callout>
+
+ <callout arearefs="ab3">
+ <para><literal>named-native-query</literal> : définit une requête
+ SQL nommée et le mapping de son résultat. Alternativement, vous
+ pouvez définir <literal>result-class</literal>. Ces définitions
+ sont ajoutées à celles definies dans les annotations, si deux
+ définitions ont le même nom, la version XML a la priorité.</para>
+ </callout>
+
+ <callout arearefs="ab4">
+ <para><literal>sql-result-set-mapping</literal> : décrit la
+ structure du mapping des résultats. Vous pouvez définir des mappings
+ de colonnes et d'entité. Ces définitions sont ajoutées à celles
+ définies dans les annotations, si deux définitions ont le même nom,
+ la version XML a la priorité.</para>
+ </callout>
+
+ <callout arearefs="ab5">
+ <para><literal>attribute-override /
+ association-override</literal> : surcharge la définition d'une
+ colonne ou d'une colonne de jointure. Cette surcharge est ajoutée à
+ celle définie dans les annotations.</para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>La même chose s'applique à <literal><embeddable></literal> et
+ <literal><mapped-superclass></literal>.</para>
+ </section>
+
+ <section>
+ <title>Méta-données de niveau propriété</title>
+
+ <para>Vous pouvez bien sûr définir des surcharges XML pour des propriétés.
+ Si les méta-données sont définies comme incomplètes, alors les propriétés
+ supplémentaires (c'est-à-dire au niveau Java) seront ignorées. Toutes les
+ méta-données de niveau propriété sont définies par
+ <literal>entity/attributes</literal>,
+ <literal>mapped-superclass/attributes</literal> ou
+ <literal>embeddable/attributes</literal>.</para>
+
+ <programlisting> <attributes>
+ <id name="id">
+ <column name="fld_id"/>
+ <generated-value generator="generator" strategy="SEQUENCE"/>
+ <temporal>DATE</temporal>
+ <sequence-generator name="generator" sequence-name="seq"/>
+ </id>
+ <version name="version"/>
+ <embedded name="embeddedObject">
+ <attribute-override name"subproperty">
+ <column name="my_column"/>
+ </attribute-override>
+ </embedded>
+ <basic name="status" optional="false">
+ <enumerated>STRING</enumerated>
+ </basic>
+ <basic name="serial" optional="true">
+ <column name="serialbytes"/>
+ <lob/>
+ </basic>
+ <basic name="terminusTime" fetch="LAZY">
+ <temporal>TIMESTAMP</temporal>
+ </basic>
+ </attributes></programlisting>
+
+ <para>Vous pouvez surcharger une propriété avec <literal>id</literal>,
+ <literal>embedded-id</literal>, <literal>version</literal>,
+ <literal>embedded</literal> et <literal>basic</literal>. Chacun de ces
+ éléments peuvent avoir des sous-éléments : <literal>lob</literal>,
+ <literal>temporal</literal>, <literal>enumerated</literal>,
+ <literal>column</literal>.</para>
+ </section>
+
+ <section>
+ <title>Méta-données au niveau association</title>
+
+ <para>Vous pouvez définir des surcharges XML pour les associations. Toutes
+ les méta-données de niveau association sont définies par
+ <literal>entity/attributes</literal>,
+ <literal>mapped-superclass/attributes</literal> ou
+ <literal>embeddable/attributes</literal>.</para>
+
+ <programlisting> <attributes>
+ <one-to-many name="players" fetch="EAGER">
+ <map-key name="name"/>
+ <join-column name="driver"/>
+ <join-column name="number"/>
+ </one-to-many>
+ <many-to-many name="roads" target-entity="Administration">
+ <order-by>maxSpeed</order-by>
+ <join-table name="bus_road">
+ <join-column name="driver"/>
+ <join-column name="number"/>
+ <inverse-join-column name="road_id"/>
+ <unique-constraint>
+ <column-name>driver</column-name>
+ <column-name>number</column-name>
+ </unique-constraint>
+ </join-table>
+ </many-to-many>
+ <many-to-many name="allTimeDrivers" mapped-by="drivenBuses">
+ </attributes></programlisting>
+
+ <para>Vous pouvez surcharger une association avec
+ <literal>one-to-many</literal>, <literal>one-to-one</literal>,
+ <literal>many-to-one</literal>, et <literal>many-to-many</literal>.
+ Chacun de ces éléments peut avoir des sous-éléments :
+ <literal>join-table</literal> (qui peut avoir des
+ <literal>join-column</literal>s et des
+ <literal>inverse-join-column</literal>s),
+ <literal><literal>join-column</literal>s</literal>,
+ <literal>map-key</literal>, et <literal>order-by</literal>.
+ <literal>mapped-by</literal> et <literal>target-entity</literal> peuvent
+ être définis en tant qu'attributs lorsque cela a du sens. Une fois de plus
+ la structure est le reflet de la structure des annotations. Vous pouvez
+ trouver toutes les informations de sémantique dans le chapitre décrivant
+ les annotations.</para>
+ </section>
+ </section>
+</chapter>
\ No newline at end of file
Added: branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/fopdf.xsl
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/fopdf.xsl 2006-10-27 19:56:30 UTC (rev 10655)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/fopdf.xsl 2006-10-27 20:03:29 UTC (rev 10656)
@@ -0,0 +1,519 @@
+<?xml version="1.0"?>
+
+<!--
+
+ This is the XSL FO configuration file for the Hibernate
+ Reference Documentation. It defines a custom titlepage and
+ the parameters for the A4 sized PDF printable output.
+
+ It took me days to figure out this stuff and fix most of
+ the obvious bugs in the DocBook XSL distribution. Some of
+ the workarounds might not be appropriate with a newer version
+ of DocBook XSL. This file is released as part of Hibernate,
+ hence LGPL licensed.
+
+ christian at hibernate.org
+
+-->
+
+<!DOCTYPE xsl:stylesheet [
+ <!ENTITY db_xsl_path "../../../../../../Hibernate3/doc/reference/support/docbook-xsl/">
+]>
+
+<xsl:stylesheet
+ version="1.0"
+ xmlns="http://www.w3.org/TR/xhtml1/transitional"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ exclude-result-prefixes="#default">
+
+ <xsl:import href="&db_xsl_path;/fo/docbook.xsl"/>
+
+ <!--###################################################
+ Custom Title Page
+ ################################################### -->
+
+ <xsl:template name="book.titlepage.recto">
+ <fo:block>
+ <fo:table table-layout="fixed" width="175mm">
+ <fo:table-column column-width="175mm"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell text-align="center">
+ <fo:block>
+ <fo:external-graphic src="file:images/hibernate_logo_a.png"/>
+ </fo:block>
+ <fo:block font-family="Helvetica" font-size="22pt" padding-before="10mm">
+ <xsl:value-of select="bookinfo/title"/>
+ </fo:block>
+ <fo:block font-family="Helvetica" font-size="18pt" padding-before="10mm">
+ <xsl:value-of select="bookinfo/subtitle"/>
+ </fo:block>
+ <fo:block font-family="Helvetica" font-size="12pt" padding="10mm">
+ Version:
+ <xsl:value-of select="bookinfo/releaseinfo"/>
+ </fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:block>
+ </xsl:template>
+
+ <!-- Prevent blank pages in output -->
+ <xsl:template name="book.titlepage.before.verso">
+ </xsl:template>
+ <xsl:template name="book.titlepage.verso">
+ </xsl:template>
+ <xsl:template name="book.titlepage.separator">
+ </xsl:template>
+
+ <!--###################################################
+ Header
+ ################################################### -->
+
+ <!-- More space in the center header for long text -->
+ <xsl:attribute-set name="header.content.properties">
+ <xsl:attribute name="font-family">
+ <xsl:value-of select="$body.font.family"/>
+ </xsl:attribute>
+ <xsl:attribute name="margin-left">-5em</xsl:attribute>
+ <xsl:attribute name="margin-right">-5em</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!--###################################################
+ Custom Footer
+ ################################################### -->
+
+ <!-- This footer prints the Hibernate version number on the left side -->
+ <xsl:template name="footer.content">
+ <xsl:param name="pageclass" select="''"/>
+ <xsl:param name="sequence" select="''"/>
+ <xsl:param name="position" select="''"/>
+ <xsl:param name="gentext-key" select="''"/>
+
+ <xsl:variable name="Version">
+ <xsl:choose>
+ <xsl:when test="//releaseinfo">
+ <xsl:text>Hibernate </xsl:text>
+ <xsl:value-of select="//releaseinfo"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- nop -->
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="$sequence='blank'">
+ <xsl:choose>
+ <xsl:when test="$double.sided != 0 and $position = 'left'">
+ <xsl:value-of select="$Version"/>
+ </xsl:when>
+
+ <xsl:when test="$double.sided = 0 and $position = 'center'">
+ <!-- nop -->
+ </xsl:when>
+
+ <xsl:otherwise>
+ <fo:page-number/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+
+ <xsl:when test="$pageclass='titlepage'">
+ <!-- nop: other titlepage sequences have no footer -->
+ </xsl:when>
+
+ <xsl:when test="$double.sided != 0 and $sequence = 'even' and $position='left'">
+ <fo:page-number/>
+ </xsl:when>
+
+ <xsl:when test="$double.sided != 0 and $sequence = 'odd' and $position='right'">
+ <fo:page-number/>
+ </xsl:when>
+
+ <xsl:when test="$double.sided = 0 and $position='right'">
+ <fo:page-number/>
+ </xsl:when>
+
+ <xsl:when test="$double.sided != 0 and $sequence = 'odd' and $position='left'">
+ <xsl:value-of select="$Version"/>
+ </xsl:when>
+
+ <xsl:when test="$double.sided != 0 and $sequence = 'even' and $position='right'">
+ <xsl:value-of select="$Version"/>
+ </xsl:when>
+
+ <xsl:when test="$double.sided = 0 and $position='left'">
+ <xsl:value-of select="$Version"/>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <!-- nop -->
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!--###################################################
+ Custom Toc Line
+ ################################################### -->
+
+ <!-- Improve the TOC. -->
+ <xsl:template name="toc.line">
+ <xsl:variable name="id">
+ <xsl:call-template name="object.id"/>
+ </xsl:variable>
+
+ <xsl:variable name="label">
+ <xsl:apply-templates select="." mode="label.markup"/>
+ </xsl:variable>
+
+ <fo:block text-align-last="justify"
+ end-indent="{$toc.indent.width}pt"
+ last-line-end-indent="-{$toc.indent.width}pt">
+ <fo:inline keep-with-next.within-line="always">
+ <fo:basic-link internal-destination="{$id}">
+
+ <!-- Chapter titles should be bold. -->
+ <xsl:choose>
+ <xsl:when test="local-name(.) = 'chapter'">
+ <xsl:attribute name="font-weight">bold</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+
+ <xsl:if test="$label != ''">
+ <xsl:copy-of select="$label"/>
+ <xsl:value-of select="$autotoc.label.separator"/>
+ </xsl:if>
+ <xsl:apply-templates select="." mode="titleabbrev.markup"/>
+ </fo:basic-link>
+ </fo:inline>
+ <fo:inline keep-together.within-line="always">
+ <xsl:text> </xsl:text>
+ <fo:leader leader-pattern="dots"
+ leader-pattern-width="3pt"
+ leader-alignment="reference-area"
+ keep-with-next.within-line="always"/>
+ <xsl:text> </xsl:text>
+ <fo:basic-link internal-destination="{$id}">
+ <fo:page-number-citation ref-id="{$id}"/>
+ </fo:basic-link>
+ </fo:inline>
+ </fo:block>
+ </xsl:template>
+
+ <!--###################################################
+ Extensions
+ ################################################### -->
+
+ <!-- These extensions are required for table printing and other stuff -->
+ <xsl:param name="use.extensions">1</xsl:param>
+ <xsl:param name="tablecolumns.extension">0</xsl:param>
+ <!-- FOP provide only PDF Bookmarks at the moment -->
+ <xsl:param name="fop.extensions">1</xsl:param>
+
+ <!--###################################################
+ Table Of Contents
+ ################################################### -->
+
+ <!-- Generate the TOCs for named components only -->
+ <xsl:param name="generate.toc">
+ book toc
+ </xsl:param>
+
+ <!-- Show only Sections up to level 3 in the TOCs -->
+ <xsl:param name="toc.section.depth">3</xsl:param>
+
+ <!-- Dot and Whitespace as separator in TOC between Label and Title-->
+ <xsl:param name="autotoc.label.separator" select="'. '"/>
+
+
+ <!--###################################################
+ Paper & Page Size
+ ################################################### -->
+
+ <!-- Paper type, no headers on blank pages, no double sided printing -->
+ <xsl:param name="paper.type" select="'A4'"/>
+ <xsl:param name="double.sided">0</xsl:param>
+ <xsl:param name="headers.on.blank.pages">0</xsl:param>
+ <xsl:param name="footers.on.blank.pages">0</xsl:param>
+
+ <!-- Space between paper border and content (chaotic stuff, don't touch) -->
+ <xsl:param name="page.margin.top">5mm</xsl:param>
+ <xsl:param name="region.before.extent">10mm</xsl:param>
+ <xsl:param name="body.margin.top">10mm</xsl:param>
+
+ <xsl:param name="body.margin.bottom">15mm</xsl:param>
+ <xsl:param name="region.after.extent">10mm</xsl:param>
+ <xsl:param name="page.margin.bottom">0mm</xsl:param>
+
+ <xsl:param name="page.margin.outer">18mm</xsl:param>
+ <xsl:param name="page.margin.inner">18mm</xsl:param>
+
+ <!-- No intendation of Titles -->
+ <xsl:param name="title.margin.left">0pc</xsl:param>
+
+ <!--###################################################
+ Fonts & Styles
+ ################################################### -->
+
+ <!-- Default Font size -->
+ <xsl:param name="body.font.master">11</xsl:param>
+
+ <!-- Line height in body text -->
+ <xsl:param name="line-height">1.4</xsl:param>
+
+ <!-- Monospaced fonts are smaller than regular text -->
+ <xsl:attribute-set name="monospace.properties">
+ <xsl:attribute name="font-family">
+ <xsl:value-of select="$monospace.font.family"/>
+ </xsl:attribute>
+ <xsl:attribute name="font-size">0.8em</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!--###################################################
+ Tables
+ ################################################### -->
+
+ <!-- The table width should be adapted to the paper size -->
+ <xsl:param name="default.table.width">17.4cm</xsl:param>
+
+ <!-- Some padding inside tables -->
+ <xsl:attribute-set name="table.cell.padding">
+ <xsl:attribute name="padding-left">4pt</xsl:attribute>
+ <xsl:attribute name="padding-right">4pt</xsl:attribute>
+ <xsl:attribute name="padding-top">4pt</xsl:attribute>
+ <xsl:attribute name="padding-bottom">4pt</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!-- Only hairlines as frame and cell borders in tables -->
+ <xsl:param name="table.frame.border.thickness">0.1pt</xsl:param>
+ <xsl:param name="table.cell.border.thickness">0.1pt</xsl:param>
+
+ <!--###################################################
+ Labels
+ ################################################### -->
+
+ <!-- Label Chapters and Sections (numbering) -->
+ <xsl:param name="chapter.autolabel">1</xsl:param>
+ <xsl:param name="section.autolabel" select="1"/>
+ <xsl:param name="section.label.includes.component.label" select="1"/>
+
+ <!-- Label only Sections up to level 2 -->
+ <xsl:param name="local.l10n.xml" select="document('')"/>
+ <l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0">
+ <l:l10n language="en">
+ <l:context name="title-numbered">
+ <l:template name="sect3" text="%t"/>
+ <l:template name="sect4" text="%t"/>
+ <l:template name="sect5" text="%t"/>
+ </l:context>
+ <l:context name="section-xref-numbered">
+ <l:template name="sect3" text="the section called %t"/>
+ <l:template name="sect4" text="the section called %t"/>
+ <l:template name="sect5" text="the section called %t"/>
+ </l:context>
+ </l:l10n>
+ </l:i18n>
+
+ <!--###################################################
+ Titles
+ ################################################### -->
+
+ <!-- Chapter title size -->
+ <xsl:attribute-set name="chapter.titlepage.recto.style">
+ <xsl:attribute name="text-align">left</xsl:attribute>
+ <xsl:attribute name="font-weight">bold</xsl:attribute>
+ <xsl:attribute name="font-size">
+ <xsl:value-of select="$body.font.master * 1.8"/>
+ <xsl:text>pt</xsl:text>
+ </xsl:attribute>
+ </xsl:attribute-set>
+
+ <!-- Why is the font-size for chapters hardcoded in the XSL FO templates?
+ Let's remove it, so this sucker can use our attribute-set only... -->
+ <xsl:template match="title" mode="chapter.titlepage.recto.auto.mode">
+ <fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xsl:use-attribute-sets="chapter.titlepage.recto.style">
+ <xsl:call-template name="component.title">
+ <xsl:with-param name="node" select="ancestor-or-self::chapter[1]"/>
+ </xsl:call-template>
+ </fo:block>
+ </xsl:template>
+
+ <!-- Sections 1, 2 and 3 titles have a small bump factor and padding -->
+ <xsl:attribute-set name="section.title.level1.properties">
+ <xsl:attribute name="space-before.optimum">0.8em</xsl:attribute>
+ <xsl:attribute name="space-before.minimum">0.8em</xsl:attribute>
+ <xsl:attribute name="space-before.maximum">0.8em</xsl:attribute>
+ <xsl:attribute name="font-size">
+ <xsl:value-of select="$body.font.master * 1.5"/>
+ <xsl:text>pt</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
+ <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
+ <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
+ </xsl:attribute-set>
+ <xsl:attribute-set name="section.title.level2.properties">
+ <xsl:attribute name="space-before.optimum">0.6em</xsl:attribute>
+ <xsl:attribute name="space-before.minimum">0.6em</xsl:attribute>
+ <xsl:attribute name="space-before.maximum">0.6em</xsl:attribute>
+ <xsl:attribute name="font-size">
+ <xsl:value-of select="$body.font.master * 1.25"/>
+ <xsl:text>pt</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
+ <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
+ <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
+ </xsl:attribute-set>
+ <xsl:attribute-set name="section.title.level3.properties">
+ <xsl:attribute name="space-before.optimum">0.4em</xsl:attribute>
+ <xsl:attribute name="space-before.minimum">0.4em</xsl:attribute>
+ <xsl:attribute name="space-before.maximum">0.4em</xsl:attribute>
+ <xsl:attribute name="font-size">
+ <xsl:value-of select="$body.font.master * 1.0"/>
+ <xsl:text>pt</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
+ <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
+ <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!-- Titles of formal objects (tables, examples, ...) -->
+ <xsl:attribute-set name="formal.title.properties" use-attribute-sets="normal.para.spacing">
+ <xsl:attribute name="font-weight">bold</xsl:attribute>
+ <xsl:attribute name="font-size">
+ <xsl:value-of select="$body.font.master"/>
+ <xsl:text>pt</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="hyphenate">false</xsl:attribute>
+ <xsl:attribute name="space-after.minimum">0.4em</xsl:attribute>
+ <xsl:attribute name="space-after.optimum">0.6em</xsl:attribute>
+ <xsl:attribute name="space-after.maximum">0.8em</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!--###################################################
+ Programlistings
+ ################################################### -->
+
+ <!-- Verbatim text formatting (programlistings) -->
+ <xsl:attribute-set name="verbatim.properties">
+ <xsl:attribute name="space-before.minimum">1em</xsl:attribute>
+ <xsl:attribute name="space-before.optimum">1em</xsl:attribute>
+ <xsl:attribute name="space-before.maximum">1em</xsl:attribute>
+ <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
+ <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
+ <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
+ <xsl:attribute name="border-color">#444444</xsl:attribute>
+ <xsl:attribute name="border-style">solid</xsl:attribute>
+ <xsl:attribute name="border-width">0.1pt</xsl:attribute>
+ <xsl:attribute name="padding-top">0.5em</xsl:attribute>
+ <xsl:attribute name="padding-left">0.5em</xsl:attribute>
+ <xsl:attribute name="padding-right">0.5em</xsl:attribute>
+ <xsl:attribute name="padding-bottom">0.5em</xsl:attribute>
+ <xsl:attribute name="margin-left">0.5em</xsl:attribute>
+ <xsl:attribute name="margin-right">0.5em</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!-- Shade (background) programlistings -->
+ <xsl:param name="shade.verbatim">1</xsl:param>
+ <xsl:attribute-set name="shade.verbatim.style">
+ <xsl:attribute name="background-color">#F0F0F0</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!--###################################################
+ Callouts
+ ################################################### -->
+
+ <!-- We want to use callouts... -->
+ <xsl:param name="callout.extensions">1</xsl:param>
+
+ <!-- Place callout bullets at this column in programmlisting.-->
+ <xsl:param name="callout.defaultcolumn">90</xsl:param>
+
+ <!--
+ No, don't use crappy graphics for the callout bullets. This setting
+ enables some weird Unicode rendering for some fancy bullet points
+ in callouts. By default, this can only count to 10 and produces
+ strange results if you ever have more than 10 callouts for one
+ programlisting. We will fix that next.
+ -->
+ <xsl:param name="callout.graphics">0</xsl:param>
+
+ <!--
+ Again, fun with DocBook XSL: The callout bullets are rendered in
+ two places: In the programlisting itself and in the list below
+ the listing, with the actual callout text. The rendering in the
+ programlisting is some XSL transformer extension (e.g. a Saxon
+ extension), so we can't change that without messing with the
+ extensions. We only can turn it off by setting this limit to
+ zero, then, a simple bracket style like "(3)" and "(4)" will
+ be used in the programlisting.
+ -->
+ <xsl:param name="callout.unicode.number.limit" select="'0'"></xsl:param>
+
+ <!--
+ The callout bullets in the actual callout list will be rendered
+ with an XSL FO template. The default template is broken: limited to 10
+ nice looking Unicode bullet points and then it doesn't print anything,
+ the fallback doesn't work. We implement our own template, which is not
+ as complicated, more ugly, but works. As always, function is more
+ important than form.
+ -->
+ <xsl:template name="callout-bug">
+ <xsl:param name="conum" select='1'/>
+ <fo:inline
+ color="black"
+ padding-top="0.1em"
+ padding-bottom="0.1em"
+ padding-start="0.2em"
+ padding-end="0.2em"
+ baseline-shift="0.1em"
+ font-family="{$monospace.font.family}"
+ font-weight="bold"
+ font-size="75%">
+ <xsl:text>(</xsl:text>
+ <xsl:value-of select="$conum"/>
+ <xsl:text>)</xsl:text>
+ </fo:inline>
+
+ </xsl:template>
+
+ <!--###################################################
+ Misc
+ ################################################### -->
+
+ <!-- Correct placement of titles for figures and examples. -->
+ <xsl:param name="formal.title.placement">
+ figure after
+ example before
+ equation before
+ table before
+ procedure before
+ </xsl:param>
+
+ <!-- Format Variable Lists as Blocks (prevents horizontal overflow). -->
+ <xsl:param name="variablelist.as.blocks">1</xsl:param>
+
+ <!-- The horrible list spacing problems, this is much better. -->
+ <xsl:attribute-set name="list.block.spacing">
+ <xsl:attribute name="space-before.optimum">0.8em</xsl:attribute>
+ <xsl:attribute name="space-before.minimum">0.8em</xsl:attribute>
+ <xsl:attribute name="space-before.maximum">0.8em</xsl:attribute>
+ <xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
+ <xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
+ <xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!-- Newer DocBook XSL apparently thinks that some sections are by
+ default "draft" status, and this idiotic thing is by default
+ also set to "maybe", so it spits out a lot of errors with the
+ latest FOP as the XSL/FO styles have references to some draft
+ watermarks, which you actually don't want in the first place.
+ Turn this crap off. If you have to work with the "status"
+ attribute, don't.
+ -->
+ <xsl:param name="draft.mode" select="'no'"/>
+
+</xsl:stylesheet>
Added: branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/html.css
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/html.css 2006-10-27 19:56:30 UTC (rev 10655)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/html.css 2006-10-27 20:03:29 UTC (rev 10656)
@@ -0,0 +1,97 @@
+A {
+ color: #003399;
+}
+
+A:active {
+ color: #003399;
+}
+
+A:visited {
+ color: #888888;
+}
+
+P, OL, UL, LI, DL, DT, DD, BLOCKQUOTE {
+ color: #000000;
+}
+
+TD, TH, SPAN {
+ color: #000000;
+}
+
+BLOCKQUOTE {
+ margin-right: 0px;
+}
+
+
+H1, H2, H3, H4, H5, H6 {
+ color: #000000;
+ font-weight:500;
+ margin-top:10px;
+ padding-top:15px;
+}
+
+TABLE {
+ border-collapse: collapse;
+ border-spacing:0;
+ border: 1px thin black;
+ empty-cells: hide;
+}
+
+TD {
+ padding: 4pt;
+}
+
+H1 { font-size: 150%; }
+H2 { font-size: 140%; }
+H3 { font-size: 110%; font-weight: bold; }
+H4 { font-size: 110%; font-weight: bold;}
+H5 { font-size: 100%; font-style: italic; }
+H6 { font-size: 100%; font-style: italic; }
+
+TT {
+font-size: 90%;
+ font-family: "Courier New", Courier, monospace;
+ color: #000000;
+}
+
+PRE {
+font-size: 100%;
+ padding: 5px;
+ border-style: solid;
+ border-width: 1px;
+ border-color: #CCCCCC;
+ background-color: #F4F4F4;
+}
+
+UL, OL, LI {
+ list-style: disc;
+}
+
+HR {
+ width: 100%;
+ height: 1px;
+ background-color: #CCCCCC;
+ border-width: 0px;
+ padding: 0px;
+ color: #CCCCCC;
+}
+
+.variablelist {
+ padding-top: 10;
+ padding-bottom:10;
+ margin:0;
+}
+
+.itemizedlist, UL {
+ padding-top: 0;
+ padding-bottom:0;
+ margin:0;
+}
+
+.term {
+ font-weight:bold;
+}
+
+
+
+
Added: branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/html.xsl
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/html.xsl 2006-10-27 19:56:30 UTC (rev 10655)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/html.xsl 2006-10-27 20:03:29 UTC (rev 10656)
@@ -0,0 +1,84 @@
+<?xml version="1.0"?>
+
+<!--
+
+ This is the XSL HTML configuration file for the Hibernate
+ Reference Documentation.
+
+ It took me days to figure out this stuff and fix most of
+ the obvious bugs in the DocBook XSL distribution. Some of
+ the workarounds might not be appropriate with a newer version
+ of DocBook XSL. This file is released as part of Hibernate,
+ hence LGPL licensed.
+
+ christian at hibernate.org
+-->
+
+<!DOCTYPE xsl:stylesheet [
+ <!ENTITY db_xsl_path "../../../../../../Hibernate3/doc/reference/support/docbook-xsl/">
+]>
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0"
+ xmlns="http://www.w3.org/TR/xhtml1/transitional"
+ exclude-result-prefixes="#default">
+
+<xsl:import href="&db_xsl_path;/html/docbook.xsl"/>
+
+<!--###################################################
+ HTML Settings
+ ################################################### -->
+
+ <xsl:param name="html.stylesheet">../shared/css/html.css</xsl:param>
+
+ <!-- These extensions are required for table printing and other stuff -->
+ <xsl:param name="use.extensions">1</xsl:param>
+ <xsl:param name="tablecolumns.extension">0</xsl:param>
+ <xsl:param name="callout.extensions">1</xsl:param>
+ <xsl:param name="graphicsize.extension">0</xsl:param>
+
+<!--###################################################
+ Table Of Contents
+ ################################################### -->
+
+ <!-- Generate the TOCs for named components only -->
+ <xsl:param name="generate.toc">
+ book toc
+ </xsl:param>
+
+ <!-- Show only Sections up to level 3 in the TOCs -->
+ <xsl:param name="toc.section.depth">3</xsl:param>
+
+<!--###################################################
+ Labels
+ ################################################### -->
+
+ <!-- Label Chapters and Sections (numbering) -->
+ <xsl:param name="chapter.autolabel">1</xsl:param>
+ <xsl:param name="section.autolabel" select="1"/>
+ <xsl:param name="section.label.includes.component.label" select="1"/>
+
+<!--###################################################
+ Callouts
+ ################################################### -->
+
+ <!-- Don't use graphics, use a simple number style -->
+ <xsl:param name="callout.graphics">0</xsl:param>
+
+ <!-- Place callout marks at this column in annotated areas -->
+ <xsl:param name="callout.defaultcolumn">90</xsl:param>
+
+<!--###################################################
+ Misc
+ ################################################### -->
+
+ <!-- Placement of titles -->
+ <xsl:param name="formal.title.placement">
+ figure after
+ example before
+ equation before
+ table before
+ procedure before
+ </xsl:param>
+
+</xsl:stylesheet>
Added: branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/html_chunk.xsl
===================================================================
--- branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/html_chunk.xsl 2006-10-27 19:56:30 UTC (rev 10655)
+++ branches/Branch_3_2/HibernateExt/metadata/doc/reference/fr/styles/html_chunk.xsl 2006-10-27 20:03:29 UTC (rev 10656)
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+
+<!--
+
+ This is the XSL HTML configuration file for the Hibernate
+ Reference Documentation.
+
+ It took me days to figure out this stuff and fix most of
+ the obvious bugs in the DocBook XSL distribution. Some of
+ the workarounds might not be appropriate with a newer version
+ of DocBook XSL. This file is released as part of Hibernate,
+ hence LGPL licensed.
+
+ christian at hibernate.org
+-->
+
+<!DOCTYPE xsl:stylesheet [
+ <!ENTITY db_xsl_path "../../../../../../Hibernate3/doc/reference/support/docbook-xsl/">
+]>
+
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0"
+ xmlns="http://www.w3.org/TR/xhtml1/transitional"
+ exclude-result-prefixes="#default">
+
+<xsl:import href="&db_xsl_path;/html/chunk.xsl"/>
+
+<!--###################################################
+ HTML Settings
+ ################################################### -->
+
+ <xsl:param name="chunk.section.depth">'5'</xsl:param>
+ <xsl:param name="use.id.as.filename">'1'</xsl:param>
+ <xsl:param name="html.stylesheet">../shared/css/html.css</xsl:param>
+
+ <!-- These extensions are required for table printing and other stuff -->
+ <xsl:param name="use.extensions">1</xsl:param>
+ <xsl:param name="tablecolumns.extension">0</xsl:param>
+ <xsl:param name="callout.extensions">1</xsl:param>
+ <xsl:param name="graphicsize.extension">0</xsl:param>
+
+<!--###################################################
+ Table Of Contents
+ ################################################### -->
+
+ <!-- Generate the TOCs for named components only -->
+ <xsl:param name="generate.toc">
+ book toc
+ </xsl:param>
+
+ <!-- Show only Sections up to level 3 in the TOCs -->
+ <xsl:param name="toc.section.depth">3</xsl:param>
+
+<!--###################################################
+ Labels
+ ################################################### -->
+
+ <!-- Label Chapters and Sections (numbering) -->
+ <xsl:param name="chapter.autolabel">1</xsl:param>
+ <xsl:param name="section.autolabel" select="1"/>
+ <xsl:param name="section.label.includes.component.label" select="1"/>
+
+<!--###################################################
+ Callouts
+ ################################################### -->
+
+ <!-- Don't use graphics, use a simple number style -->
+ <xsl:param name="callout.graphics">0</xsl:param>
+
+ <!-- Place callout marks at this column in annotated areas -->
+ <xsl:param name="callout.defaultcolumn">90</xsl:param>
+
+<!--###################################################
+ Misc
+ ################################################### -->
+
+ <!-- Placement of titles -->
+ <xsl:param name="formal.title.placement">
+ figure after
+ example before
+ equation before
+ table before
+ procedure before
+ </xsl:param>
+
+</xsl:stylesheet>
More information about the hibernate-commits
mailing list