一. 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()方法不通过,会报空指向异常的。
建议,两个约束都写。
谢谢!!!