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

本文详细介绍了在Hibernate框架中如何实现复合主键映射的方法,包括两种主要的映射方式:将复合主键属性与其他属性合并在一起的方式以及将复合主键提取到单独主键类中的方式。

东家蝴蝶西家飞,白骑少年今日归。 愿,所有迷茫的人,都不再迷茫的,愿,所有努力工作的人,都可以得到应有的回报,愿,所有的人,都可以找到回家的方向,愿,再无苦痛,再无离别。

上一章简单介绍了Hibernate的继承映射(十四),如果没有看过,请观看上一章
参考了:音①晓 前辈的: https://www.cnblogs.com/otomedaybreak/archive/2012/01/25/2329390.html

一.复合映射

在多对多映射的时候,我们讲到员工与角色表,会创建第三张表。 第三张表中有员工编号,角色编号,创建人和创建日期。 其中,员工编号和角色编号,我们用的是对象,即两个一对多来进行创建第三张表。 实际开发中,员工编号和角色编号是复合主键,两个一对多是无法体现出复合主键的。 这里讲一下,复合主键的使用。
主要有两种方式:
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 方法。 引用的属性是复合主键的属性。

原因,可以参考 音①晓 前辈的:
在这里插入图片描述

二.二 配置文件

<?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();
	}

在这里插入图片描述

二.四 保存测试

/**
	 * 保存的测试
	 */
	@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();
	}

在这里插入图片描述
在这里插入图片描述

二.五 查询测试

/**
	 * 查询的测试
	 */
	@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();
	}

在这里插入图片描述

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

三.一 创建主键类

将主键提取出来

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

创建的依旧是一个类,并不是一个主键类和一个实体类。
在这里插入图片描述

三.五 插入测试

/**
	 * 保存的测试
	 */
	@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();
	}

在这里插入图片描述

三.六 查询测试

/**
	 * 查询的测试
	 */
	@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();
	}

在这里插入图片描述

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

谢谢!!!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

两个蝴蝶飞

你的鼓励,是老蝴蝶更努力写作的

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值