Hibernate的一对一映射(八)

简介: 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();
  }


20181020195217475.png


20181021132619898.png


添加约束:


20181021132646964.png


后面就是两条插入语句,insert 语句.

生成的数据表中均有两个数据:


2018102113275640.png


20181021132812695.png


两者的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());
  }


先执行一条外键修改操作:


20181021133034133.png


再执行查询操作:


20181021133051734.png


二.十 由身份证查询用户


/**
   * 由身份证查询相应的相对应的用户
   */
  @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());
  }


这里,先修改外键,然后查询


20181021133343448.png


关联查询,查询出用户的信息


20181021133406312.png


这种方式,每次都要修改外键,造成效率低。而且,如果一旦修改id的话,如将IdCard表中的id进行修改的话,是没有任何现象可以查的。因为,生成的表,实际上是没有任何外键关联的。


20181021133607658.png


2018102113362722.png


这个外键,只是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()时,先进行两条创建表的操作,然后是,先删除唯一约束,然后添加唯一约束,最后添加外键。


20181021135635884.png


最后是两条插入的sql语句.


其中IdCard中没有约束,而user表中是存在着约束的:


20181021135835255.png


并且,会在user表中添加一个列,cardId的列


20181021135913369.png


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()方法不通过,会报空指向异常的。


建议,两个约束都写。


谢谢!!!

相关文章
|
2月前
|
Java 数据库连接 API
解锁高效开发秘籍:深入探究 Hibernate 如何优雅处理一对多与多对多关系,让数据映射再无烦恼!
【9月更文挑战第3天】Hibernate 是 Java 领域中最流行的 ORM 框架之一,广泛用于处理实体对象与数据库表之间的映射。尤其在处理复杂关系如一对多和多对多时,Hibernate 提供了丰富的 API 和配置选项。本文通过具体代码示例,展示如何使用 `@OneToMany`、`@JoinColumn`、`@ManyToMany` 和 `@JoinTable` 等注解优雅地实现这些关系,帮助开发者保持代码简洁的同时确保数据一致性。
50 4
|
3月前
|
Java 数据库连接 数据库
AI 时代风起云涌,Hibernate 实体映射引领数据库高效之路,最佳实践与陷阱全解析!
【8月更文挑战第31天】Hibernate 是一款强大的 Java 持久化框架,可将 Java 对象映射到关系数据库表中。本文通过代码示例详细介绍了 Hibernate 实体映射的最佳实践,包括合理使用关联映射(如 `@OneToMany` 和 `@ManyToOne`)以及正确处理继承关系(如单表继承)。此外,还探讨了常见陷阱,例如循环依赖可能导致的无限递归问题,并提供了使用 `@JsonIgnore` 等注解来避免此类问题的方法。通过遵循这些最佳实践,可以显著提升开发效率和数据库操作性能。
84 0
|
3月前
|
数据库 开发者 Java
Hibernate映射注解的魔力:实体类配置的革命,让你的代码量瞬间蒸发!
【8月更文挑战第31天】Hibernate 是一款出色的对象关系映射框架,简化了 Java 应用与数据库的交互。其映射注解让实体类配置变得直观简洁。本文深入剖析核心概念与使用技巧,通过示例展示如何简化配置。
44 0
|
SQL XML 存储
Hibernate框架【五】——基本映射——多对多映射
Hibernate框架【五】——基本映射——多对多映射
189 0
|
6月前
|
缓存 Java 数据库连接
Hibernate或MyBatis:ORM映射、缓存机制等知识讲解梳理
Hibernate或MyBatis:ORM映射、缓存机制等知识讲解梳理
126 0
|
6月前
|
Java 数据库连接 数据库
Hibernate5中实体映射命名策略
Hibernate5中实体映射命名策略
134 0
|
6月前
|
SQL 存储 Java
Hibernate - 继承关联关系映射
Hibernate - 继承关联关系映射
71 0
|
6月前
|
SQL Java 数据库连接
Hibernate -双向一对一关联关系映射
Hibernate -双向一对一关联关系映射
55 0
|
6月前
|
SQL Java 关系型数据库
Hibernate - Java 类型, Hibernate 映射类型及 SQL 类型之间的对应关系
Hibernate - Java 类型, Hibernate 映射类型及 SQL 类型之间的对应关系
63 0
|
SQL XML Java
Hibernate框架【四】——基本映射——多对一和一对多映射
Hibernate框架【四】——基本映射——多对一和一对多映射
172 0