东家蝴蝶西家飞,白骑少年今日归。 愿,所有迷茫的人,都不再迷茫的,愿,所有努力工作的人,都可以得到应有的回报,愿,所有的人,都可以找到回家的方向,愿,再无苦痛,再无离别。
上一章简单介绍了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 有以下几个扩充:
- 实现Serializable 接口。
- 重写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中,不推荐使用复合主键映射,因为需要手动去判断两个主键值,仍然喜欢用两个一对多映射进行替换。
谢谢!!!