写点什么

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

  • 2022 年 5 月 04 日
  • 本文字数:5059 字

    阅读完需:约 17 分钟

direct messages to file mylog.log

log4j.appender.file=org.apache.log4j.FileAppender


log4j.appender.file.File=c:mylog.log


log4j.appender.file.layout=org.apache.log4j.PatternLayout


log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

set log levels - for more verbose logging change 'info' to 'debug'

error warn info debug trace

log4j.rootLogger= info, stdout


(4)工具类


package com.itzheng.hibernate.utils;


import org.hibernate.Session;


import org.hibernate.SessionFactory;


import org.hibernate.cfg.Configuration;


/*


Hibernate 的工具类


做 hibernate 的小练习,对 configuration 的 configure()方法很好奇,为啥创建的对象还要执行这个方法呢。


Configuration cfg = new Configuration().configure();


原来 configure()方法默认会在 classpath 下面寻找 hibernate.cfg.xml 文件,


如果没有找到该文件,系统会打印如下信息并抛出 HibernateException 异常。


其实不使用 configure()方法也可以


Configuration cfg = new Configuration();


这时 hibernate 会在 classpath 下面寻找 hibernate.properties 文件,


如果没有找到该文件,系统会打印如下信息并抛出 HibernateException 异常。


*/


public class HibernateUtils {


public static final Configuration cfg;


public static final SessionFactory sf;


static {


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


/*


  • 保存多条记录:保存多个用户和角色


*/


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


/*


  • 多对多的一个级联保存

  • 保存角色去,级联保存用户。在角 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 色的映射文件当中配置。


*/


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、多对多的级联删除(基本不用)

用户头像

还未添加个人签名 2022.04.13 加入

还未添加个人简介

评论

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