一对一有两种关联方式:主键关联
主键既是主键也是外键
一对一主键关联:
表中:
一对一 关联映射,我们在数据库表中设计的时候,应该是一个表中关联另一张表中的id 外键 不会各自拥有。这样符合数据库设计的规范
因此我们将表分为主表和从表 比如 Person和 IDCard的例子 人和身份证 是一对一关系
因为人比身份证重要,身份证是附属于人的,所以把人看做主对象
我们将 IDCard中 添加一个Person的主键 也就是说在IDCard中添加外键 :
外键在从表中,意思就是说:外键建立在IdCard中 既是IdCard的主键 而且是外键,关联Person中的主键
对象模型:
public class Person {
private int id;
private String name;
private IdCard idCard;
private int id;
private String name;
private IdCard idCard;
public class IdCard {
private int id;
private Date usefulLife;
private Person person;
private int id;
private Date usefulLife;
private Person person;
映射文件:
person中
<hibernate-mapping package="com.coffee.one2one">
<class name="Person">
<id name="id">
<generator class="native">
</generator>
</id>
<property name="name"></property>
< one-to-one name="idCard"></one-to-one>
</class>
</hibernate-mapping>
<class name="Person">
<id name="id">
<generator class="native">
</generator>
</id>
<property name="name"></property>
< one-to-one name="idCard"></one-to-one>
</class>
</hibernate-mapping>
表明1对1是关联那个类就可以了,因为外键在从表中
IdCard从对象映射文件:
<hibernate-mapping package="com.coffee.one2one">
<class name="IdCard" table="id_card">
<id name="id">
<generator class="foreign">
<!-- 指定由什么参数生成主键 由person里getId方法拿到ID -->
<param name="property">person</param>
</generator>
</id>
<property name="usefulLife" column="useful_life"></property>
<!-- constrained=true 约束为真 引用主对象的id -->
<one-to-one name="person" constrained="true"></one-to-one>
</class>
</hibernate-mapping>
<class name="IdCard" table="id_card">
<id name="id">
<generator class="foreign">
<!-- 指定由什么参数生成主键 由person里getId方法拿到ID -->
<param name="property">person</param>
</generator>
</id>
<property name="usefulLife" column="useful_life"></property>
<!-- constrained=true 约束为真 引用主对象的id -->
<one-to-one name="person" constrained="true"></one-to-one>
</class>
</hibernate-mapping>
不仅要指定关联的对象 而且要指定外键 :
<generator class="foreign">
<param name="property">person</param>
不仅如此:
还要添加外键约束:constrained="true"
这里要提到一种主键生成器:
foreign:
用这种生成器就是hibernate在保存idcard的时候 通过关联另一种表的属性所获得的(person id);
保存 检索分析:
保存:
从对象中没有主对象是不能保存的
主对象中没有从对象 是可以保存的
检索:
按照我自己的思路:当我们再查询主对象的时候,并得到从对象的时候,应该是先查询主对象,然后再产生一条select语句查询从对象,但是:
查询主对象的时候 是用的左链接查询( left outer join ), 只有一条select语句
查询从对象的时候,用了两次查询,更为复杂
先查询从对象IdCard 然后再查询主对象Person 再用 left outer join + 其他条件
一对一外键关联:
表结构:
idCard中不再将主键作为外键
而是单独设置一个外键关联person中的主键
从表结构上 可以看出
和多对一有些类似,但是区别在于 这里不能多个IdCard对于同一个Person
对象结构:不变
所以映射文件上稍微做点儿改变:
IdCard:
IdCard:
<hibernate-mapping package="com.coffee.one2oneFK">
<class name="IdCard" table="id_card">
<id name="id">
<generator class="native"></generator> //生成器改变:不需要外键生成器
</id>
<class name="IdCard" table="id_card">
<id name="id">
<generator class="native"></generator> //生成器改变:不需要外键生成器
</id>
<property name="usefulLife" column="useful_life"></property>
<!-- 和对一设置一样,不过叫上多的一方唯一的属性 并指定属性名为person_id规范-->
<many-to-one name="person" unique="true" column="person_id"></many-to-one>
</class>
</hibernate-mapping>
<!-- 和对一设置一样,不过叫上多的一方唯一的属性 并指定属性名为person_id规范-->
<many-to-one name="person" unique="true" column="person_id"></many-to-one>
</class>
</hibernate-mapping>
person:
<hibernate-mapping package="com.coffee.one2oneFK">
<class name="Person">
<id name="id">
<generator class="native">
</generator>
</id>
<property name="name"></property>
<!-- property-ref:设置关联类的属性名,此属性和本类的主键相对应 默认值为关联类的主键 -->
<!-- 如果有此属性 则Person没有关联上IdCard 就为单向关联 不能通过person查到ID了 -->
<one-to-one name="idCard" property-ref="person"></one-to-one>
</class>
</hibernate-mapping>
<hibernate-mapping package="com.coffee.one2oneFK">
<class name="Person">
<id name="id">
<generator class="native">
</generator>
</id>
<property name="name"></property>
<!-- property-ref:设置关联类的属性名,此属性和本类的主键相对应 默认值为关联类的主键 -->
<!-- 如果有此属性 则Person没有关联上IdCard 就为单向关联 不能通过person查到ID了 -->
<one-to-one name="idCard" property-ref="person"></one-to-one>
</class>
</hibernate-mapping>
这里和一对一主键关联不同的是,从对象的角度在思考,需要指定 idcard关联的属性 person,没有去指定column是什么字段 一对一主键关联没有指定 见上映射文件
一对一有两种关联方式:主键关联
主键既是主键也是外键
一对一主键关联:
表中:
一对一 关联映射,我们在数据库表中设计的时候,应该是一个表中关联另一张表中的id 外键 不会各自拥有。这样符合数据库设计的规范
因此我们将表分为主表和从表 比如 Person和 IDCard的例子 人和身份证 是一对一关系
因为人比身份证重要,身份证是附属于人的,所以把人看做主对象
我们将 IDCard中 添加一个Person的主键 也就是说在IDCard中添加外键 :
外键在从表中,意思就是说:外键建立在IdCard中 既是IdCard的主键 而且是外键,关联Person中的主键
对象模型:
public class Person {
private int id;
private String name;
private IdCard idCard;
private int id;
private String name;
private IdCard idCard;
public class IdCard {
private int id;
private Date usefulLife;
private Person person;
private int id;
private Date usefulLife;
private Person person;
映射文件:
person中
<hibernate-mapping package="com.coffee.one2one">
<class name="Person">
<id name="id">
<generator class="native">
</generator>
</id>
<property name="name"></property>
< one-to-one name="idCard"></one-to-one>
</class>
</hibernate-mapping>
<class name="Person">
<id name="id">
<generator class="native">
</generator>
</id>
<property name="name"></property>
< one-to-one name="idCard"></one-to-one>
</class>
</hibernate-mapping>
表明1对1是关联那个类就可以了,因为外键在从表中
IdCard从对象映射文件:
<hibernate-mapping package="com.coffee.one2one">
<class name="IdCard" table="id_card">
<id name="id">
<generator class="foreign">
<!-- 指定由什么参数生成主键 由person里getId方法拿到ID -->
<param name="property">person</param>
</generator>
</id>
<property name="usefulLife" column="useful_life"></property>
<!-- constrained=true 约束为真 引用主对象的id -->
<one-to-one name="person" constrained="true"></one-to-one>
</class>
</hibernate-mapping>
<class name="IdCard" table="id_card">
<id name="id">
<generator class="foreign">
<!-- 指定由什么参数生成主键 由person里getId方法拿到ID -->
<param name="property">person</param>
</generator>
</id>
<property name="usefulLife" column="useful_life"></property>
<!-- constrained=true 约束为真 引用主对象的id -->
<one-to-one name="person" constrained="true"></one-to-one>
</class>
</hibernate-mapping>
不仅要指定关联的对象 而且要指定外键 :
<generator class="foreign">
<param name="property">person</param>
不仅如此:
还要添加外键约束:constrained="true"
这里要提到一种主键生成器:
foreign:
用这种生成器就是hibernate在保存idcard的时候 通过关联另一种表的属性所获得的(person id);
保存 检索分析:
保存:
从对象中没有主对象是不能保存的
主对象中没有从对象 是可以保存的
检索:
按照我自己的思路:当我们再查询主对象的时候,并得到从对象的时候,应该是先查询主对象,然后再产生一条select语句查询从对象,但是:
查询主对象的时候 是用的左链接查询( left outer join ), 只有一条select语句
查询从对象的时候,用了两次查询,更为复杂
先查询从对象IdCard 然后再查询主对象Person 再用 left outer join + 其他条件
一对一外键关联:
表结构:
idCard中不再将主键作为外键
而是单独设置一个外键关联person中的主键
从表结构上 可以看出
和多对一有些类似,但是区别在于 这里不能多个IdCard对于同一个Person
对象结构:不变
所以映射文件上稍微做点儿改变:
IdCard:
IdCard:
<hibernate-mapping package="com.coffee.one2oneFK">
<class name="IdCard" table="id_card">
<id name="id">
<generator class="native"></generator> //生成器改变:不需要外键生成器
</id>
<class name="IdCard" table="id_card">
<id name="id">
<generator class="native"></generator> //生成器改变:不需要外键生成器
</id>
<property name="usefulLife" column="useful_life"></property>
<!-- 和对一设置一样,不过叫上多的一方唯一的属性 并指定属性名为person_id规范-->
<many-to-one name="person" unique="true" column="person_id"></many-to-one>
</class>
</hibernate-mapping>
<!-- 和对一设置一样,不过叫上多的一方唯一的属性 并指定属性名为person_id规范-->
<many-to-one name="person" unique="true" column="person_id"></many-to-one>
</class>
</hibernate-mapping>
person:
<hibernate-mapping package="com.coffee.one2oneFK">
<class name="Person">
<id name="id">
<generator class="native">
</generator>
</id>
<property name="name"></property>
<!-- property-ref:设置关联类的属性名,此属性和本类的主键相对应 默认值为关联类的主键 -->
<!-- 如果有此属性 则Person没有关联上IdCard 就为单向关联 不能通过person查到ID了 -->
<one-to-one name="idCard" property-ref="person"></one-to-one>
</class>
</hibernate-mapping>
<hibernate-mapping package="com.coffee.one2oneFK">
<class name="Person">
<id name="id">
<generator class="native">
</generator>
</id>
<property name="name"></property>
<!-- property-ref:设置关联类的属性名,此属性和本类的主键相对应 默认值为关联类的主键 -->
<!-- 如果有此属性 则Person没有关联上IdCard 就为单向关联 不能通过person查到ID了 -->
<one-to-one name="idCard" property-ref="person"></one-to-one>
</class>
</hibernate-mapping>
这里和一对一主键关联不同的是,从对象的角度在思考,需要指定 idcard关联的属性 person,没有去指定column是什么字段 一对一主键关联没有指定 见上映射文件