写点什么

Hibernate 多对多的关系映射,详解(代码

  • 2022 年 5 月 12 日
  • 本文字数:4770 字

    阅读完需:约 16 分钟

cfg = new Configuration().configure();// 获取与数据库的链接的配置文件


sf = cfg.buildSessionFactory();//开启事务建立与数据库之间的链接


}


public static Session openSession() {


return sf.openSession();


}


public static Session getCurrentSession() {


return sf.getCurrentSession();


}


}

[](()3、创建实体

(1)创建用户的实体


package com.itzheng.hibernate.domain;


/*


  • 用户的实体


CREATE TABLE sys_user (


user_id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '用户 id',


user_code varchar(32) NOT NULL COMMENT '用户账号',


user_name varchar(64) NOT NULL COMMENT '用户名称',


user_password varchar(32) NOT NULL COMMENT '用户密码',


user_state char(1) NOT NULL COMMENT '1:正常,0:暂停',


PRIMARY KEY (user_id)


) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;


*/


public class User {


private Long user_id;


private String user_code;


private String user_name;


private String user_password;


private String user_state;


public Long getUser_id() {


return user_id;


}


public void setUser_id(Long user_id) {


this.user_id = user_id;


}


public String getUser_code() {


return user_code;


}


public void setUser_code(String user_code) {


this.user_code = user_code;


}


public String getUser_name() {


return user_name;


}


public void setUser_name(String user_name) {


this.user_name = user_name;


}


public String getUser_password() {


return user_password;


}


public void setUser_password(String user_password) {


this.user_password = user_password;


}


public String getUser_state() {


return user_state;


}


public void setUser_state(String user_state) {


this.user_state = user_state;


}


}


(2)创建角色的实体


package com.itzheng.hibernate.domain;


/*


  • 角色的实体


CREATE TABLE sys_role (


role_id bigint(32) NOT NULL AUTO_INCREMENT,


role_name varchar(32) NOT NULL COMMENT '角色名称',


role_memo varchar(128) DEFAULT NULL COMMENT '备注',


PRIMARY KEY (role_id)


) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;


*/


public class Role {


private Long role_id;


private String role_name;


private String role_memo;


public Long getRole_id() {


return role_id;


}


public void setRole_id(Long role_id) {


this.role_id = role_id;


}


public String getRole_name() {


return role_name;


}


public void setRole_name(String role_name) {


this.role_name = role_name;


}


public String getRole_memo() {


return role_memo;


}


public void setRole_memo(String role_memo) {


this.role_memo = role_memo;


}


}

[](()4、设置多对多的关系(放置对方的集合)

(1)一个用户选择多个角色



同时生成 get 和 set 方法


(2)一个角色被多个用户选择



同时生成 get 和 set 方法

[](()4、创建映射


User.hbm.xml


<?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.itzheng.hibernate.domain.User" table="sys_user">


<id name="user_id" column="user_id">


<generator class="native" />


</id>


<property name="user_code" column="user_code"/>


<property name="user_name" column="user_name"/>


<property name="user_password" column="user_password"/>


<property name="user_state" column="user_state"/>


<!--


在 set 标签当中有


*name 属性:对方集合的属性名称


table 属性:多对多的关系需要使用中间表,中间表的名称


-->


<set name="roles" table="sys_user_role">


<!--


key 标签的:


column:当前的对象对应中间表的外键的名称。


-->


<key column="user_id"/>


<!--


many-to-many 标签:


*class :对象的类的全路径


*column:对方的对象对应的中间表中的外键名称。


-->


<many-to-many class="com.itzheng.hibernate.domain.Role" column="role_id"/>


</set>


</class>


</hibernate-mapping>


Role.hbm.xml


<?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.itzheng.hibernate.domain.Role" table="sys_role">


<id name="role_id" column="role_id">


<generator class="native"/>


</id>


<property name="role_name" column="role_name"/>


<property name="role_memo" column="role_memo"/>


<!--


key 标签的:


column:当前的对象对应中间表的外键的名称。


-->


<set name="users" table="sys_user_role">


<!--


key 标签的:


column:当前的对象对应中间表的外键的名称。


-->


<key column="role_id"/>


<!--


many-to-many 标签:


*class :对象的类的全路径


*column:对方的对象对应的中间表中的外键名称。


-->


<many-to-many class="com.itzheng.hibernate.domain.User" column="user_id"/>


</set>


</class>


</hibernate-mapping>

[](()5、将映射添加到核心配置文件

在 hibernate.cfg.xml



[](()二、编写测试类




直接执行下面代码会报错


package com.itzheng.hibernate.demo2;


import org.hibernate.Session;


import org.hibernate.Transaction;


import org.junit.Test;


import com.itzheng.hibernate.domain.Role;


import com.itzheng.hibernate.domain.User;


import com.itzheng.hibernate.utils.HibernateUtils;


/*


  • Hibernate 的多对多的映射


*/


public class HibernateDemo2 {


@Test


/*


  • 保存多条 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 记录:保存多个用户和角色


*/


public void demo01() {


Session session = HibernateUtils.getCurrentSession();


Transaction transaction = session.beginTransaction();


// 创建 2 个用户


User user1 = new User();


user1.setUser_name("李白");


User user2 = new User();


user2.setUser_name("杜甫");


// 创建 3 个角色


Role role1 = new Role();


role1.setRole_name("研发部");


Role role2 = new Role();


role2.setRole_name("市场部");


Role role3 = new Role();


role3.setRole_name("公关部");


// 设置双向的关联关系,获取到对应的集合将对象添加进去,用户和角色相互对应


user1.getRoles().add(role1);


user1.getRoles().add(role2);


user2.getRoles().add(role2);


user2.getRoles().add(role3);


role1.getUsers().add(user1);


role2.getUsers().add(user1);


role2.getUsers().add(user2);


role3.getUsers().add(user2);


// 保存操作:多对多建立了双向的关系,必须有一方放弃了外键维护


session.save(user1);


session.save(user2);


session.save(role1);


session.save(role2);


session.save(role3);


transaction.commit();


}


}


报主键重混异常



需要被动方放弃外键维护权,这里是在角色的一方放弃外键维护权


在 Role.hbm.xml 当中的 set 集合当中



设置完后执行


成功执行



[](()三、Hibernate 多对多的一些操作



[](()1、多对多的情况下在不设置级联的情况下,只保存一边会报错

(1)值保存用户(测试代码)


@Test


/*


  • 多对多的一些操作 只是保存一边是否可以,答案在不设置级联的情况下会报,瞬时对象异常


*/


public void demo02() {


Session session = HibernateUtils.getCurrentSession();


Transaction transaction = session.beginTransaction();


// 创建 2 个用户


User user1 = new User();


user1.setUser_name("李白");


// 创建 3 个角色


Role role1 = new Role();


role1.setRole_name("研发部");


Role role2 = new Role();


role2.setRole_name("市场部");


Role role3 = new Role();


role3.setRole_name("公关部");


// 设置双向的关联关系,获取到对应的集合将对象添加进去,用户和角色相互对应


user1.getRoles().add(role1);


role1.getUsers().add(user1);


// 只保存角色


session.save(user1);


transaction.commit();


}


(2)只保存角色,因为 Role 放弃了外键维护权,保存角色的时候,不影用户,所以不会报错(但是因为在核心配置文件当中是 create 从新建表,所以用户表会被置空)


@Test


/*


  • 多对多的一些操作 只是保存一边是否可以,答案在不设置级联的情况下会报,瞬时对象异常


*/


public void demo02() {


Session session = HibernateUtils.getCurrentSession();


Transaction transaction = session.beginTransaction();


// 创建 2 个用户


User user1 = new User();


user1.setUser_name("李白");


// 创建 3 个角色


Role role1 = new Role();


role1.setRole_name("研发部");


Role role2 = new Role();


role2.setRole_name("市场部");


Role role3 = new Role();


role3.setRole_name("公关部");


// 设置双向的关联关系,获取到对应的集合将对象添加进去,用户和角色相互对应


user1.getRoles().add(role1);


role1.getUsers().add(user1);


// 只保存用户


//session.save(user1);


//只保存角色


session.save(role1);


transaction.commit();


}

[](()2、多对多的级联保存或者更新

(1) 保存用户,级联保存角色。在用户的映射文件当中配置。


在 User.hbm.xml 中的 set 当中配置 cascade=“save-update”



这是只保存 User 的时候


@Test


/*


  • 多对多的一个级联保存

  • 保存用户,级联保存角色。在用户的映射文件当中配置。


*/


public void demo03() {


Session session = HibernateUtils.getCurrentSession();


Transaction transaction = session.beginTransaction();


// 创建 2 个用户


User user1 = new User();


user1.setUser_name("李白");


// 创建 3 个角色


Role role1 = new Role();


role1.setRole_name("研发部");


Role role2 = new Role();


role2.setRole_name("市场部");


Role role3 = new Role();


role3.setRole_name("公关部");


// 设置双向的关联关系,获取到对应的集合将对象添加进去,用户和角色相互对应


user1.getRoles().add(role1);


role1.getUsers().add(user1);


// 只保存用户


session.save(user1);


// 只保存角色


//session.save(role1);


transaction.commit();


}


成功执行并插入了数据(一号用户选择了一号角色)



多对多的一个级联保存


(2) 保存角色去,级联保存用户。在角色的映射文件当中配置。


在 Role.hbm.xml 当中



@Test


/*


  • 多对多的一个级联保存

  • 保存角色去,级联保存用户。在角色的映射文件当中配置。


*/


public void demo04() {


Session session = HibernateUtils.getCurrentSession();


Transaction transaction = session.beginTransaction();


// 创建 2 个用户


User user1 = new User();


user1.setUser_name("李白");


// 创建 3 个角色


Role role1 = new Role();


role1.setRole_name("研发部");


Role role2 = new Role();


role2.setRole_name("市场部");


Role role3 = new Role();


role3.setRole_name("公关部");


// 设置双向的关联关系,获取到对应的集合将对象添加进去,用户和角色相互对应


user1.getRoles().add(role1);


role1.getUsers().add(user1);


// 只保存用户


//session.save(role1);


// 只保存角色


session.save(role1);


transaction.commit();


}

[](()3、多对多的级联删除(基本不用)

中间表



(1)测试级联删除的功能,当中删除用户的时候级联删除角色


在 User.hbm.xml 当中配置



更改核心配置文件当中的 hibernate.cfg.xml



执行下列代码


@Test


/*


  • 多对多的一个级联删除 删除用户级联删除角色,

  • 在 User.hbm.xml 中的 set 上配置 cascade="delete"


*/


public void demo05() {


Session session = HibernateUtils.getCurrentSession();


Transaction transaction = session.beginTransaction();


// 先查询 1 号用户


User user = session.get(User.class, 1l);


//删除对应的用户


session.delete(user);


transaction.commit();


}


级联删除



(2)删除角色级联删除用户


在 Role.hbm.xml 中的 set 上配置 cascade=“delete”



执行下面代码

用户头像

还未添加个人签名 2022.04.13 加入

还未添加个人简介

评论

发布
暂无评论
Hibernate多对多的关系映射,详解(代码_Java_爱好编程进阶_InfoQ写作社区