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中,不推荐使用复合主键映射,因为需要手动去判断两个主键值,仍然喜欢用两个一对多映射进行替换。


谢谢!!!

相关文章
|
Java 数据库连接 API
解锁高效开发秘籍:深入探究 Hibernate 如何优雅处理一对多与多对多关系,让数据映射再无烦恼!
【9月更文挑战第3天】Hibernate 是 Java 领域中最流行的 ORM 框架之一,广泛用于处理实体对象与数据库表之间的映射。尤其在处理复杂关系如一对多和多对多时,Hibernate 提供了丰富的 API 和配置选项。本文通过具体代码示例,展示如何使用 `@OneToMany`、`@JoinColumn`、`@ManyToMany` 和 `@JoinTable` 等注解优雅地实现这些关系,帮助开发者保持代码简洁的同时确保数据一致性。
343 4
|
Java 数据库连接 数据库
AI 时代风起云涌,Hibernate 实体映射引领数据库高效之路,最佳实践与陷阱全解析!
【8月更文挑战第31天】Hibernate 是一款强大的 Java 持久化框架,可将 Java 对象映射到关系数据库表中。本文通过代码示例详细介绍了 Hibernate 实体映射的最佳实践,包括合理使用关联映射(如 `@OneToMany` 和 `@ManyToOne`)以及正确处理继承关系(如单表继承)。此外,还探讨了常见陷阱,例如循环依赖可能导致的无限递归问题,并提供了使用 `@JsonIgnore` 等注解来避免此类问题的方法。通过遵循这些最佳实践,可以显著提升开发效率和数据库操作性能。
311 0
|
数据库 开发者 Java
Hibernate映射注解的魔力:实体类配置的革命,让你的代码量瞬间蒸发!
【8月更文挑战第31天】Hibernate 是一款出色的对象关系映射框架,简化了 Java 应用与数据库的交互。其映射注解让实体类配置变得直观简洁。本文深入剖析核心概念与使用技巧,通过示例展示如何简化配置。
231 0
|
缓存 Java 数据库连接
Hibernate或MyBatis:ORM映射、缓存机制等知识讲解梳理
Hibernate或MyBatis:ORM映射、缓存机制等知识讲解梳理
340 0
|
Java 数据库连接 数据库
Hibernate5中实体映射命名策略
Hibernate5中实体映射命名策略
312 0
|
SQL 存储 Java
Hibernate - 继承关联关系映射
Hibernate - 继承关联关系映射
211 0
|
SQL Java 关系型数据库
Hibernate - Java 类型, Hibernate 映射类型及 SQL 类型之间的对应关系
Hibernate - Java 类型, Hibernate 映射类型及 SQL 类型之间的对应关系
326 0
|
SQL 缓存 Java
框架分析(9)-Hibernate
框架分析(9)-Hibernate
|
缓存 Java 数据库连接
Hibernate:Java持久层框架的高效应用
通过上述步骤,可以在Java项目中高效应用Hibernate框架,实现对关系数据库的透明持久化管理。Hibernate提供的强大功能和灵活配置,使得开发者能够专注于业务逻辑的实现,而不必过多关注底层数据库操作。
227 1
|
SQL Java 数据库连接
Hibernate 是一款开源 ORM(对象关系映射)框架,封装了 JDBC,允许以面向对象的方式操作数据库,简化了数据访问层的开发。
Hibernate 是一款开源 ORM(对象关系映射)框架,封装了 JDBC,允许以面向对象的方式操作数据库,简化了数据访问层的开发。通过映射机制,它可以自动处理对象与数据库表之间的转换,支持主流数据库,提高了代码的可移植性和可维护性。其核心接口包括 SessionFactory、Session 和 Transaction 等,通过它们可以执行数据库的 CRUD 操作。配置方面,需在项目中引入 Hibernate 及数据库驱动依赖,并创建 `hibernate.cfg.xml` 配置文件来设置数据库连接和 Hibernate 行为参数。
252 1