双向一对一关联关系:
域模型:
例如,部门只有一个部门经理,一个经理也只能管理一个部门。即,Department 中有一个Manager的引用,Manager 中又有一个Department 的引用。
关系数据模型:
按照主键映射: 这种方式跟 多对一关联关系非常相似,比如department 表有一个外键 MANAGER_ID 指向manager 表的ID, 此时Department 和 Manager 对应的这两张表是多对一的关联关系,为了实现一对一的关联关系,只要给 外键 MANAGER_ID 加上一个唯一约束,则可以实现一对一关联关系。
需要注意的问题:
①、保存:建议先保存没有外键列的那一端的对象。
②、查询:默认情况下使用懒加载异常。
③、没有外键的一端需要使用 one-to-one 元素,该元素使用property-ref 属性指定使用 被关联实体主键以外的字段作为关联字段。
④、在查询没有外键关联的一端对象的时候,使用左外连接一并查询出其关联的对象,并进行初始化。
也就是说:把懒加载属性设为true 的时候,查询 Manager 会一并把Department 查询出来,但是查询Department 并不会把Manager对象查询出来。
按照外键映射:
拥有外键的一端生成主键的方式要注意,不是使用 native ,而是使用 foreign
示例:
实体类按照主键映射的一样,区别在于映射文件。这里将映射文件代码贴出来。
Department类的映射文件
<class name="com.zcd.hibernate.oneToOnePrimary.Department" table="DEPARTMENT"> <id name="id" type="java.lang.Integer"> <column name="ID" /> <generator class="foreign" > <!-- 生成主键的方式 --> <param name="property">manager</param> <!-- 还要指定根据。。。 --> </generator> </id> <property name="name" type="java.lang.String"> <column name="NAME" /> </property> <one-to-one name="manager" class="com.zcd.hibernate.oneToOnePrimary.Manager" constrained="true"> </one-to-one> </class>
Manager的映射文件
<class name="com.zcd.hibernate.oneToOnePrimary.Manager" table="MANAGER"> <id name="id" type="java.lang.Integer"> <column name="ID" /> <generator class="native" /> </id> <property name="name" type="java.lang.String"> <column name="NAME" /> </property> <one-to-one name="department" class="com.zcd.hibernate.oneToOnePrimary.Department"></one-to-one> </class>
不管先插入哪一个对象,都会先发送被拿主键来作为他人外键的那个对象的插入SQL语句,比如这里不管先插入Department 还是Manager,都会先发送插入Manager 的SQL语句。
有一个疑问:下面的代码为什么会保存两次 Manager 对象呢?
@Test public void testDepartmentAndManager() { Department department = new Department(); department.setName("研发部"); Manager manager = new Manager(); manager.setName("BB"); department.setManager(manager); manager.setDepartment(department); oneToOnePrimaryService.saveDepartment(department); oneToOnePrimaryService.saveManager(manager); }
Hibernate 一对一关联关系,使用外键映射和使用主键映射的区别:
目前发现的一点区别如下,以后发现了在进行添加。
外键映射 | 主键映射 | |
生成主键方式 |
使用native <generator class="native" /> |
使用foreign还有 <generator class="foreign" > <param name="property">company</param> </generator> |
使用many-to-one 加上unique属性,另一端不需要修改,按自动生成的使用 | 使用one-to-one,加上contrained="true"属性,另一端不需要修改,按自动生成的使用 |