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.
La suite de test unitaires montre des exemples supplémentaires de fichier XML.
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.
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.
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.
<?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>
xml-mapping-metadata-complete 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).
schema / catalog surchargera toutes les définitions par défaut de schéma et de catalogue dans les méta-données (XML et annotations).
cascade-persist signifie que toutes les associations ont PERSIST comme type de cascade. Nous vous recommandons de ne pas utiliser cette fonctionnalité.
Vous pouvez définir ou surcharger des informations de méta-données sur une entité donnée.
<?xml version="1.0" encoding="UTF-8"?> <entity-mappings (1) 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.annotations.reflection</package> (2) <entity class="Administration" access="PROPERTY" metadata-complete="true"> (3) <table name="tbl_admin"> (4) <unique-constraint> <column-name>firstname</column-name> <column-name>lastname</column-name> </unique-constraint> </table> <secondary-table name="admin2"> (5) <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"/> (6) <inheritance strategy="JOINED"/> (7) <sequence-generator name="seqhilo" sequence-name="seqhilo"/> (8) <table-generator name="table" table="tablehilo"/> (9) ... </entity> <entity class="PostalAdministration"> <primary-key-join-column name="id"/> (10) ... </entity> </entity-mappings>
(1) | entity-mappings : 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. |
(2) | package (optionnel) : package par défaut utilisé pour tous les noms de classes sans package dans le fichier de descripteur de déploiement donné. |
(3) | entity : décrit une entité. metadata-complete 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). Une entité doit avoir un attribut class référençant une classe java à laquelle s'applique les méta-données. Vous pouvez surcharger un nom d'entité avec l'attribut name, si aucun n'est défini et si une annotation @Entity.name est présente, alors elle est utilisée (et établit que les méta-données ne sont pas complètes). Pour un élément avec des méta-données complètes (voir ci-dessous), vous pouvez définir un attribut access (soit FIELD, soit PROPERTY (valeur par défaut)). Pour un élément avec des méta-données incomplètes, si access n'est pas défini, la position de @Id permettra de le déterminer, si access est défini, sa valeur est utilisée. |
(4) | table : 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. Vous pouvez définir une ou plusieurs contraintes d'unicité comme dans l'exemple. |
(5) | secondary-table : 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 primary-key-join-column. Sur des méta-données incomplètes, les annotations de table secondaire sont utilisées seulement s'il n'y a pas de secondary-table de défini, sinon les annotations sont ignorées. |
(6) | id-class : définit la classe identifiante comme le fait @IdClass. |
(7) | inheritance : définit la stratégie d'héritage (JOINED, TABLE_PER_CLASS, SINGLE_TABLE) ; disponible seulement au niveau de l'élément racine. |
(8) | sequence-generator : définit un générateur de séquence. |
(9) | table-generator : définit un générateur de table. |
(10) | primary-key-join-column : 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. |
<?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.annotations.reflection</package> <entity class="Music" access="PROPERTY" metadata-complete="true"> <discriminator-value>Generic</discriminator-value> (1) <discriminator-column length="34"/> ... </entity> <entity class="PostalAdministration"> <primary-key-join-column name="id"/> <named-query name="adminById"> (2) <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"> (3) <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"> (4) <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"> (5) <column name="fld_ground" unique="true" scale="2"/> </attribute-override> <association-override name="referer"> <join-column name="referer_id" referenced-column-name="id"/> </association-override> ... </entity> </entity-mappings>
(1) | discriminator-value / discriminator-column : définissent la colonne et la valeur discriminantes lorsque la stratégie d'héritage choisie est SINGLE_TABLE. |
(2) | named-query : 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é. |
(3) | named-native-query : définit une requête SQL nommée et le mapping de son résultat. Alternativement, vous pouvez définir result-class. 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é. |
(4) | sql-result-set-mapping : 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é. |
(5) | attribute-override / association-override : surcharge la définition d'une colonne ou d'une colonne de jointure. Cette surcharge est ajoutée à celle définie dans les annotations. |
La même chose s'applique à <embeddable> et <mapped-superclass>.
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 entity/attributes, mapped-superclass/attributes ou embeddable/attributes.
<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>
Vous pouvez surcharger une propriété avec id, embedded-id, version, embedded et basic. Chacun de ces éléments peuvent avoir des sous-éléments : lob, temporal, enumerated, column.
Vous pouvez définir des surcharges XML pour les associations. Toutes les méta-données de niveau association sont définies par entity/attributes, mapped-superclass/attributes ou embeddable/attributes.
<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>
Vous pouvez surcharger une association avec one-to-many, one-to-one, many-to-one, et many-to-many. Chacun de ces éléments peut avoir des sous-éléments : join-table (qui peut avoir des join-columns et des inverse-join-columns), join-columns, map-key, et order-by. mapped-by et target-entity 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.