一.复合映射
在多对多映射的时候,我们讲到员工与角色表,会创建第三张表。 第三张表中有员工编号,角色编号,创建人和创建日期。 其中,员工编号和角色编号,我们用的是对象,即两个一对多来进行创建第三张表。 实际开发中,员工编号和角色编号是复合主键,两个一对多是无法体现出复合主键的。 这里讲一下,复合主键的使用。
主要有两种方式:
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中,不推荐使用复合主键映射,因为需要手动去判断两个主键值,仍然喜欢用两个一对多映射进行替换。
谢谢!!!