Hibernate的一对一映射

版权声明:转载请注明出处(两个蝴蝶飞) https://blog.csdn.net/yjltx1234csdn/article/details/83241189

感谢Jie’ blog http://ilog.vip/ ,谢谢他让我有了继续写下去的信念。愿一起坚持,在路上…
上一章简单介绍了Hibernate的一级缓存和二级缓存(七),如果没有看过,请观看上一章

一. Hibernate的一对一映射的使用范围

在Hibernate开发中,一对一的映射虽然使用的少,不如一对多和多对多运用的多,但还是有使用的。 如,如果用户的个人资料太多,可以将用户的重要资料放在一起,私人资料放在一起,即将个人资料进行拆分,而重要资料与私人资料是要进行一对一的关联的。如,用户与个人的住址方式也是一对一的,用户与银行卡也是一对一的,(有一个用户表,银行卡表,这两个表之间也是一对一的),还有最常用举例的,用户与身份证号也是一对一的。
其中一对一映射,有两种方式,一种是共用同一个Id,另外一种是外键映射。

二. 共用Id映射详细步骤

这是简单的使用,用户与身份证号进行相应的举例。按照第一章的方式
的创建相应的工程,搭建Hibernate开发的环境。为User类和IdCard类

二.一 User类和User.hbm.xml的创建

User.java

package com.yjl.pojo;
/**
 @author: yuejl
 @date: 2018年10月21日 下午12:40:04
 @Description 类的相关描述
*/
public class User {
	/**
	 * @param id 标识符Id
	 * @param userName 用户名
	 * @param password 密码
	 * @param description 描述
	 */
	private Integer id;
	private String userName;
	private String password;
	private String description;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
}

User.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入相应的约束 -->
<!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.yjl.pojo" >
	<!-- 具体的实体类 -->
	<class name="User" table="user" lazy="true">
		<!-- 主键 -->
		<id name="id" column="id">
			<generator class="native"></generator>	
		</id>
		<!-- 其余属性 -->
		<property name="userName"></property>
		<property name="password"></property>
		<property name="description"></property>
	</class>
</hibernate-mapping>

二. IdCard类和IdCard.hbm.xml的创建

IdCard.java

package com.yjl.pojo;
/**
 @author: yuejl
 @date: 2018年10月21日 下午12:41:47
 @Description 类的相关描述
*/
public class IdCard {
	/**
	 * @param uid 身份证唯一标识符
	 * @param idNum 身份证标识符
	 */
	private Integer uid;
	private String idNum;
	public Integer getUid() {
		return uid;
	}
	public void setUid(Integer uid) {
		this.uid = uid;
	}
	public String getIdNum() {
		return idNum;
	}
	public void setIdNum(String idNum) {
		this.idNum = idNum;
	}
}

IdCard.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入相应的约束 -->
<!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.yjl.pojo" >
	<!-- 具体的实体类 -->
	<class name="IdCard" table="idCard">
		<!-- 主键 -->
		<id name="uid" column="uid">
			<!--这里应该是外键映射-->
			<generator class="native"></generator>	
		</id>
		<!-- 其余属性 -->
		<property name="idNum"></property>
	</class>
</hibernate-mapping>

二.三 在类中添加属性映射

在User.java类中,需要有一个属性来包括IdCard类的对象,即在User.java中添加一个IdCard对象的引用。是一对一的引用。
User.java中添加:

//添加IdCard的一对一的引用
	private IdCard card;
	public IdCard getCard() {
		return card;
	}
	public void setCard(IdCard card) {
		this.card = card;
	}

二.四 在User.hbm.xml中添加相对应的属性映射

		<!-- 添加与IdCard的一对一映射 -->
		<one-to-one name="card" class="com.yjl.pojo.IdCard"></one-to-one>

二.五 在IdCard类中添加User对象引用

//添加对User对象的引用
	private User user;
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}

二.六 在IdCard.hbm.xml中修改主键生成策略为外键,添加一对一映射

<hibernate-mapping package="com.yjl.pojo" >
	<!-- 具体的实体类 -->
	<class name="IdCard" table="idCard">
		<!-- 主键 -->
		<id name="uid" column="uid">
			<!--添加外键-->
			<generator class="foreign">
				<param name="property">user</param>
			</generator>	
		</id>
		<!-- 其余属性 -->
		<property name="idNum"></property>
		<!-- 添加User对象的一对一的引用   修改constrained 约束为true-->
		<one-to-one name="user" class="com.yjl.pojo.User" constrained="true"></one-to-one>
	</class>
</hibernate-mapping>

二.七 在hibernate.cfg.xml中添加这两个约束文件

<!-- 引入相应的约束文件  ctrl点击时可以正确进入-->
	 	<mapping resource="com/yjl/pojo/User.hbm.xml"/>
	 	<mapping resource="com/yjl/pojo/IdCard.hbm.xml"/>

二.八 测试插入

@Test
	public void saveTest(){
		//1  得到Session对象
		Session session=HibernateUtil.getSession();
		//2 打开事务
		Transaction tran=session.beginTransaction();
		//3 实例化User对象
		User user=new User();
		user.setUserName("两个蝴蝶飞");
		user.setDescription("一个简单的程序员");
		//4 实际化IdCard对象
		IdCard idCard=new IdCard();
		idCard.setIdNum("411421**********");
		//5 设置对应关系
		user.setCard(idCard);
		idCard.setUser(user);
		//6 保存对象
		session.save(idCard);
		session.save(user);
		//7 提交事务
		tran.commit();
		//8 关闭session
		session.close();
	}

在这里插入图片描述
在这里插入图片描述
添加约束:
在这里插入图片描述
后面就是两条插入语句,insert 语句.
生成的数据表中均有两个数据:
在这里插入图片描述
在这里插入图片描述
两者的Id是相同的。

二.九 由用户查询身份证测试

/**
	 * 由用户查询相应的身份证
	 */
	@Test
	public void selectTest1(){
		//1  得到Session对象
		Session session=HibernateUtil.getSession();
		//2 得到User对象
		User user=session.get(User.class,1);
		System.out.println("姓名为:"+user.getUserName());
		//3 得到关联的对象
		IdCard idCard=user.getCard();
		System.out.println("身份证为:"+idCard.getIdNum());
	}

先执行一条外键修改操作:
在这里插入图片描述
再执行查询操作:
在这里插入图片描述

二.十 由身份证查询用户

/**
	 * 由身份证查询相应的相对应的用户
	 */
	@Test
	public void selectTest2(){
		//1  得到Session对象
		Session session=HibernateUtil.getSession();
		//2 得到IdCard对象
		IdCard idCard=session.get(IdCard.class,1);
		System.out.println("身份证为:"+idCard.getIdNum());
		//3 得到关联的用户对象
		User user=idCard.getUser();
		System.out.println("姓名为:"+user.getUserName());
	}

这里,先修改外键,然后查询
在这里插入图片描述
关联查询,查询出用户的信息
在这里插入图片描述
这种方式,每次都要修改外键,造成效率低。而且,如果一旦修改id的话,如将IdCard表中的id进行修改的话,是没有任何现象可以查的。因为,生成的表,实际上是没有任何外键关联的。
在这里插入图片描述
在这里插入图片描述
这个外键,只是Hibernate自己进行相应的约束,并不是体现在真正的数据库表的。所以一般采用真正的外键约束,也就是第二种方式.

三. 外键约束的一对一详细配置

这种方式的一对一配置,实际上就是一对多的配置,只是多的这一方设置unique=“true”,即是唯一的。多的一方唯一,那么这是一对一了。
外键约束的一对一配置,与上面的基本是相同的,只是相应的配置不一样,即User.hbm.xml与IdCard.hbm.xml有一些不同而已。
将生成的user表与idcard表进行删除。
将User.hbm.xml进行修改为

<hibernate-mapping package="com.yjl.pojo" >
	<!-- 具体的实体类 -->
	<class name="User" table="user" lazy="true">
		<!-- 主键 -->
		<id name="id" column="id">
			<generator class="native"></generator>	
		</id>
		<!-- 其余属性 -->
		<property name="userName"></property>
		<property name="password"></property>
		<property name="description"></property>
		<!-- 添加与IdCard的一对一映射  添加unique为true-->
		<many-to-one name="card" class="com.yjl.pojo.IdCard" column="cardId" 
		unique="true"></many-to-one>
	</class>
</hibernate-mapping>

将IdCard.hbm.xml修改为:

<hibernate-mapping package="com.yjl.pojo" >
	<!-- 具体的实体类 -->
	<class name="IdCard" table="idCard">
		<!-- 主键 -->
		<id name="uid" column="cardId">
			<!--添加外键-->
			<generator class="native">
			</generator>	
		</id>
		<!-- 其余属性 -->
		<property name="idNum"></property>
		<!-- 添加User对象的一对一的引用  添加property-ref对应的是User类中的card属性-->
		<one-to-one name="user" class="com.yjl.pojo.User"
		property-ref="card"></one-to-one>
	</class>
</hibernate-mapping>

按照上面所给的saveTest()方法,selectTest1(),selectTest2()进行相应的测试。
saveTest()时,先进行两条创建表的操作,然后是,先删除唯一约束,然后添加唯一约束,最后添加外键。
在这里插入图片描述
最后是两条插入的sql语句.
其中IdCard中没有约束,而user表中是存在着约束的:
在这里插入图片描述
并且,会在user表中添加一个列,cardId的列
在这里插入图片描述

selectTest1()与selectTest2(), 均可以正常的查询出来。
注意点: 有时候,只是在User.hbm.xml中添加相应的约束,而在IdCard.hbm.xml中不添加约束,即在IdCard.hbm.xml中删除这条语句

<!-- 添加User对象的一对一的引用   删除这条语句-->
		<one-to-one name="user" class="com.yjl.pojo.User"
		property-ref="card"></one-to-one>

这个时候,也是可以正确创建一对一的表的,user表中也存在着唯一索引,但是,这个时候,只能通过用户查询银行卡,即selectTest1()方法通过,是不能通过银行卡查找到相应的用户的,即selectTest2()方法不通过,会报空指向异常的。

建议,两个约束都写。
谢谢!!!

猜你喜欢

转载自blog.csdn.net/yjltx1234csdn/article/details/83241189