Académique Documents
Professionnel Documents
Culture Documents
::Relationship:: person(many) -> address(one) ::DB Schema:: person( personId, addressId ) address( addressId ) ::Java Operation:: person.getAddress(); ::Annotation::
@Entity @Table(name="PERSON") public class Person { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; @ManyToOne @JoinColumn(name = "ADDRESS_ID") private Address address; public Address getAddress() { return address; } } @Entity @Table(name="ADDRESS") public class Address { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; }
@Entity @Table(name="PERSON") public class Person { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name="personId") private int id; @OneToOne @JoinColumn(name="addressId") private Address address; } @Entity @Table(name = "ADDRESS") public class Address { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "addressId") private int id; }
8.1. Introduction
Association mappings are often the most difficult thing to implement correctly. In this section we examine some canonical cases one by one, starting with unidirectional mappings and then bidirectional cases. We will use Person and Address in all the examples. Associations will be classified by multiplicity and whether or not they map to an intervening join table. Nullable foreign keys are not considered to be good practice in traditional data modelling, so our examples do not use nullable foreign keys. This is not a requirement of Hibernate, and the mappings will work if you drop the nullability constraints.
8.2.2. One-to-one
A unidirectional one-to-one association on a foreign key is almost identical. The only difference is the column unique constraint.
<class name="Person"> <id name="id" column="personId"> <generator class="native"/>
</id> <many-to-one name="address" column="addressId" unique="true" not-null="true"/> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> </class> create table Person ( personId bigint not null primary key, addressId bigint not null unique ) create table Address ( addressId bigint not null primary key )
A unidirectional one-to-one association on a primary key usually uses a special id generator In this example, however, we have reversed the direction of the association:
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> </class> <class name="Address"> <id name="id" column="personId"> <generator class="foreign"> <param name="property">person</param> </generator> </id> <one-to-one name="person" constrained="true"/> </class> create table Person ( personId bigint not null primary key ) create table Address ( personId bigint not null primary key )
8.2.3. One-to-many
A unidirectional one-to-many association on a foreign key is an unusual case, and is not recommended.
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses"> <key column="personId" not-null="true"/> <one-to-many class="Address"/> </set>
</class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> </class> create table Person ( personId bigint not null primary key ) create table Address ( addressId bigint not null primary key, personId bigint not null )
You should instead use a join table for this kind of association.
8.3.2. Many-to-one
A unidirectional many-to-one association on a join table is common when the association is optional. For example:
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <join table="PersonAddress" optional="true"> <key column="personId" unique="true"/> <many-to-one name="address" column="addressId" not-null="true"/> </join> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> </class> create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId bigint not null primary key, addressId bigint not null ) create table Address ( addressId bigint not null primary key )
8.3.3. One-to-one
A unidirectional one-to-one association on a join table is possible, but extremely unusual.
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <join table="PersonAddress" optional="true"> <key column="personId" unique="true"/> <many-to-one name="address" column="addressId" not-null="true" unique="true"/> </join> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> </class> create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId bigint not null primary key, addressId bigint not null unique ) create table Address ( addressId bigint not null primary key )
8.3.4. Many-to-many
Finally, here is an example of a unidirectional many-to-many association.
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses" table="PersonAddress"> <key column="personId"/> <many-to-many column="addressId" class="Address"/> </set> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> </class> create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId) ) create table Address ( addressId bigint not null primary key )
create table Person ( personId bigint not null primary key, addressId bigint not null ) create table Address ( addressId bigint not null primary key )
If you use a List, or other indexed collection, set the key column of the foreign key to not null. Hibernate will manage the association from the collections side to maintain the index of each element, making the other side virtually inverse by setting update="false" and insert="false":
<class name="Person"> <id name="id"/> ... <many-to-one name="address" column="addressId" not-null="true" insert="false" update="false"/> </class> <class name="Address"> <id name="id"/> ... <list name="people"> <key column="addressId" not-null="true"/> <list-index column="peopleIdx"/> <one-to-many class="Person"/> </list> </class>
If the underlying foreign key column is NOT NULL, it is important that you define notnull="true" on the <key> element of the collection mapping. Do not only declare notnull="true" on a possible nested <column> element, but on the <key> element.
8.4.2. One-to-one
A bidirectional one-to-one association on a foreign key is common:
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <many-to-one name="address" column="addressId" unique="true" not-null="true"/> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/>
</id> <one-to-one name="person" property-ref="address"/> </class> create table Person ( personId bigint not null primary key, addressId bigint not null unique ) create table Address ( addressId bigint not null primary key )
<class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> <join table="PersonAddress" inverse="true" optional="true"> <key column="addressId"/> <many-to-one name="person" column="personId" not-null="true"/> </join> </class> create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId bigint not null, addressId bigint not null primary key ) create table Address ( addressId bigint not null primary key )
create table PersonAddress ( personId bigint not null primary key, addressId bigint not null unique ) create table Address ( addressId bigint not null primary key )
8.5.3. Many-to-many
Here is an example of a bidirectional many-to-many association.
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses" table="PersonAddress"> <key column="personId"/> <many-to-many column="addressId" class="Address"/> </set> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> <set name="people" inverse="true" table="PersonAddress"> <key column="addressId"/> <many-to-many column="personId" class="Person"/> </set> </class> create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId) ) create table Address ( addressId bigint not null primary key )
You can then map an association to the current instance, the one with null effectiveEndDate, by using:
<many-to-one name="currentAccountInfo" property-ref="currentAccountKey" class="AccountInfo"> <column name="accountNumber"/> <formula>'1'</formula> </many-to-one>
In a more complex example, imagine that the association between Employee and Organization is maintained in an Employment table full of historical employment data. An association to the employee's most recent employer, the one with the most recent startDate, could be mapped in the following way:
<join> <key column="employeeId"/> <subselect> select employeeId, orgId from Employments group by orgId having startDate = max(startDate) </subselect> <many-to-one name="mostRecentEmployer" class="Organization" column="orgId"/> </join>
8.1. Introduction
Association mappings are often the most difficult thing to implement correctly. In this section we examine some canonical cases one by one, starting with unidirectional mappings and then bidirectional cases. We will use Person and Address in all the examples. Associations will be classified by multiplicity and whether or not they map to an intervening join table. Nullable foreign keys are not considered to be good practice in traditional data modelling, so our examples do not use nullable foreign keys. This is not a requirement of Hibernate, and the mappings will work if you drop the nullability constraints.
8.2.2. One-to-one
A unidirectional one-to-one association on a foreign key is almost identical. The only difference is the column unique constraint.
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <many-to-one name="address" column="addressId" unique="true" not-null="true"/> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> </class> create table Person ( personId bigint not null primary key, addressId bigint not null unique ) create table Address ( addressId bigint not null primary key )
A unidirectional one-to-one association on a primary key usually uses a special id generator In this example, however, we have reversed the direction of the association:
<class name="Person">
<id name="id" column="personId"> <generator class="native"/> </id> </class> <class name="Address"> <id name="id" column="personId"> <generator class="foreign"> <param name="property">person</param> </generator> </id> <one-to-one name="person" constrained="true"/> </class> create table Person ( personId bigint not null primary key ) create table Address ( personId bigint not null primary key )
8.2.3. One-to-many
A unidirectional one-to-many association on a foreign key is an unusual case, and is not recommended.
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses"> <key column="personId" not-null="true"/> <one-to-many class="Address"/> </set> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> </class> create table Person ( personId bigint not null primary key ) create table Address ( addressId bigint not null primary key, personId bigint not null )
You should instead use a join table for this kind of association.
A unidirectional one-to-many association on a join table is the preferred option. Specifying unique="true", changes the multiplicity from many-to-many to one-tomany.
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses" table="PersonAddress"> <key column="personId"/> <many-to-many column="addressId" unique="true" class="Address"/> </set> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> </class> create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId not null, addressId bigint not null primary key ) create table Address ( addressId bigint not null primary key )
8.3.2. Many-to-one
A unidirectional many-to-one association on a join table is common when the association is optional. For example:
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <join table="PersonAddress" optional="true"> <key column="personId" unique="true"/> <many-to-one name="address" column="addressId" not-null="true"/> </join> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> </class> create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null primary key, addressId bigint not null ) create table Address ( addressId bigint not null primary key )
8.3.3. One-to-one
A unidirectional one-to-one association on a join table is possible, but extremely unusual.
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <join table="PersonAddress" optional="true"> <key column="personId" unique="true"/> <many-to-one name="address" column="addressId" not-null="true" unique="true"/> </join> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> </class> create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId bigint not null primary key, addressId bigint not null unique ) create table Address ( addressId bigint not null primary key )
8.3.4. Many-to-many
Finally, here is an example of a unidirectional many-to-many association.
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses" table="PersonAddress"> <key column="personId"/> <many-to-many column="addressId" class="Address"/> </set> </class> <class name="Address">
<id name="id" column="addressId"> <generator class="native"/> </id> </class> create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId) ) create table Address ( addressId bigint not null primary key )
If you use a List, or other indexed collection, set the key column of the foreign key to not null. Hibernate will manage the association from the collections side to maintain the index of each element, making the other side virtually inverse by setting update="false" and insert="false":
<class name="Person"> <id name="id"/> ... <many-to-one name="address" column="addressId" not-null="true"
insert="false" update="false"/> </class> <class name="Address"> <id name="id"/> ... <list name="people"> <key column="addressId" not-null="true"/> <list-index column="peopleIdx"/> <one-to-many class="Person"/> </list> </class>
If the underlying foreign key column is NOT NULL, it is important that you define notnull="true" on the <key> element of the collection mapping. Do not only declare notnull="true" on a possible nested <column> element, but on the <key> element.
8.4.2. One-to-one
A bidirectional one-to-one association on a foreign key is common:
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <many-to-one name="address" column="addressId" unique="true" not-null="true"/> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> <one-to-one name="person" property-ref="address"/> </class> create table Person ( personId bigint not null primary key, addressId bigint not null unique ) create table Address ( addressId bigint not null primary key )
<class name="Address"> <id name="id" column="personId"> <generator class="foreign"> <param name="property">person</param> </generator> </id> <one-to-one name="person" constrained="true"/> </class> create table Person ( personId bigint not null primary key ) create table Address ( personId bigint not null primary key )
8.5.3. Many-to-many
Here is an example of a bidirectional many-to-many association.
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses" table="PersonAddress"> <key column="personId"/> <many-to-many column="addressId" class="Address"/>
</set> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> <set name="people" inverse="true" table="PersonAddress"> <key column="addressId"/> <many-to-many column="personId" class="Person"/> </set> </class> create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId) ) create table Address ( addressId bigint not null primary key )
You can then map an association to the current instance, the one with null effectiveEndDate, by using:
<many-to-one name="currentAccountInfo" property-ref="currentAccountKey" class="AccountInfo"> <column name="accountNumber"/> <formula>'1'</formula> </many-to-one>
In a more complex example, imagine that the association between Employee and Organization is maintained in an Employment table full of historical employment data. An association to the employee's most recent employer, the one with the most recent startDate, could be mapped in the following way:
<join> <key column="employeeId"/> <subselect> select employeeId, orgId from Employments group by orgId having startDate = max(startDate) </subselect> <many-to-one name="mostRecentEmployer" class="Organization" column="orgId"/> </join>
::Relationship:: person(many) -> address(one) ex) person A and person B live in address AA ::DB Schema:: person (personId) addres (addressId) personAddress (personId, addressId) ::Java Operation:: person.getAddress(); ::Annotation::
@Entity @Table(name = "PERSON") public class Person { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "personId") private int id; @ManyToOne(optional=true) @JoinTable(name="PersonAddress",
@Entity @Table(name = "ADDRESS") public class Address { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "addressId") private int id; }
@Column(name = "personId") private int id; @ManyToMany @JoinTable(name = "PersonAddress", joinColumns = { @JoinColumn(name="personId", unique = true) }, inverseJoinColumns = { @JoinColumn(name="addressId") } ) private Set<Address> addresses;
@Entity @Table(name = "ADDRESS") public class Address { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "addressId") private int id; }