Hibernate的复合主键映射(十五)

简介: Hibernate的复合主键映射(十五)

一.复合映射


在多对多映射的时候,我们讲到员工与角色表,会创建第三张表。 第三张表中有员工编号,角色编号,创建人和创建日期。 其中,员工编号和角色编号,我们用的是对象,即两个一对多来进行创建第三张表。 实际开发中,员工编号和角色编号是复合主键,两个一对多是无法体现出复合主键的。 这里讲一下,复合主键的使用。


主要有两种方式:

1. 将复合主键所对应的属性与其他属性放置在一起。

2. 将复合主键提取出一个主键类中,实体类中存在这一个主键类的引用。


二.复合映射的操作(第一种方式)


二.一 实体类


package com.yjl.pojo;
import java.io.Serializable;
import java.util.Date;
/**
@Date: 2019年3月24日
@author: 两个蝴蝶飞
@Description:用户与角色关联的表
*/
public class UserRole implements Serializable{
  private static final long serialVersionUID = 1L;
  /**
   * @param userCode 用户编号
   * @param roleCode 角色编号
   * @param operateCode 操作人
   * @param operateDate 操作日期
   */
  private String userCode;
  private String roleCode;
  private String operateCode;
  private Date operateDate;
  public String getUserCode() {
    return userCode;
  }
  public void setUserCode(String userCode) {
    this.userCode = userCode;
  }
  public String getRoleCode() {
    return roleCode;
  }
  public void setRoleCode(String roleCode) {
    this.roleCode = roleCode;
  }
  public String getOperateCode() {
    return operateCode;
  }
  public void setOperateCode(String operateCode) {
    this.operateCode = operateCode;
  }
  public Date getOperateDate() {
    return operateDate;
  }
  public void setOperateDate(Date operateDate) {
    this.operateDate = operateDate;
  }
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((roleCode == null) ? 0 : roleCode.hashCode());
    result = prime * result + ((userCode == null) ? 0 : userCode.hashCode());
    return result;
  }
  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    UserRole other = (UserRole) obj;
    if (roleCode == null) {
      if (other.roleCode != null)
        return false;
    } else if (!roleCode.equals(other.roleCode))
      return false;
    if (userCode == null) {
      if (other.userCode != null)
        return false;
    } else if (!userCode.equals(other.userCode))
      return false;
    return true;
  }
  @Override
  public String toString() {
    return "UserRole [userCode=" + userCode + ", roleCode=" + roleCode + ", operateCode=" + operateCode
        + ", operateDate=" + operateDate + "]";
  }
}


其中,这个简单的实体类相对较POJO 有以下几个扩充:


  1. 实现Serializable 接口。
  2. 重写hashCode 和equals 方法。 引用的属性是复合主键的属性。


原因,可以参考 音①晓 前辈的:


20190324125927613.png


二.二 配置文件


<?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>
  <class name="com.yjl.pojo.UserRole" table="user_role">
    <!-- 写入复合主键  用composite-id  -->
    <composite-id>
      <!-- 设置字符串时,有可能会因为长度问题而报错。 如报:
      Specified key was too long; max key length is 1000 bytes
      最好设置一下长度。 length="长度" -->
      <key-property name="userCode" column="userCode" type="java.lang.String" length="30"></key-property>
      <key-property name="roleCode" column="roleCode" type="java.lang.String" length="30"></key-property>
    </composite-id>
    <!-- 写普通的属性 -->
    <property name="operateCode" column="operateCode" type="java.lang.String" length="30"></property>
    <property name="operateDate" column="operateDate" type="java.util.Date"></property>
  </class>
</hibernate-mapping>


二.三 创建的测试


/**
   *创建的测试
   */
  @Test
  public void createTest(){
    Session session=HibernateUtil.getSession();
    session.close();
  }


20190324130138947.png


二.四 保存测试


/**
   * 保存的测试
   */
  @Test
  public void saveTest(){
    Session session=HibernateUtil.getSession();
    Transaction transaction=session.beginTransaction();
    /*设置普通的用户角色表*/
    UserRole userRole=new UserRole();
    userRole.setUserCode("两个蝴蝶飞"); //开发中应该设置的是编号
    userRole.setRoleCode("超级管理员");
    userRole.setOperateCode("两个蝴蝶飞");
    userRole.setOperateDate(new java.util.Date());
    session.save(userRole);
    transaction.commit();
    session.close();
  }


20190324130310856.png


20190324130324860.png


二.五 查询测试


/**
   * 查询的测试
   */
  @Test
  public void readTest(){
    Session session=HibernateUtil.getSession();
    Transaction transaction=session.beginTransaction();
    /*创建主键查询*/
    UserRole userRole=new UserRole();
    userRole.setUserCode("两个蝴蝶飞"); //开发中应该设置的是编号
    userRole.setRoleCode("超级管理员"); //这是传入的userRole, 实际上是Serializable接口,是接口编程。
    UserRole uRole=session.get(UserRole.class,userRole);
    System.out.println(uRole);
    transaction.commit();
    session.close();
  }


2019032413054660.png


三. 复合映射(第二种方式)


三.一 创建主键类


将主键提取出来


package com.yjl.pojo;
import java.io.Serializable;
/**
@Date: 2019年3月24日
@author: 两个蝴蝶飞
@Description:复合主键单独拿出来,成为一个类
*/
public class UserRolePrimaryKey implements Serializable{
  private static final long serialVersionUID = 1L;
  /**
   * @param userCode 用户编号
   * @param roleCode 角色编号
   */
  private String userCode;
  private String roleCode;
  public String getUserCode() {
    return userCode;
  }
  public void setUserCode(String userCode) {
    this.userCode = userCode;
  }
  public String getRoleCode() {
    return roleCode;
  }
  public void setRoleCode(String roleCode) {
    this.roleCode = roleCode;
  }
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((roleCode == null) ? 0 : roleCode.hashCode());
    result = prime * result + ((userCode == null) ? 0 : userCode.hashCode());
    return result;
  }
  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    UserRolePrimaryKey other = (UserRolePrimaryKey) obj;
    if (roleCode == null) {
      if (other.roleCode != null)
        return false;
    } else if (!roleCode.equals(other.roleCode))
      return false;
    if (userCode == null) {
      if (other.userCode != null)
        return false;
    } else if (!userCode.equals(other.userCode))
      return false;
    return true;
  }
}


三.二 创建实体类


package com.yjl.pojo;
import java.util.Date;
/**
@Date: 2019年3月24日
@author: 两个蝴蝶飞
@Description:用户与角色关联的表
可以不用实现Serializable接口了。
*/
public class UserRole{
  /*引用复合主键*/
  private UserRolePrimaryKey userRolePrimaryKey;
  /**
   * @param operateCode 操作人
   * @param operateDate 操作日期
   */
  private String operateCode;
  private Date operateDate;
  public UserRolePrimaryKey getUserRolePrimaryKey() {
    return userRolePrimaryKey;
  }
  public void setUserRolePrimaryKey(UserRolePrimaryKey userRolePrimaryKey) {
    this.userRolePrimaryKey = userRolePrimaryKey;
  }
  public String getOperateCode() {
    return operateCode;
  }
  public void setOperateCode(String operateCode) {
    this.operateCode = operateCode;
  }
  public Date getOperateDate() {
    return operateDate;
  }
  public void setOperateDate(Date operateDate) {
    this.operateDate = operateDate;
  }
  @Override
  public String toString() {
    return "UserRole [userRolePrimaryKey=" + userRolePrimaryKey.getUserCode()+":"+userRolePrimaryKey.getRoleCode() 
    + ", operateCode=" + operateCode + ", operateDate="
        + operateDate + "]";
  }
}


三.三 配置文件


<hibernate-mapping>
  <class name="com.yjl.pojo.UserRole" table="user_role">
    <!-- 写入复合主键,这时复合主键实际上是一个属性。 用class进行引入对应的主键类-->
    <composite-id name="userRolePrimaryKey"  class="com.yjl.pojo.UserRolePrimaryKey">
      <key-property name="userCode" column="userCode" type="java.lang.String" length="30"></key-property>
      <key-property name="roleCode" column="roleCode" type="java.lang.String" length="30"></key-property>
    </composite-id>
    <!-- 写普通的属性 -->
    <property name="operateCode" column="operateCode" type="java.lang.String" length="30"></property>
    <property name="operateDate" column="operateDate" type="java.util.Date"></property>
  </class>
</hibernate-mapping>


三.四 创建测试


/**
   *创建的测试
   */
  @Test
  public void createTest(){
    Session session=HibernateUtil.getSession();
    session.close();
  }


创建的依旧是一个类,并不是一个主键类和一个实体类。


2019032413180757.png


三.五 插入测试


/**
   * 保存的测试
   */
  @Test
  public void saveTest(){
    Session session=HibernateUtil.getSession();
    Transaction transaction=session.beginTransaction();
    //开始使用主键类
    UserRolePrimaryKey urPK=new UserRolePrimaryKey();
    urPK.setUserCode("两个蝴蝶飞");
    urPK.setRoleCode("超级管理员");
    /*设置普通的用户角色表*/
    UserRole userRole=new UserRole();
    userRole.setUserRolePrimaryKey(urPK);
    userRole.setOperateCode("两个蝴蝶飞");
    userRole.setOperateDate(new java.util.Date());
    session.save(userRole);
    transaction.commit();
    session.close();
  }


2019032413194348.png


三.六 查询测试


/**
   * 查询的测试
   */
  @Test
  public void readTest(){
    Session session=HibernateUtil.getSession();
    Transaction transaction=session.beginTransaction();
    /*创建主键查询*/
    UserRolePrimaryKey urPK=new UserRolePrimaryKey();
    urPK.setUserCode("两个蝴蝶飞"); //开发中应该设置的是编号
    urPK.setRoleCode("超级管理员"); 
    //传入Serializable接口实现,是接口编程。
    UserRole uRole=session.get(UserRole.class,urPK);
    System.out.println(uRole);
    transaction.commit();
    session.close();
  }


2019032413202711.png


在Hibernate中,不推荐使用复合主键映射,因为需要手动去判断两个主键值,仍然喜欢用两个一对多映射进行替换。


谢谢!!!

相关文章
|
11月前
|
SQL XML 存储
Hibernate框架【五】——基本映射——多对多映射
Hibernate框架【五】——基本映射——多对多映射
139 0
|
1月前
|
Java 数据库连接 数据库
Hibernate5中实体映射命名策略
Hibernate5中实体映射命名策略
62 0
|
1月前
|
SQL 存储 Java
Hibernate - 继承关联关系映射
Hibernate - 继承关联关系映射
46 0
|
Java 数据库连接
mybatis-plus和hibernate 忽略映射字段
mybatis-plus和hibernate 忽略映射字段
254 1
|
SQL Java 数据库连接
《Hibernate上课笔记》-----class3----Hibernate的单实体映射
《Hibernate上课笔记》-----class3----Hibernate的单实体映射
100 0
|
XML Java 数据库连接
《Hibernate上课笔记》----class4----Hibernate继承关系映射实现详解
《Hibernate上课笔记》----class4----Hibernate继承关系映射实现详解
73 0
《Hibernate上课笔记》----class4----Hibernate继承关系映射实现详解
|
存储 SQL Java
hibernate学习笔记之二(映射关系与懒加载)
hibernate学习笔记之二(映射关系与懒加载)
hibernate学习笔记之二(映射关系与懒加载)
|
1月前
|
SQL 缓存 Java
框架分析(9)-Hibernate
框架分析(9)-Hibernate
|
1月前
|
SQL 缓存 Java
Java一分钟之-Hibernate:ORM框架实践
【5月更文挑战第15天】Hibernate是Java的ORM框架,简化数据库操作。本文列举并解决了一些常见问题: 1. 配置SessionFactory,检查数据库连接和JDBC驱动。 2. 实体类需标记主键,属性映射应匹配数据库列。 3. 使用事务管理Session,记得关闭。 4. CRUD操作时注意对象状态和查询结果转换。 5. 使用正确HQL语法,防止SQL注入。 6. 根据需求配置缓存。 7. 懒加载需在事务内处理,避免`LazyInitializationException`。理解和避免这些问题能提升开发效率。
41 0
|
1月前
|
SQL Java 数据库连接
Java从入门到精通:3.1.2深入学习Java EE技术——Hibernate与MyBatis等ORM框架的掌握
Java从入门到精通:3.1.2深入学习Java EE技术——Hibernate与MyBatis等ORM框架的掌握