diff --git a/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml b/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml index 051cf29fe1..bdaf0f216e 100644 --- a/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml +++ b/documentation/manual/src/main/docbook/en-US/content/basic_mapping.xml @@ -210,345 +210,6 @@ public class Dog { ... } affect the database schemas exported by the schema export tool (for example, the not-null attribute). -
- Some hbm.xml specificities - - The hbm.xml structure has some specificities naturally not present - when using annotations, let's describe them briefly. - -
- Doctype - - All XML mappings should declare the doctype shown. The actual - DTD can be found at the URL above, in the directory - hibernate-x.x.x/src/org/hibernate , or in - hibernate3.jar. Hibernate will always look for the - DTD in its classpath first. If you experience lookups of the DTD using - an Internet connection, check the DTD declaration against the contents - of your classpath. - -
- EntityResolver - - Hibernate will first attempt to resolve DTDs in its classpath. - It does this is by registering a custom - org.xml.sax.EntityResolver implementation with - the SAXReader it uses to read in the xml files. This custom - EntityResolver recognizes two different systemId - namespaces: - - - - a hibernate namespace is recognized - whenever the resolver encounters a systemId starting with - http://hibernate.sourceforge.net/. The - resolver attempts to resolve these entities via the classloader - which loaded the Hibernate classes. - - - - a user namespace is recognized whenever - the resolver encounters a systemId using a - classpath:// URL protocol. The resolver will - attempt to resolve these entities via (1) the current thread - context classloader and (2) the classloader which loaded the - Hibernate classes. - - - - The following is an example of utilizing user - namespacing: - - - - - - Where types.xml is a resource in the - your.domain package and contains a custom typedef. -
-
- -
- Hibernate-mapping - - This element has several optional attributes. The - schema and catalog attributes - specify that tables referred to in this mapping belong to the named - schema and/or catalog. If they are specified, tablenames will be - qualified by the given schema and catalog names. If they are missing, - tablenames will be unqualified. The default-cascade - attribute specifies what cascade style should be assumed for - properties and collections that do not specify a - cascade attribute. By default, the - auto-import attribute allows you to use unqualified - class names in the query language. - - - - - - - - - - - - - - - - - - - <hibernate-mapping - schema="schemaName" - catalog="catalogName" - default-cascade="cascade_style" - default-access="field|property|ClassName" - default-lazy="true|false" - auto-import="true|false" - package="package.name" - /> - - - - schema (optional): the name of a - database schema. - - - - catalog (optional): the name of a - database catalog. - - - - default-cascade (optional - defaults to - none): a default cascade style. - - - - default-access (optional - defaults to - property): the strategy Hibernate should use - for accessing all properties. It can be a custom implementation - of PropertyAccessor. - - - - default-lazy (optional - defaults to - true): the default value for unspecified - lazy attributes of class and collection - mappings. - - - - auto-import (optional - defaults to - true): specifies whether we can use - unqualified class names of classes in this mapping in the query - language. - - - - package (optional): specifies a package - prefix to use for unqualified class names in the mapping - document. - - - - - If you have two persistent classes with the same unqualified - name, you should set auto-import="false". An - exception will result if you attempt to assign two classes to the same - "imported" name. - - The hibernate-mapping element allows you to - nest several persistent <class> mappings, as - shown above. It is, however, good practice (and expected by some - tools) to map only a single persistent class, or a single class - hierarchy, in one mapping file and name it after the persistent - superclass. For example, Cat.hbm.xml, - Dog.hbm.xml, or if using inheritance, - Animal.hbm.xml. -
- -
- Key - - The <key> element is featured a few - times within this guide. It appears anywhere the parent mapping - element defines a join to a new table that references the primary key - of the original table. It also defines the foreign key in the joined - table: - - - - - - - - - - - - - - - - - <key - column="columnname" - on-delete="noaction|cascade" - property-ref="propertyName" - not-null="true|false" - update="true|false" - unique="true|false" -/> - - - - column (optional): the name of the - foreign key column. This can also be specified by nested - <column> element(s). - - - - on-delete (optional - defaults to - noaction): specifies whether the foreign key - constraint has database-level cascade delete enabled. - - - - property-ref (optional): specifies that - the foreign key refers to columns that are not the primary key - of the original table. It is provided for legacy data. - - - - not-null (optional): specifies that the - foreign key columns are not nullable. This is implied whenever - the foreign key is also part of the primary key. - - - - update (optional): specifies that the - foreign key should never be updated. This is implied whenever - the foreign key is also part of the primary key. - - - - unique (optional): specifies that the - foreign key should have a unique constraint. This is implied - whenever the foreign key is also the primary key. - - - - - For systems where delete performance is important, we recommend - that all keys should be defined - on-delete="cascade". Hibernate uses a - database-level ON CASCADE DELETE constraint, - instead of many individual DELETE statements. Be - aware that this feature bypasses Hibernate's usual optimistic locking - strategy for versioned data. - - The not-null and update - attributes are useful when mapping a unidirectional one-to-many - association. If you map a unidirectional one-to-many association to a - non-nullable foreign key, you must declare the - key column using <key - not-null="true">. -
- -
- Import - - If your application has two persistent classes with the same - name, and you do not want to specify the fully qualified package name - in Hibernate queries, classes can be "imported" explicitly, rather - than relying upon auto-import="true". You can also - import classes and interfaces that are not explicitly mapped: - - <import class="java.lang.Object" rename="Universe"/> - - - - - - - - - <import - class="ClassName" - rename="ShortName" -/> - - - - class: the fully qualified class name - of any Java class. - - - - rename (optional - defaults to the - unqualified class name): a name that can be used in the query - language. - - - - - - This feature is unique to hbm.xml and is not supported in - annotations. - -
- -
- Column and formula elements - - Mapping elements which accept a column - attribute will alternatively accept a - <column> subelement. Likewise, - <formula> is an alternative to the - formula attribute. For example: - - <column - name="column_name" - length="N" - precision="N" - scale="N" - not-null="true|false" - unique="true|false" - unique-key="multicolumn_unique_key_name" - index="index_name" - sql-type="sql_type_name" - check="SQL expression" - default="SQL expression" - read="SQL expression" - write="SQL expression"/> - - <formula>SQL expression</formula> - - Most of the attributes on column provide a - means of tailoring the DDL during automatic schema generation. The - read and write attributes allow - you to specify custom SQL that Hibernate will use to access the - column's value. For more on this, see the discussion of column read and write - expressions. - - The column and formula - elements can even be combined within the same property or association - mapping to express, for example, exotic join conditions. - - <many-to-one name="homeAddress" class="Address" - insert="false" update="false"> - <column name="person_id" not-null="true" length="10"/> - <formula>'MAILING'</formula> -</many-to-one> -
-
-
Entity @@ -2399,803 +2060,6 @@ public class Customer implements Serializable {
-
- Inheritance strategy - - Java is a language supporting polymorphism: a class can inherit - from another. Several strategies are possible to persist a class - hierarchy: - - - - Single table per class hierarchy strategy: a single table - hosts all the instances of a class hierarchy - - - - Joined subclass strategy: one table per class and subclass is - present and each table persist the properties specific to a given - subclass. The state of the entity is then stored in its - corresponding class table and all its superclasses - - - - Table per class strategy: one table per concrete class and - subclass is present and each table persist the properties of the - class and its superclasses. The state of the entity is then stored - entirely in the dedicated table for its class. - - - -
- Single table per class hierarchy strategy - - With this approach the properties of all the subclasses in a - given mapped class hierarchy are stored in a single table. - - Each subclass declares its own persistent properties and - subclasses. Version and id properties are assumed to be inherited from - the root class. Each subclass in a hierarchy must define a unique - discriminator value. If this is not specified, the fully qualified - Java class name is used. - - @Entity -@Inheritance(strategy=InheritanceType.SINGLE_TABLE) -@DiscriminatorColumn( - name="planetype", - discriminatorType=DiscriminatorType.STRING -) -@DiscriminatorValue("Plane") -public class Plane { ... } - -@Entity -@DiscriminatorValue("A320") -public class A320 extends Plane { ... } - - In hbm.xml, for the table-per-class-hierarchy mapping strategy, - the <subclass> declaration is used. For - example: - - - - - - - - - - - - - <subclass - name="ClassName" - discriminator-value="discriminator_value" - proxy="ProxyInterface" - lazy="true|false" - dynamic-update="true|false" - dynamic-insert="true|false" - entity-name="EntityName" - node="element-name" - extends="SuperclassName"> - - <property .... /> - ..... -</subclass> - - - - name: the fully qualified class name of - the subclass. - - - - discriminator-value (optional - - defaults to the class name): a value that distinguishes - individual subclasses. - - - - proxy (optional): specifies a class or - interface used for lazy initializing proxies. - - - - lazy (optional - defaults to - true): setting - lazy="false" disables the use of lazy - fetching. - - - - - For information about inheritance mappings see . - -
- Discriminator - - Discriminators are required for polymorphic persistence using - the table-per-class-hierarchy mapping strategy. It declares a - discriminator column of the table. The discriminator column contains - marker values that tell the persistence layer what subclass to - instantiate for a particular row. A restricted set of types can be - used: string, character, - integer, byte, - short, boolean, - yes_no, true_false. - - Use the @DiscriminatorColumn to define - the discriminator column as well as the discriminator type. - Alternatively, you can also use - @DiscriminatorFormula to express in SQL what - would be in a virtual discriminator column. This is particularly - handy when the discriminator value can be extracted from one or more - columns of the table. Both - @DiscriminatorColumn and - @DiscriminatorFormula are to be set on the - root entity (once per persisted hierarchy). - - Finally, use @DiscriminatorValue on - each class of the hierarchy to specify the value stored in the - discriminator column for a given entity. If you do not set - @DiscriminatorValue on a class, the fully - qualified class name is used. - - @Entity -@Inheritance(strategy=InheritanceType.SINGLE_TABLE) -@DiscriminatorColumn( - name="planetype", - discriminatorType=DiscriminatorType.STRING -) -@DiscriminatorValue("Plane") -public class Plane { ... } - -@Entity -@DiscriminatorValue("A320") -public class A320 extends Plane { ... } - - In hbm.xml, the <discriminator> - element is used to define the discriminator column or - formula: - - - - - - - - - - - - - - - <discriminator - column="discriminator_column" - type="discriminator_type" - force="true|false" - insert="true|false" - formula="arbitrary sql expression" -/> - - - - column (optional - defaults to - class): the name of the discriminator - column. - - - - type (optional - defaults to - string): a name that indicates the - Hibernate type - - - - force (optional - defaults to - false): "forces" Hibernate to specify the - allowed discriminator values, even when retrieving all - instances of the root class. - - - - insert (optional - defaults to - true): set this to false - if your discriminator column is also part of a mapped - composite identifier. It tells Hibernate not to include the - column in SQL INSERTs. - - - - formula (optional): an arbitrary SQL - expression that is executed when a type has to be evaluated. - It allows content-based discrimination. - - - - - Actual values of the discriminator column are specified by the - discriminator-value attribute of the - <class> and - <subclass> elements. - - The force attribute is only useful if the - table contains rows with "extra" discriminator values that are not - mapped to a persistent class. This will not usually be the - case. - - The formula attribute allows you to declare - an arbitrary SQL expression that will be used to evaluate the type - of a row. For example: - - <discriminator - formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0 else 1 end" - type="integer"/> -
-
- -
- Joined subclass strategy - - Each subclass can also be mapped to its own table. This is - called the table-per-subclass mapping strategy. An inherited state is - retrieved by joining with the table of the superclass. A discriminator - column is not required for this mapping strategy. Each subclass must, - however, declare a table column holding the object identifier. The - primary key of this table is also a foreign key to the superclass - table and described by the - @PrimaryKeyJoinColumns or the - <key> element. - - @Entity @Table(name="CATS") -@Inheritance(strategy=InheritanceType.JOINED) -public class Cat implements Serializable { - @Id @GeneratedValue(generator="cat-uuid") - @GenericGenerator(name="cat-uuid", strategy="uuid") - String getId() { return id; } - - ... -} - -@Entity @Table(name="DOMESTIC_CATS") -@PrimaryKeyJoinColumn(name="CAT") -public class DomesticCat extends Cat { - public String getName() { return name; } -} - - - The table name still defaults to the non qualified class name. - Also if @PrimaryKeyJoinColumn is not set, the - primary key / foreign key columns are assumed to have the same names - as the primary key columns of the primary table of the - superclass. - - - In hbm.xml, use the <joined-subclass> - element. For example: - - - - - - - - - - - - - <joined-subclass - name="ClassName" - table="tablename" - proxy="ProxyInterface" - lazy="true|false" - dynamic-update="true|false" - dynamic-insert="true|false" - schema="schema" - catalog="catalog" - extends="SuperclassName" - persister="ClassName" - subselect="SQL expression" - entity-name="EntityName" - node="element-name"> - - <key .... > - - <property .... /> - ..... -</joined-subclass> - - - - name: the fully qualified class name of - the subclass. - - - - table: the name of the subclass - table. - - - - proxy (optional): specifies a class or - interface to use for lazy initializing proxies. - - - - lazy (optional, defaults to - true): setting - lazy="false" disables the use of lazy - fetching. - - - - - Use the <key> element to declare the - primary key / foreign key column. The mapping at the start of the - chapter would then be re-written as: - - <?xml version="1.0"?> -<!DOCTYPE hibernate-mapping PUBLIC - "-//Hibernate/Hibernate Mapping DTD//EN" - "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> - -<hibernate-mapping package="eg"> - - <class name="Cat" table="CATS"> - <id name="id" column="uid" type="long"> - <generator class="hilo"/> - </id> - <property name="birthdate" type="date"/> - <property name="color" not-null="true"/> - <property name="sex" not-null="true"/> - <property name="weight"/> - <many-to-one name="mate"/> - <set name="kittens"> - <key column="MOTHER"/> - <one-to-many class="Cat"/> - </set> - <joined-subclass name="DomesticCat" table="DOMESTIC_CATS"> - <key column="CAT"/> - <property name="name" type="string"/> - </joined-subclass> - </class> - - <class name="eg.Dog"> - <!-- mapping for Dog could go here --> - </class> - -</hibernate-mapping> - - For information about inheritance mappings see . -
- -
- Table per class strategy - - A third option is to map only the concrete classes of an - inheritance hierarchy to tables. This is called the - table-per-concrete-class strategy. Each table defines all persistent - states of the class, including the inherited state. In Hibernate, it - is not necessary to explicitly map such inheritance hierarchies. You - can map each class as a separate entity root. However, if you wish use - polymorphic associations (e.g. an association to the superclass of - your hierarchy), you need to use the union subclass mapping. - - @Entity -@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) -public class Flight implements Serializable { ... } - - Or in hbm.xml: - - - - - - - - - - - - - <union-subclass - name="ClassName" - table="tablename" - proxy="ProxyInterface" - lazy="true|false" - dynamic-update="true|false" - dynamic-insert="true|false" - schema="schema" - catalog="catalog" - extends="SuperclassName" - abstract="true|false" - persister="ClassName" - subselect="SQL expression" - entity-name="EntityName" - node="element-name"> - - <property .... /> - ..... -</union-subclass> - - - - name: the fully qualified class name of - the subclass. - - - - table: the name of the subclass - table. - - - - proxy (optional): specifies a class or - interface to use for lazy initializing proxies. - - - - lazy (optional, defaults to - true): setting - lazy="false" disables the use of lazy - fetching. - - - - - No discriminator column or key column is required for this - mapping strategy. - - For information about inheritance mappings see . -
- -
- Inherit properties from superclasses - - This is sometimes useful to share common properties through a - technical or a business superclass without including it as a regular - mapped entity (ie no specific table for this entity). For that purpose - you can map them as @MappedSuperclass. - - @MappedSuperclass -public class BaseEntity { - @Basic - @Temporal(TemporalType.TIMESTAMP) - public Date getLastUpdate() { ... } - public String getLastUpdater() { ... } - ... -} - -@Entity class Order extends BaseEntity { - @Id public Integer getId() { ... } - ... -} - - In database, this hierarchy will be represented as an - Order table having the id, - lastUpdate and lastUpdater - columns. The embedded superclass property mappings are copied into - their entity subclasses. Remember that the embeddable superclass is - not the root of the hierarchy though. - - - Properties from superclasses not mapped as - @MappedSuperclass are ignored. - - - - The default access type (field or methods) is used, unless you - use the @Access annotation. - - - - The same notion can be applied to - @Embeddable objects to persist properties from - their superclasses. You also need to use - @MappedSuperclass to do that (this should not be - considered as a standard EJB3 feature though) - - - - It is allowed to mark a class as - @MappedSuperclass in the middle of the mapped - inheritance hierarchy. - - - - Any class in the hierarchy non annotated with - @MappedSuperclass nor @Entity - will be ignored. - - - You can override columns defined in entity superclasses at the - root entity level using the @AttributeOverride - annotation. - - @MappedSuperclass -public class FlyingObject implements Serializable { - - public int getAltitude() { - return altitude; - } - - @Transient - public int getMetricAltitude() { - return metricAltitude; - } - - @ManyToOne - public PropulsionType getPropulsion() { - return metricAltitude; - } - ... -} - -@Entity -@AttributeOverride( name="altitude", column = @Column(name="fld_altitude") ) -@AssociationOverride( - name="propulsion", - joinColumns = @JoinColumn(name="fld_propulsion_fk") -) -public class Plane extends FlyingObject { - ... -} - - The altitude property will be persisted in an - fld_altitude column of table - Plane and the propulsion association will be - materialized in a fld_propulsion_fk foreign key - column. - - You can define @AttributeOverride(s) and - @AssociationOverride(s) on - @Entity classes, - @MappedSuperclass classes and properties pointing - to an @Embeddable object. - - In hbm.xml, simply map the properties of the superclass in the - <class> element of the entity that needs to - inherit them. -
- -
- Mapping one entity to several tables - - While not recommended for a fresh schema, some legacy databases - force your to map a single entity on several tables. - - Using the @SecondaryTable or - @SecondaryTables class level annotations. To - express that a column is in a particular table, use the - table parameter of @Column or - @JoinColumn. - - @Entity -@Table(name="MainCat") -@SecondaryTables({ - @SecondaryTable(name="Cat1", pkJoinColumns={ - @PrimaryKeyJoinColumn(name="cat_id", referencedColumnName="id") - ), - @SecondaryTable(name="Cat2", uniqueConstraints={@UniqueConstraint(columnNames={"storyPart2"})}) -}) -public class Cat implements Serializable { - - private Integer id; - private String name; - private String storyPart1; - private String storyPart2; - - @Id @GeneratedValue - public Integer getId() { - return id; - } - - public String getName() { - return name; - } - - @Column(table="Cat1") - public String getStoryPart1() { - return storyPart1; - } - - @Column(table="Cat2") - public String getStoryPart2() { - return storyPart2; - } -} - - In this example, name will be in - MainCat. storyPart1 will be in - Cat1 and storyPart2 will be in - Cat2. Cat1 will be joined to - MainCat using the cat_id as a - foreign key, and Cat2 using id - (ie the same column name, the MainCat id column - has). Plus a unique constraint on storyPart2 has - been set. - - There is also additional tuning accessible via the - @org.hibernate.annotations.Table - annotation: - - - - fetch: If set to JOIN, the default, - Hibernate will use an inner join to retrieve a secondary table - defined by a class or its superclasses and an outer join for a - secondary table defined by a subclass. If set to - SELECT then Hibernate will use a sequential - select for a secondary table defined on a subclass, which will be - issued only if a row turns out to represent an instance of the - subclass. Inner joins will still be used to retrieve a secondary - defined by the class and its superclasses. - - - - inverse: If true, Hibernate will not try - to insert or update the properties defined by this join. Default - to false. - - - - optional: If enabled (the default), - Hibernate will insert a row only if the properties defined by this - join are non-null and will always use an outer join to retrieve - the properties. - - - - foreignKey: defines the Foreign Key name - of a secondary table pointing back to the primary table. - - - - Make sure to use the secondary table name in the - appliesto property - - @Entity -@Table(name="MainCat") -@SecondaryTable(name="Cat1") -@org.hibernate.annotations.Table( - appliesTo="Cat1", - fetch=FetchMode.SELECT, - optional=true) -public class Cat implements Serializable { - - private Integer id; - private String name; - private String storyPart1; - private String storyPart2; - - @Id @GeneratedValue - public Integer getId() { - return id; - } - - public String getName() { - return name; - } - - @Column(table="Cat1") - public String getStoryPart1() { - return storyPart1; - } - - @Column(table="Cat2") - public String getStoryPart2() { - return storyPart2; - } -} - - In hbm.xml, use the <join> - element. - - - - - - - - - - - - - - - - - <join - table="tablename" - schema="owner" - catalog="catalog" - fetch="join|select" - inverse="true|false" - optional="true|false"> - - <key ... /> - - <property ... /> - ... -</join> - - - - table: the name of the joined - table. - - - - schema (optional): overrides the schema - name specified by the root - <hibernate-mapping> element. - - - - catalog (optional): overrides the - catalog name specified by the root - <hibernate-mapping> element. - - - - fetch (optional - defaults to - join): if set to join, the - default, Hibernate will use an inner join to retrieve a - <join> defined by a class or its - superclasses. It will use an outer join for a - <join> defined by a subclass. If set to - select then Hibernate will use a sequential - select for a <join> defined on a - subclass. This will be issued only if a row represents an - instance of the subclass. Inner joins will still be used to - retrieve a <join> defined by the class - and its superclasses. - - - - inverse (optional - defaults to - false): if enabled, Hibernate will not insert - or update the properties defined by this join. - - - - optional (optional - defaults to - false): if enabled, Hibernate will insert a - row only if the properties defined by this join are non-null. It - will always use an outer join to retrieve the properties. - - - - - For example, address information for a person can be mapped to a - separate table while preserving value type semantics for all - properties: - - <class name="Person" - table="PERSON"> - - <id name="id" column="PERSON_ID">...</id> - - <join table="ADDRESS"> - <key column="ADDRESS_ID"/> - <property name="address"/> - <property name="zip"/> - <property name="country"/> - </join> - ... - - This feature is often only useful for legacy data models. We - recommend fewer tables than classes and a fine-grained domain model. - However, it is useful for switching between inheritance mapping - strategies in a single hierarchy, as explained later. -
-
-
Optimistic locking properties (optional) @@ -4182,6 +3046,1012 @@ public long getObjectVolume()
+
+ Embedded objects (aka components) + + Embeddable objects (or components) are objects whose properties + are mapped to the same table as the owning entity's table. Components + can, in turn, declare their own properties, components or + collections + + It is possible to declare an embedded component inside an entity + and even override its column mapping. Component classes have to be + annotated at the class level with the @Embeddable + annotation. It is possible to override the column mapping of an embedded + object for a particular entity using the @Embedded + and @AttributeOverride annotation in the associated + property: + + @Entity +public class Person implements Serializable { + + // Persistent component using defaults + Address homeAddress; + + @Embedded + @AttributeOverrides( { + @AttributeOverride(name="iso2", column = @Column(name="bornIso2") ), + @AttributeOverride(name="name", column = @Column(name="bornCountryName") ) + } ) + Country bornIn; + ... +} + + @Embeddable +public class Address implements Serializable { + String city; + Country nationality; //no overriding here +} + + @Embeddable +public class Country implements Serializable { + private String iso2; + @Column(name="countryName") private String name; + + public String getIso2() { return iso2; } + public void setIso2(String iso2) { this.iso2 = iso2; } + + + public String getName() { return name; } + public void setName(String name) { this.name = name; } + ... +} + + An embeddable object inherits the access type of its owning entity + (note that you can override that using the @Access + annotation). + + The Person entity has two component properties, + homeAddress and bornIn. + homeAddress property has not been annotated, but + Hibernate will guess that it is a persistent component by looking for + the @Embeddable annotation in the Address class. We + also override the mapping of a column name (to + bornCountryName) with the + @Embedded and @AttributeOverride + annotations for each mapped attribute of + Country. As you can see, Country + is also a nested component of Address, + again using auto-detection by Hibernate and JPA defaults. Overriding + columns of embedded objects of embedded objects is through dotted + expressions. + + @Embedded + @AttributeOverrides( { + @AttributeOverride(name="city", column = @Column(name="fld_city") ), + @AttributeOverride(name="nationality.iso2", column = @Column(name="nat_Iso2") ), + @AttributeOverride(name="nationality.name", column = @Column(name="nat_CountryName") ) + //nationality columns in homeAddress are overridden + } ) + Address homeAddress; + + Hibernate Annotations supports something that is not explicitly + supported by the JPA specification. You can annotate a embedded object + with the @MappedSuperclass annotation to make the + superclass properties persistent (see + @MappedSuperclass for more informations). + + You can also use association annotations in an embeddable object + (ie @OneToOne, @ManyToOne, + @OneToMany or @ManyToMany). To + override the association columns you can use + @AssociationOverride. + + If you want to have the same embeddable object type twice in the + same entity, the column name defaulting will not work as several + embedded objects would share the same set of columns. In plain JPA, you + need to override at least one set of columns. Hibernate, however, allows + you to enhance the default naming mechanism through the + NamingStrategy interface. You can write a + strategy that prevent name clashing in such a situation. + DefaultComponentSafeNamingStrategy is an example + of this. + + If a property of the embedded object points back to the owning + entity, annotate it with the @Parent annotation. + Hibernate will make sure this property is properly loaded with the + entity reference. + + In XML, use the <component> + element. + + + + + + + + + + + + + + + + + + + + + <component + name="propertyName" + class="className" + insert="true|false" + update="true|false" + access="field|property|ClassName" + lazy="true|false" + optimistic-lock="true|false" + unique="true|false" + node="element-name|." +> + + <property ...../> + <many-to-one .... /> + ........ +</component> + + + + name: the name of the property. + + + + class (optional - defaults to the + property type determined by reflection): the name of the component + (child) class. + + + + insert: do the mapped columns appear in + SQL INSERTs? + + + + update: do the mapped columns appear in + SQL UPDATEs? + + + + access (optional - defaults to + property): the strategy Hibernate uses for + accessing the property value. + + + + lazy (optional - defaults to + false): specifies that this component should be + fetched lazily when the instance variable is first accessed. It + requires build-time bytecode instrumentation. + + + + optimistic-lock (optional - defaults to + true): specifies that updates to this component + either do or do not require acquisition of the optimistic lock. It + determines if a version increment should occur when this property + is dirty. + + + + unique (optional - defaults to + false): specifies that a unique constraint + exists upon all mapped columns of the component. + + + + + The child <property> tags map properties + of the child class to table columns. + + The <component> element allows a + <parent> subelement that maps a property of the + component class as a reference back to the containing entity. + + The <dynamic-component> element allows a + Map to be mapped as a component, where the property + names refer to keys of the map. See for more information. This feature is + not supported in annotations. +
+ +
+ Inheritance strategy + + Java is a language supporting polymorphism: a class can inherit + from another. Several strategies are possible to persist a class + hierarchy: + + + + Single table per class hierarchy strategy: a single table + hosts all the instances of a class hierarchy + + + + Joined subclass strategy: one table per class and subclass is + present and each table persist the properties specific to a given + subclass. The state of the entity is then stored in its + corresponding class table and all its superclasses + + + + Table per class strategy: one table per concrete class and + subclass is present and each table persist the properties of the + class and its superclasses. The state of the entity is then stored + entirely in the dedicated table for its class. + + + +
+ Single table per class hierarchy strategy + + With this approach the properties of all the subclasses in a + given mapped class hierarchy are stored in a single table. + + Each subclass declares its own persistent properties and + subclasses. Version and id properties are assumed to be inherited from + the root class. Each subclass in a hierarchy must define a unique + discriminator value. If this is not specified, the fully qualified + Java class name is used. + + @Entity +@Inheritance(strategy=InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn( + name="planetype", + discriminatorType=DiscriminatorType.STRING +) +@DiscriminatorValue("Plane") +public class Plane { ... } + +@Entity +@DiscriminatorValue("A320") +public class A320 extends Plane { ... } + + In hbm.xml, for the table-per-class-hierarchy mapping strategy, + the <subclass> declaration is used. For + example: + + + + + + + + + + + + + <subclass + name="ClassName" + discriminator-value="discriminator_value" + proxy="ProxyInterface" + lazy="true|false" + dynamic-update="true|false" + dynamic-insert="true|false" + entity-name="EntityName" + node="element-name" + extends="SuperclassName"> + + <property .... /> + ..... +</subclass> + + + + name: the fully qualified class name of + the subclass. + + + + discriminator-value (optional - + defaults to the class name): a value that distinguishes + individual subclasses. + + + + proxy (optional): specifies a class or + interface used for lazy initializing proxies. + + + + lazy (optional - defaults to + true): setting + lazy="false" disables the use of lazy + fetching. + + + + + For information about inheritance mappings see . + +
+ Discriminator + + Discriminators are required for polymorphic persistence using + the table-per-class-hierarchy mapping strategy. It declares a + discriminator column of the table. The discriminator column contains + marker values that tell the persistence layer what subclass to + instantiate for a particular row. A restricted set of types can be + used: string, character, + integer, byte, + short, boolean, + yes_no, true_false. + + Use the @DiscriminatorColumn to define + the discriminator column as well as the discriminator type. + Alternatively, you can also use + @DiscriminatorFormula to express in SQL what + would be in a virtual discriminator column. This is particularly + handy when the discriminator value can be extracted from one or more + columns of the table. Both + @DiscriminatorColumn and + @DiscriminatorFormula are to be set on the + root entity (once per persisted hierarchy). + + Finally, use @DiscriminatorValue on + each class of the hierarchy to specify the value stored in the + discriminator column for a given entity. If you do not set + @DiscriminatorValue on a class, the fully + qualified class name is used. + + @Entity +@Inheritance(strategy=InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn( + name="planetype", + discriminatorType=DiscriminatorType.STRING +) +@DiscriminatorValue("Plane") +public class Plane { ... } + +@Entity +@DiscriminatorValue("A320") +public class A320 extends Plane { ... } + + In hbm.xml, the <discriminator> + element is used to define the discriminator column or + formula: + + + + + + + + + + + + + + + <discriminator + column="discriminator_column" + type="discriminator_type" + force="true|false" + insert="true|false" + formula="arbitrary sql expression" +/> + + + + column (optional - defaults to + class): the name of the discriminator + column. + + + + type (optional - defaults to + string): a name that indicates the + Hibernate type + + + + force (optional - defaults to + false): "forces" Hibernate to specify the + allowed discriminator values, even when retrieving all + instances of the root class. + + + + insert (optional - defaults to + true): set this to false + if your discriminator column is also part of a mapped + composite identifier. It tells Hibernate not to include the + column in SQL INSERTs. + + + + formula (optional): an arbitrary SQL + expression that is executed when a type has to be evaluated. + It allows content-based discrimination. + + + + + Actual values of the discriminator column are specified by the + discriminator-value attribute of the + <class> and + <subclass> elements. + + The force attribute is only useful if the + table contains rows with "extra" discriminator values that are not + mapped to a persistent class. This will not usually be the + case. + + The formula attribute allows you to declare + an arbitrary SQL expression that will be used to evaluate the type + of a row. For example: + + <discriminator + formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0 else 1 end" + type="integer"/> +
+
+ +
+ Joined subclass strategy + + Each subclass can also be mapped to its own table. This is + called the table-per-subclass mapping strategy. An inherited state is + retrieved by joining with the table of the superclass. A discriminator + column is not required for this mapping strategy. Each subclass must, + however, declare a table column holding the object identifier. The + primary key of this table is also a foreign key to the superclass + table and described by the + @PrimaryKeyJoinColumns or the + <key> element. + + @Entity @Table(name="CATS") +@Inheritance(strategy=InheritanceType.JOINED) +public class Cat implements Serializable { + @Id @GeneratedValue(generator="cat-uuid") + @GenericGenerator(name="cat-uuid", strategy="uuid") + String getId() { return id; } + + ... +} + +@Entity @Table(name="DOMESTIC_CATS") +@PrimaryKeyJoinColumn(name="CAT") +public class DomesticCat extends Cat { + public String getName() { return name; } +} + + + The table name still defaults to the non qualified class name. + Also if @PrimaryKeyJoinColumn is not set, the + primary key / foreign key columns are assumed to have the same names + as the primary key columns of the primary table of the + superclass. + + + In hbm.xml, use the <joined-subclass> + element. For example: + + + + + + + + + + + + + <joined-subclass + name="ClassName" + table="tablename" + proxy="ProxyInterface" + lazy="true|false" + dynamic-update="true|false" + dynamic-insert="true|false" + schema="schema" + catalog="catalog" + extends="SuperclassName" + persister="ClassName" + subselect="SQL expression" + entity-name="EntityName" + node="element-name"> + + <key .... > + + <property .... /> + ..... +</joined-subclass> + + + + name: the fully qualified class name of + the subclass. + + + + table: the name of the subclass + table. + + + + proxy (optional): specifies a class or + interface to use for lazy initializing proxies. + + + + lazy (optional, defaults to + true): setting + lazy="false" disables the use of lazy + fetching. + + + + + Use the <key> element to declare the + primary key / foreign key column. The mapping at the start of the + chapter would then be re-written as: + + <?xml version="1.0"?> +<!DOCTYPE hibernate-mapping PUBLIC + "-//Hibernate/Hibernate Mapping DTD//EN" + "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> + +<hibernate-mapping package="eg"> + + <class name="Cat" table="CATS"> + <id name="id" column="uid" type="long"> + <generator class="hilo"/> + </id> + <property name="birthdate" type="date"/> + <property name="color" not-null="true"/> + <property name="sex" not-null="true"/> + <property name="weight"/> + <many-to-one name="mate"/> + <set name="kittens"> + <key column="MOTHER"/> + <one-to-many class="Cat"/> + </set> + <joined-subclass name="DomesticCat" table="DOMESTIC_CATS"> + <key column="CAT"/> + <property name="name" type="string"/> + </joined-subclass> + </class> + + <class name="eg.Dog"> + <!-- mapping for Dog could go here --> + </class> + +</hibernate-mapping> + + For information about inheritance mappings see . +
+ +
+ Table per class strategy + + A third option is to map only the concrete classes of an + inheritance hierarchy to tables. This is called the + table-per-concrete-class strategy. Each table defines all persistent + states of the class, including the inherited state. In Hibernate, it + is not necessary to explicitly map such inheritance hierarchies. You + can map each class as a separate entity root. However, if you wish use + polymorphic associations (e.g. an association to the superclass of + your hierarchy), you need to use the union subclass mapping. + + @Entity +@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) +public class Flight implements Serializable { ... } + + Or in hbm.xml: + + + + + + + + + + + + + <union-subclass + name="ClassName" + table="tablename" + proxy="ProxyInterface" + lazy="true|false" + dynamic-update="true|false" + dynamic-insert="true|false" + schema="schema" + catalog="catalog" + extends="SuperclassName" + abstract="true|false" + persister="ClassName" + subselect="SQL expression" + entity-name="EntityName" + node="element-name"> + + <property .... /> + ..... +</union-subclass> + + + + name: the fully qualified class name of + the subclass. + + + + table: the name of the subclass + table. + + + + proxy (optional): specifies a class or + interface to use for lazy initializing proxies. + + + + lazy (optional, defaults to + true): setting + lazy="false" disables the use of lazy + fetching. + + + + + No discriminator column or key column is required for this + mapping strategy. + + For information about inheritance mappings see . +
+ +
+ Inherit properties from superclasses + + This is sometimes useful to share common properties through a + technical or a business superclass without including it as a regular + mapped entity (ie no specific table for this entity). For that purpose + you can map them as @MappedSuperclass. + + @MappedSuperclass +public class BaseEntity { + @Basic + @Temporal(TemporalType.TIMESTAMP) + public Date getLastUpdate() { ... } + public String getLastUpdater() { ... } + ... +} + +@Entity class Order extends BaseEntity { + @Id public Integer getId() { ... } + ... +} + + In database, this hierarchy will be represented as an + Order table having the id, + lastUpdate and lastUpdater + columns. The embedded superclass property mappings are copied into + their entity subclasses. Remember that the embeddable superclass is + not the root of the hierarchy though. + + + Properties from superclasses not mapped as + @MappedSuperclass are ignored. + + + + The default access type (field or methods) is used, unless you + use the @Access annotation. + + + + The same notion can be applied to + @Embeddable objects to persist properties from + their superclasses. You also need to use + @MappedSuperclass to do that (this should not be + considered as a standard EJB3 feature though) + + + + It is allowed to mark a class as + @MappedSuperclass in the middle of the mapped + inheritance hierarchy. + + + + Any class in the hierarchy non annotated with + @MappedSuperclass nor @Entity + will be ignored. + + + You can override columns defined in entity superclasses at the + root entity level using the @AttributeOverride + annotation. + + @MappedSuperclass +public class FlyingObject implements Serializable { + + public int getAltitude() { + return altitude; + } + + @Transient + public int getMetricAltitude() { + return metricAltitude; + } + + @ManyToOne + public PropulsionType getPropulsion() { + return metricAltitude; + } + ... +} + +@Entity +@AttributeOverride( name="altitude", column = @Column(name="fld_altitude") ) +@AssociationOverride( + name="propulsion", + joinColumns = @JoinColumn(name="fld_propulsion_fk") +) +public class Plane extends FlyingObject { + ... +} + + The altitude property will be persisted in an + fld_altitude column of table + Plane and the propulsion association will be + materialized in a fld_propulsion_fk foreign key + column. + + You can define @AttributeOverride(s) and + @AssociationOverride(s) on + @Entity classes, + @MappedSuperclass classes and properties pointing + to an @Embeddable object. + + In hbm.xml, simply map the properties of the superclass in the + <class> element of the entity that needs to + inherit them. +
+ +
+ Mapping one entity to several tables + + While not recommended for a fresh schema, some legacy databases + force your to map a single entity on several tables. + + Using the @SecondaryTable or + @SecondaryTables class level annotations. To + express that a column is in a particular table, use the + table parameter of @Column or + @JoinColumn. + + @Entity +@Table(name="MainCat") +@SecondaryTables({ + @SecondaryTable(name="Cat1", pkJoinColumns={ + @PrimaryKeyJoinColumn(name="cat_id", referencedColumnName="id") + ), + @SecondaryTable(name="Cat2", uniqueConstraints={@UniqueConstraint(columnNames={"storyPart2"})}) +}) +public class Cat implements Serializable { + + private Integer id; + private String name; + private String storyPart1; + private String storyPart2; + + @Id @GeneratedValue + public Integer getId() { + return id; + } + + public String getName() { + return name; + } + + @Column(table="Cat1") + public String getStoryPart1() { + return storyPart1; + } + + @Column(table="Cat2") + public String getStoryPart2() { + return storyPart2; + } +} + + In this example, name will be in + MainCat. storyPart1 will be in + Cat1 and storyPart2 will be in + Cat2. Cat1 will be joined to + MainCat using the cat_id as a + foreign key, and Cat2 using id + (ie the same column name, the MainCat id column + has). Plus a unique constraint on storyPart2 has + been set. + + There is also additional tuning accessible via the + @org.hibernate.annotations.Table + annotation: + + + + fetch: If set to JOIN, the default, + Hibernate will use an inner join to retrieve a secondary table + defined by a class or its superclasses and an outer join for a + secondary table defined by a subclass. If set to + SELECT then Hibernate will use a sequential + select for a secondary table defined on a subclass, which will be + issued only if a row turns out to represent an instance of the + subclass. Inner joins will still be used to retrieve a secondary + defined by the class and its superclasses. + + + + inverse: If true, Hibernate will not try + to insert or update the properties defined by this join. Default + to false. + + + + optional: If enabled (the default), + Hibernate will insert a row only if the properties defined by this + join are non-null and will always use an outer join to retrieve + the properties. + + + + foreignKey: defines the Foreign Key name + of a secondary table pointing back to the primary table. + + + + Make sure to use the secondary table name in the + appliesto property + + @Entity +@Table(name="MainCat") +@SecondaryTable(name="Cat1") +@org.hibernate.annotations.Table( + appliesTo="Cat1", + fetch=FetchMode.SELECT, + optional=true) +public class Cat implements Serializable { + + private Integer id; + private String name; + private String storyPart1; + private String storyPart2; + + @Id @GeneratedValue + public Integer getId() { + return id; + } + + public String getName() { + return name; + } + + @Column(table="Cat1") + public String getStoryPart1() { + return storyPart1; + } + + @Column(table="Cat2") + public String getStoryPart2() { + return storyPart2; + } +} + + In hbm.xml, use the <join> + element. + + + + + + + + + + + + + + + + + <join + table="tablename" + schema="owner" + catalog="catalog" + fetch="join|select" + inverse="true|false" + optional="true|false"> + + <key ... /> + + <property ... /> + ... +</join> + + + + table: the name of the joined + table. + + + + schema (optional): overrides the schema + name specified by the root + <hibernate-mapping> element. + + + + catalog (optional): overrides the + catalog name specified by the root + <hibernate-mapping> element. + + + + fetch (optional - defaults to + join): if set to join, the + default, Hibernate will use an inner join to retrieve a + <join> defined by a class or its + superclasses. It will use an outer join for a + <join> defined by a subclass. If set to + select then Hibernate will use a sequential + select for a <join> defined on a + subclass. This will be issued only if a row represents an + instance of the subclass. Inner joins will still be used to + retrieve a <join> defined by the class + and its superclasses. + + + + inverse (optional - defaults to + false): if enabled, Hibernate will not insert + or update the properties defined by this join. + + + + optional (optional - defaults to + false): if enabled, Hibernate will insert a + row only if the properties defined by this join are non-null. It + will always use an outer join to retrieve the properties. + + + + + For example, address information for a person can be mapped to a + separate table while preserving value type semantics for all + properties: + + <class name="Person" + table="PERSON"> + + <id name="id" column="PERSON_ID">...</id> + + <join table="ADDRESS"> + <key column="ADDRESS_ID"/> + <property name="address"/> + <property name="zip"/> + <property name="country"/> + </join> + ... + + This feature is often only useful for legacy data models. We + recommend fewer tables than classes and a fine-grained domain model. + However, it is useful for switching between inheritance mapping + strategies in a single hierarchy, as explained later. +
+
+
Mapping one to one and one to many associations @@ -4900,339 +4770,6 @@ List results = s.createCriteria( Citizen.class )
-
- Embedded objects (aka components) - - Embeddable objects (or components) are objects whose properties - are mapped to the same table as the owning entity's table. Components - can, in turn, declare their own properties, components or - collections - - It is possible to declare an embedded component inside an entity - and even override its column mapping. Component classes have to be - annotated at the class level with the @Embeddable - annotation. It is possible to override the column mapping of an embedded - object for a particular entity using the @Embedded - and @AttributeOverride annotation in the associated - property: - - @Entity -public class Person implements Serializable { - - // Persistent component using defaults - Address homeAddress; - - @Embedded - @AttributeOverrides( { - @AttributeOverride(name="iso2", column = @Column(name="bornIso2") ), - @AttributeOverride(name="name", column = @Column(name="bornCountryName") ) - } ) - Country bornIn; - ... -} - - @Embeddable -public class Address implements Serializable { - String city; - Country nationality; //no overriding here -} - - @Embeddable -public class Country implements Serializable { - private String iso2; - @Column(name="countryName") private String name; - - public String getIso2() { return iso2; } - public void setIso2(String iso2) { this.iso2 = iso2; } - - - public String getName() { return name; } - public void setName(String name) { this.name = name; } - ... -} - - An embeddable object inherits the access type of its owning entity - (note that you can override that using the @Access - annotation). - - The Person entity has two component properties, - homeAddress and bornIn. - homeAddress property has not been annotated, but - Hibernate will guess that it is a persistent component by looking for - the @Embeddable annotation in the Address class. We - also override the mapping of a column name (to - bornCountryName) with the - @Embedded and @AttributeOverride - annotations for each mapped attribute of - Country. As you can see, Country - is also a nested component of Address, - again using auto-detection by Hibernate and JPA defaults. Overriding - columns of embedded objects of embedded objects is through dotted - expressions. - - @Embedded - @AttributeOverrides( { - @AttributeOverride(name="city", column = @Column(name="fld_city") ), - @AttributeOverride(name="nationality.iso2", column = @Column(name="nat_Iso2") ), - @AttributeOverride(name="nationality.name", column = @Column(name="nat_CountryName") ) - //nationality columns in homeAddress are overridden - } ) - Address homeAddress; - - Hibernate Annotations supports something that is not explicitly - supported by the JPA specification. You can annotate a embedded object - with the @MappedSuperclass annotation to make the - superclass properties persistent (see - @MappedSuperclass for more informations). - - You can also use association annotations in an embeddable object - (ie @OneToOne, @ManyToOne, - @OneToMany or @ManyToMany). To - override the association columns you can use - @AssociationOverride. - - If you want to have the same embeddable object type twice in the - same entity, the column name defaulting will not work as several - embedded objects would share the same set of columns. In plain JPA, you - need to override at least one set of columns. Hibernate, however, allows - you to enhance the default naming mechanism through the - NamingStrategy interface. You can write a - strategy that prevent name clashing in such a situation. - DefaultComponentSafeNamingStrategy is an example - of this. - - If a property of the embedded object points back to the owning - entity, annotate it with the @Parent annotation. - Hibernate will make sure this property is properly loaded with the - entity reference. - - In XML, use the <component> - element. - - - - - - - - - - - - - - - - - - - - - <component - name="propertyName" - class="className" - insert="true|false" - update="true|false" - access="field|property|ClassName" - lazy="true|false" - optimistic-lock="true|false" - unique="true|false" - node="element-name|." -> - - <property ...../> - <many-to-one .... /> - ........ -</component> - - - - name: the name of the property. - - - - class (optional - defaults to the - property type determined by reflection): the name of the component - (child) class. - - - - insert: do the mapped columns appear in - SQL INSERTs? - - - - update: do the mapped columns appear in - SQL UPDATEs? - - - - access (optional - defaults to - property): the strategy Hibernate uses for - accessing the property value. - - - - lazy (optional - defaults to - false): specifies that this component should be - fetched lazily when the instance variable is first accessed. It - requires build-time bytecode instrumentation. - - - - optimistic-lock (optional - defaults to - true): specifies that updates to this component - either do or do not require acquisition of the optimistic lock. It - determines if a version increment should occur when this property - is dirty. - - - - unique (optional - defaults to - false): specifies that a unique constraint - exists upon all mapped columns of the component. - - - - - The child <property> tags map properties - of the child class to table columns. - - The <component> element allows a - <parent> subelement that maps a property of the - component class as a reference back to the containing entity. - - The <dynamic-component> element allows a - Map to be mapped as a component, where the property - names refer to keys of the map. See for more information. This feature is - not supported in annotations. -
- -
- Properties - - The <properties> element allows the - definition of a named, logical grouping of the properties of a class. - The most important use of the construct is that it allows a combination - of properties to be the target of a property-ref. It - is also a convenient way to define a multi-column unique constraint. For - example: - - - - - - - - - - - - - - - <properties - name="logicalName" - insert="true|false" - update="true|false" - optimistic-lock="true|false" - unique="true|false" -> - - <property ...../> - <many-to-one .... /> - ........ -</properties> - - - - name: the logical name of the grouping. - It is not an actual property name. - - - - insert: do the mapped columns appear in - SQL INSERTs? - - - - update: do the mapped columns appear in - SQL UPDATEs? - - - - optimistic-lock (optional - defaults to - true): specifies that updates to these - properties either do or do not require acquisition of the - optimistic lock. It determines if a version increment should occur - when these properties are dirty. - - - - unique (optional - defaults to - false): specifies that a unique constraint - exists upon all mapped columns of the component. - - - - - For example, if we have the following - <properties> mapping: - - <class name="Person"> - <id name="personNumber"/> - - ... - <properties name="name" - unique="true" update="false"> - <property name="firstName"/> - <property name="initial"/> - <property name="lastName"/> - </properties> -</class> - - You might have some legacy data association that refers to this - unique key of the Person table, instead of to the - primary key: - - <many-to-one name="owner" - class="Person" property-ref="name"> - <column name="firstName"/> - <column name="initial"/> - <column name="lastName"/> -</many-to-one> - - - When using annotations as a mapping strategy, such construct is - not necessary as the binding between a column and its related column - on the associated table is done directly - - @Entity -class Person { - @Id Integer personNumber; - String firstName; - @Column(name="I") - String initial; - String lastName; -} - -@Entity -class Home { - @ManyToOne - @JoinColumns({ - @JoinColumn(name="first_name", referencedColumnName="firstName"), - @JoinColumn(name="init", referencedColumnName="I"), - @JoinColumn(name="last_name", referencedColumnName="lastName"), - }) - Person owner -} - - - The use of this outside the context of mapping legacy data is not - recommended. -
-
Any @@ -5373,6 +4910,469 @@ package org.hibernate.test.annotations.any;
+ +
+ Properties + + The <properties> element allows the + definition of a named, logical grouping of the properties of a class. + The most important use of the construct is that it allows a combination + of properties to be the target of a property-ref. It + is also a convenient way to define a multi-column unique constraint. For + example: + + + + + + + + + + + + + + + <properties + name="logicalName" + insert="true|false" + update="true|false" + optimistic-lock="true|false" + unique="true|false" +> + + <property ...../> + <many-to-one .... /> + ........ +</properties> + + + + name: the logical name of the grouping. + It is not an actual property name. + + + + insert: do the mapped columns appear in + SQL INSERTs? + + + + update: do the mapped columns appear in + SQL UPDATEs? + + + + optimistic-lock (optional - defaults to + true): specifies that updates to these + properties either do or do not require acquisition of the + optimistic lock. It determines if a version increment should occur + when these properties are dirty. + + + + unique (optional - defaults to + false): specifies that a unique constraint + exists upon all mapped columns of the component. + + + + + For example, if we have the following + <properties> mapping: + + <class name="Person"> + <id name="personNumber"/> + + ... + <properties name="name" + unique="true" update="false"> + <property name="firstName"/> + <property name="initial"/> + <property name="lastName"/> + </properties> +</class> + + You might have some legacy data association that refers to this + unique key of the Person table, instead of to the + primary key: + + <many-to-one name="owner" + class="Person" property-ref="name"> + <column name="firstName"/> + <column name="initial"/> + <column name="lastName"/> +</many-to-one> + + + When using annotations as a mapping strategy, such construct is + not necessary as the binding between a column and its related column + on the associated table is done directly + + @Entity +class Person { + @Id Integer personNumber; + String firstName; + @Column(name="I") + String initial; + String lastName; +} + +@Entity +class Home { + @ManyToOne + @JoinColumns({ + @JoinColumn(name="first_name", referencedColumnName="firstName"), + @JoinColumn(name="init", referencedColumnName="I"), + @JoinColumn(name="last_name", referencedColumnName="lastName"), + }) + Person owner +} + + + The use of this outside the context of mapping legacy data is not + recommended. +
+ +
+ Some hbm.xml specificities + + The hbm.xml structure has some specificities naturally not present + when using annotations, let's describe them briefly. + +
+ Doctype + + All XML mappings should declare the doctype shown. The actual + DTD can be found at the URL above, in the directory + hibernate-x.x.x/src/org/hibernate , or in + hibernate3.jar. Hibernate will always look for the + DTD in its classpath first. If you experience lookups of the DTD using + an Internet connection, check the DTD declaration against the contents + of your classpath. + +
+ EntityResolver + + Hibernate will first attempt to resolve DTDs in its classpath. + It does this is by registering a custom + org.xml.sax.EntityResolver implementation with + the SAXReader it uses to read in the xml files. This custom + EntityResolver recognizes two different systemId + namespaces: + + + + a hibernate namespace is recognized + whenever the resolver encounters a systemId starting with + http://hibernate.sourceforge.net/. The + resolver attempts to resolve these entities via the classloader + which loaded the Hibernate classes. + + + + a user namespace is recognized whenever + the resolver encounters a systemId using a + classpath:// URL protocol. The resolver will + attempt to resolve these entities via (1) the current thread + context classloader and (2) the classloader which loaded the + Hibernate classes. + + + + The following is an example of utilizing user + namespacing: + + + + + + Where types.xml is a resource in the + your.domain package and contains a custom typedef. +
+
+ +
+ Hibernate-mapping + + This element has several optional attributes. The + schema and catalog attributes + specify that tables referred to in this mapping belong to the named + schema and/or catalog. If they are specified, tablenames will be + qualified by the given schema and catalog names. If they are missing, + tablenames will be unqualified. The default-cascade + attribute specifies what cascade style should be assumed for + properties and collections that do not specify a + cascade attribute. By default, the + auto-import attribute allows you to use unqualified + class names in the query language. + + + + + + + + + + + + + + + + + + + <hibernate-mapping + schema="schemaName" + catalog="catalogName" + default-cascade="cascade_style" + default-access="field|property|ClassName" + default-lazy="true|false" + auto-import="true|false" + package="package.name" + /> + + + + schema (optional): the name of a + database schema. + + + + catalog (optional): the name of a + database catalog. + + + + default-cascade (optional - defaults to + none): a default cascade style. + + + + default-access (optional - defaults to + property): the strategy Hibernate should use + for accessing all properties. It can be a custom implementation + of PropertyAccessor. + + + + default-lazy (optional - defaults to + true): the default value for unspecified + lazy attributes of class and collection + mappings. + + + + auto-import (optional - defaults to + true): specifies whether we can use + unqualified class names of classes in this mapping in the query + language. + + + + package (optional): specifies a package + prefix to use for unqualified class names in the mapping + document. + + + + + If you have two persistent classes with the same unqualified + name, you should set auto-import="false". An + exception will result if you attempt to assign two classes to the same + "imported" name. + + The hibernate-mapping element allows you to + nest several persistent <class> mappings, as + shown above. It is, however, good practice (and expected by some + tools) to map only a single persistent class, or a single class + hierarchy, in one mapping file and name it after the persistent + superclass. For example, Cat.hbm.xml, + Dog.hbm.xml, or if using inheritance, + Animal.hbm.xml. +
+ +
+ Key + + The <key> element is featured a few + times within this guide. It appears anywhere the parent mapping + element defines a join to a new table that references the primary key + of the original table. It also defines the foreign key in the joined + table: + + + + + + + + + + + + + + + + + <key + column="columnname" + on-delete="noaction|cascade" + property-ref="propertyName" + not-null="true|false" + update="true|false" + unique="true|false" +/> + + + + column (optional): the name of the + foreign key column. This can also be specified by nested + <column> element(s). + + + + on-delete (optional - defaults to + noaction): specifies whether the foreign key + constraint has database-level cascade delete enabled. + + + + property-ref (optional): specifies that + the foreign key refers to columns that are not the primary key + of the original table. It is provided for legacy data. + + + + not-null (optional): specifies that the + foreign key columns are not nullable. This is implied whenever + the foreign key is also part of the primary key. + + + + update (optional): specifies that the + foreign key should never be updated. This is implied whenever + the foreign key is also part of the primary key. + + + + unique (optional): specifies that the + foreign key should have a unique constraint. This is implied + whenever the foreign key is also the primary key. + + + + + For systems where delete performance is important, we recommend + that all keys should be defined + on-delete="cascade". Hibernate uses a + database-level ON CASCADE DELETE constraint, + instead of many individual DELETE statements. Be + aware that this feature bypasses Hibernate's usual optimistic locking + strategy for versioned data. + + The not-null and update + attributes are useful when mapping a unidirectional one-to-many + association. If you map a unidirectional one-to-many association to a + non-nullable foreign key, you must declare the + key column using <key + not-null="true">. +
+ +
+ Import + + If your application has two persistent classes with the same + name, and you do not want to specify the fully qualified package name + in Hibernate queries, classes can be "imported" explicitly, rather + than relying upon auto-import="true". You can also + import classes and interfaces that are not explicitly mapped: + + <import class="java.lang.Object" rename="Universe"/> + + + + + + + + + <import + class="ClassName" + rename="ShortName" +/> + + + + class: the fully qualified class name + of any Java class. + + + + rename (optional - defaults to the + unqualified class name): a name that can be used in the query + language. + + + + + + This feature is unique to hbm.xml and is not supported in + annotations. + +
+ +
+ Column and formula elements + + Mapping elements which accept a column + attribute will alternatively accept a + <column> subelement. Likewise, + <formula> is an alternative to the + formula attribute. For example: + + <column + name="column_name" + length="N" + precision="N" + scale="N" + not-null="true|false" + unique="true|false" + unique-key="multicolumn_unique_key_name" + index="index_name" + sql-type="sql_type_name" + check="SQL expression" + default="SQL expression" + read="SQL expression" + write="SQL expression"/> + + <formula>SQL expression</formula> + + Most of the attributes on column provide a + means of tailoring the DDL during automatic schema generation. The + read and write attributes allow + you to specify custom SQL that Hibernate will use to access the + column's value. For more on this, see the discussion of column read and write + expressions. + + The column and formula + elements can even be combined within the same property or association + mapping to express, for example, exotic join conditions. + + <many-to-one name="homeAddress" class="Address" + insert="false" update="false"> + <column name="person_id" not-null="true" length="10"/> + <formula>'MAILING'</formula> +</many-to-one> +
+