概述
前言
在前面的Hibernate学习中已经介绍了多对一、一对多、多对多的关系,本文主要介绍一对一关系。比如:一个用户有且仅有一个身份证,一个身份证也只能对应一个用户。而在学习Hibernate框架主要是学习映射关系如何配置。那么一对一关系映射主要有两种配置方式。一种是基于外键的映射关系。一种是基于主键的映射关系。本文将分别从具体案例出发,介绍两种不同的一对一映射配置。
案例说明:
需求
一个用户对应一个身份证信息。即用户与身份证信息。
设计数据库:
从数据库的设计发现,上面一种是基于外键的映射关系。主要是将用户的主键user_id作为身份证表的外键字段关联起来,作为单独的外键列,保存在数据库中。不难发现,其实这种
方式并不陌生,类似于一对多的映射关系,多方维护着一方的主键作为外键。所以基于外键映射方式的一对一关系也是特殊的一对多,只是有一个特殊条件,外键必须唯一,限制了唯一性。
下面一种呢,是基于主键的一对一关系映射方式。将用户表的主键user_id作为身份证表的主键,即主键必唯一。但是关联关系怎么保存呢,只能通过外键的方式了,也就是说user_id即是主键也是外键。
案例代码
我们从具体的代码来介绍:
先是第一种基于主键的映射:
User.java
// 用户
public class User {
private int userId;
private String userName;
// 用户与身份证信息, 一对一关系
private IdCard idCard;
public IdCard getIdCard() {
return idCard;
}
public void setIdCard(IdCard idCard) {
this.idCard = idCard;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
IdCard.java
// 身份证
public class IdCard {
// 身份证号(主键)
private String cardNum;// 对象唯一表示(Object Identified, OID)
private String place; // 身份证地址
// 身份证与用户,一对一的关系
private User user;
public String getCardNum() {
return cardNum;
}
public void setCardNum(String cardNum) {
this.cardNum = cardNum;
}
public String getPlace() {
return place;
}
public void setPlace(String place) {
this.place = place;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
这里的user映射文件相对简单,只需要说明userid自增长,有一个userName属性字段,然后《one-to-one》一对一映射关系,指定关系的类型和user类中对应的成员属性名称idCard,其实就是告诉hibernate如何去找关联一方的类和对应的配置文件。
IdCard.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.nwpu.geeker.one2one">
<class name="IdCard" table="t_IdCard">
<id name="cardNum">
<generator class="assigned"></generator>
</id>
<property name="place" length="20"></property>
<!--
一对一映射,有外键方
unique="true" 给外键字段添加唯一约束
-->
<many-to-one name="user" unique="true" column="user_id" class="User" cascade="save-update"></many-to-one>
</class>
</hibernate-mapping>
注意:因为t_IdCard表中主键为身份证号,必须设置成手动方式,因此在配置主键生成策略时使用“assigned”。因为基于外键的一对一关系也是特殊的一对多关系,在多的一方设置《many-to-one》,记住一点,把对象映射到数据库生成外键字段只能用《many-to-one》配置。
还要注意在配置中给外键字段添加唯一约束即,unique=”true”。
测试保存:App.java
public class App {
private static SessionFactory sf;
static {
sf = new Configuration()
.configure()
.addClass(IdCard.class)
.addClass(User.class) // 测试时候使用
.buildSessionFactory();
}
@Test
public void getSave() {
Session session = sf.openSession();
session.beginTransaction();
// 用户
User user = new User();
user.setUserName("Jack");
// 身份证
IdCard idCard = new IdCard();
idCard.setCardNum("121202XXX");
idCard.setPlace("北京XXX");
// 关系
idCard.setUser(user);
// ----保存----
session.save(idCard);
session.getTransaction().commit();
session.close();
}
}
因为设置了级联保存,直接保存idCard对象,即可。数据库保存成功!
另外一种基于主键的一对一映射
和上面的方式javaBean和配置有所不同:
User.java
// 用户
public class User {
private int userId;
private String userName;
// 用户与身份证信息, 一对一关系
private IdCard idCard;
public IdCard getIdCard() {
return idCard;
}
public void setIdCard(IdCard idCard) {
this.idCard = idCard;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
IdCard .java
// 身份证
public class IdCard {
private int user_id;
// 身份证号
private String cardNum;
private String place; // 身份证地址
// 身份证与用户,一对一的关系
private User user;
public int getUser_id() {
return user_id;
}
public void setUser_id(int userId) {
user_id = userId;
}
public String getCardNum() {
return cardNum;
}
public void setCardNum(String cardNum) {
this.cardNum = cardNum;
}
public String getPlace() {
return place;
}
public void setPlace(String place) {
this.place = place;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
注意:因为是基于主键的,因此IdCard 表中必须有主键字段user_id。
配置文件:User.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.nwpu.geeker.one2one2">
<class name="User" table="t_user">
<id name="userId">
<generator class="native"></generator>
</id>
<property name="userName" length="20"></property>
<!--
一对一映射: 没有外键方
-->
<one-to-one name="idCard" class="IdCard"></one-to-one>
</class>
</hibernate-mapping>
和上面user配置文件相同。
IdCard.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.nwpu.geeker.one2one2">
<class name="IdCard" table="t_IdCard">
<id name="user_id">
<!--
id 节点指定的是主键映射, 即user_id是主键
主键生成方式: foreign 即把别的表的主键作为当前表的主键;
property (关键字不能修改)指定引用的对象 对象的全名 cn..User、 对象映射 cn.User.hbm.xml、 table(id)
-->
<generator class="foreign">
<param name="property">user</param>
</generator>
</id>
<property name="cardNum" length="20"></property>
<property name="place" length="20"></property>
<!--
一对一映射,有外键方
(基于主键的映射)
constrained="true" 指定在主键上添加外键约束
-->
<one-to-one name="user" class="User" constrained="true" cascade="save-update"></one-to-one>
</class>
</hibernate-mapping>
注意:IdCard表的主键生成策略为引用别的表的主键。因此配置class=”foreign”。还要告诉Hibernate引用的是哪一张表的映射,所以<param name="property">user</param>
,其中name=”property”,为必须的不能修改,而user指定为在IdCard.java中定义的成员变量的名字。
还有,基于主键的一对一关系,也是必须有外键关联的。因此还要在《one-to-one》配置constrained=”true”,即指定在主键上添加外键约束。
这里的测试代码,与上面App.java一致,也能保持数据量成功!保持的数据与数据库设计第一幅图一致。
最后
以上就是缓慢哈密瓜为你收集整理的Hibernate之两种一对一关系映射方式的全部内容,希望文章能够帮你解决Hibernate之两种一对一关系映射方式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复