使用hibernate映射一对一双向关联关系共有三种情况:
1、基于外键;
2、基于主键;
3、基于连接表。
基于外键的映射关系在官方文档上是这样描述的:
A bidirectional one-to-one association on a foreign key is quite common.
sql语句
基于主键映射关系在官方文档描述:
A bidirectional one-to-one association on a primary key uses the special id generator.
sql语句
基于关联表的关联映射描述:
A bidirectional one-to-one association on a join table is extremely unusual, but possible.
sql语句
刚开始我想都是一对一的关系全部用one-to-one描述不就可以了么,仔细看了一下官方文档,三种情况还是有区别的。基于外键的关联映射必须在表里面多一个外键,而one-to-one的属性里找不到column属性,想了想就明白了,应该是gavin在设计时考虑的many-to-one与one-to-one之间的区别才这样设计的。
先看第一种基于外键的映射关系:
1. 如果是基于外键一方的数据表里面必须出现外键引用关联方数据表里的记录对象,因此用many-to-one放在有外键的一方的映射文件中表述关联关系,并设column="外键",unique="true"。
2. 在另一方就用one-to-one表达映射关系,里面有一个属性property-ref,官方文档的描述,property-ref: (optional) The name of a property of the associated class that is joined to the primary key of this class. If not specified, the primary key of the associated class is used.大致意思是说该属性的值是对方类对该类的引用标识,如果不写默认就是对方的主键引用了该方,也就成了第二种情况,基于主键的引用。所以表达此种情况,必须要有property="彼方对此方的引用"。
第二种基于主键的情况:
1. 此种情况双方都没有外键,并且一方的主键是引用了对方的主键。因此双方都用one-to-one就可以表达清楚此种情况,假设a方的主键是基于b方的主键生成的,先配置b方,<one-to-one name="对a方的引用标识"/>,再配置a方,a方有两个地方需要注意,一是主键的id标识的生成策略变为,
<id name="id" column="personId">
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
二是one-to-one里面属性的变化,
<one-to-one name="person" constrained="true"/>
多了一个constrained属性,官方文档上这么表述,
constrained (optional) specifies that a foreign key constraint on the
primary key of the mapped table references the table of the associated
class. This option affects the order in which save() and delete() are
cascaded, and determines whether the association may be proxied (it is
also used by the schema export tool).
大致意思是说如果指定constrained="true",此方的主键是基于彼方的。
第三种基于关联表的情况:
这种情况比较容易理解,就不再详述。
1、基于外键;
2、基于主键;
3、基于连接表。
基于外键的映射关系在官方文档上是这样描述的:
A bidirectional one-to-one association on a foreign key is quite 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>
sql语句
create table Person ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
基于主键映射关系在官方文档描述:
A bidirectional one-to-one association on a primary key uses the special id generator.
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<one-to-one name="address"/>
</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>
sql语句
create table Person ( personId bigint not null primary key )
create table Address ( personId bigint not null primary key )
基于关联表的关联映射描述:
A bidirectional one-to-one association on a join table is extremely unusual, but possible.
<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>
<join table="PersonAddress"
optional="true"
inverse="true">
<key column="addressId"
unique="true"/>
<many-to-one name="person"
column="personId"
not-null="true"
unique="true"/>
</join>
</class>
sql语句
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 )
刚开始我想都是一对一的关系全部用one-to-one描述不就可以了么,仔细看了一下官方文档,三种情况还是有区别的。基于外键的关联映射必须在表里面多一个外键,而one-to-one的属性里找不到column属性,想了想就明白了,应该是gavin在设计时考虑的many-to-one与one-to-one之间的区别才这样设计的。
先看第一种基于外键的映射关系:
1. 如果是基于外键一方的数据表里面必须出现外键引用关联方数据表里的记录对象,因此用many-to-one放在有外键的一方的映射文件中表述关联关系,并设column="外键",unique="true"。
2. 在另一方就用one-to-one表达映射关系,里面有一个属性property-ref,官方文档的描述,property-ref: (optional) The name of a property of the associated class that is joined to the primary key of this class. If not specified, the primary key of the associated class is used.大致意思是说该属性的值是对方类对该类的引用标识,如果不写默认就是对方的主键引用了该方,也就成了第二种情况,基于主键的引用。所以表达此种情况,必须要有property="彼方对此方的引用"。
第二种基于主键的情况:
1. 此种情况双方都没有外键,并且一方的主键是引用了对方的主键。因此双方都用one-to-one就可以表达清楚此种情况,假设a方的主键是基于b方的主键生成的,先配置b方,<one-to-one name="对a方的引用标识"/>,再配置a方,a方有两个地方需要注意,一是主键的id标识的生成策略变为,
<id name="id" column="personId">
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
二是one-to-one里面属性的变化,
<one-to-one name="person" constrained="true"/>
多了一个constrained属性,官方文档上这么表述,
constrained (optional) specifies that a foreign key constraint on the
primary key of the mapped table references the table of the associated
class. This option affects the order in which save() and delete() are
cascaded, and determines whether the association may be proxied (it is
also used by the schema export tool).
大致意思是说如果指定constrained="true",此方的主键是基于彼方的。
第三种基于关联表的情况:
这种情况比较容易理解,就不再详述。