Mybatis的多表关联查询(多对多)

  • 项目目录结构
  • 实现 Role 到 User 多对多
    • 业务要求
    • 用户与角色的关系模型
    • 编写角色实体类
    • 编写 Role 持久层接口
    • 实现的 SQL 语句
    • 编写映射文件
    • 测试代码
  • 实现 User 到 Role 的多对多
    • 业务要求
    • 编写用户实体类
    • 编写 User持久层接口
    • 实现的 SQL 语句
    • 编写映射文件
    • 测试代码
mybatis中的多表查询:示例:用户和角色一个用户可以有多个角色一个角色可以赋予多个用户步骤:1、建立两张表:用户表,角色表让用户表和角色表具有多对多的关系。需要使用中间表,中间表中包含各自的主键,在中间表中是外键。2、建立两个实体类:用户实体类和角色实体类让用户和角色的实体类能体现出来多对多的关系各自包含对方一个集合引用3、建立两个配置文件用户的配置文件角色的配置文件4、实现配置:当我们查询用户时,可以同时得到用户所包含的角色信息当我们查询角色时,可以同时得到角色的所赋予的用户信息

项目目录结构

实现 Role 到 User 多对多

多对多关系其实我们看成是双向的一对多关系。

业务要求

需求:
当我们查询角色时,可以同时得到角色的所赋予的用户信息。
分析:
查询角色我们需要用到Role表,但角色分配的用户的信息我们并不能直接找到用户信息,而是要通过中间表(USER_ROLE 表)才能关联到用户信息。

用户与角色的关系模型

用户与角色的多对多关系模型如下:

角色表:

用户表:

用户角色中间表:

编写角色实体类

Role:

package com.keafmd.domain;import java.io.Serializable;
import java.util.List;/*** Keafmd** @ClassName: Role* @Description: 角色实体类* @author: 牛哄哄的柯南* @date: 2021-02-12 16:45*/
public class Role implements Serializable {private Integer roleId;private String roleName;private String roleDesc;//多对多的关系映射private List<User> users;public List<User> getUsers() {return users;}public void setUsers(List<User> users) {this.users = users;}public Integer getRoleId() {return roleId;}public void setRoleId(Integer roleId) {this.roleId = roleId;}public String getRoleName() {return roleName;}public void setRoleName(String roleName) {this.roleName = roleName;}public String getRoleDesc() {return roleDesc;}public void setRoleDesc(String roleDesc) {this.roleDesc = roleDesc;}@Overridepublic String toString() {return "Role{" +"roleId=" + roleId +", roleName='" + roleName + '\'' +", roleDesc='" + roleDesc + '\'' +'}';}
}

编写 Role 持久层接口

IRoleDao:

package com.keafmd.dao;
import com.keafmd.domain.Role;
import java.util.List;/*** Keafmd** @ClassName: IRoleDao* @Description:* @author: 牛哄哄的柯南* @date: 2021-02-12 19:01*/public interface IRoleDao {/*** 查询所有角色* @return*/List<Role> findAll();}

实现的 SQL 语句

select u.*,r.id as rid ,r.role_name ,r.role_desc from role r
left outer join user_role ur on r.id = ur.rid
left outer join user u on u.id=ur.uid

执行结果:

注意:sql语句换行的时候最好在每行的末尾或开头添加空格,这样可以防止合并成一行时发生错误。

编写映射文件

IRoleDao.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.keafmd.dao.IRoleDao"><!--定义role表的resultmap--><resultMap id="roleMap" type="role"><id property="roleId" column="rid"></id><result property="roleName" column="role_name"></result><result property="roleDesc" column="role_desc"></result><collection property="users" ofType="user"><id column="id" property="id"></id><result column="username" property="username"></result><result column="address" property="address"></result><result column="sex" property="sex"></result><result column="birthday" property="birthday"></result></collection></resultMap><!--查询所有--><select id="findAll" resultMap="roleMap">select u.*,r.id as rid ,r.role_name ,r.role_desc from role rleft outer join user_role ur on r.id = ur.ridleft outer join user u on u.id=ur.uid</select></mapper>

测试代码

RoleTest:

package com.keafmd.test;import com.keafmd.dao.IRoleDao;
import com.keafmd.dao.IUserDao;
import com.keafmd.domain.Role;
import com.keafmd.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;import java.io.InputStream;
import java.util.List;/*** Keafmd** @ClassName: MybatisTest* @Description: 测试类,测试crud操作* @author: 牛哄哄的柯南* @date: 2021-02-08 15:24*/
public class RoleTest {private InputStream in;private SqlSession sqlsession;private IRoleDao roleDao;@Before // 用于在测试方法执行前执行public void init()throws Exception{//1.读取配置文件,生成字节输入流in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建SqlSessionFactory工厂SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();SqlSessionFactory factory = builder.build(in);//3.使用工厂生产SqlSession对象sqlsession = factory.openSession(); //里面写个true,下面每次就不用了写 sqlsession.commit(); 了//4.使用SqlSession创建Dao接口的代理对象roleDao = sqlsession.getMapper(IRoleDao.class);}@After // 用于在测试方法执行后执行public void destory() throws Exception{//提交事务sqlsession.commit();//6.释放资源sqlsession.close();in.close();}/*** 查询所有* @throws Exception*/@Testpublic void testFindAll() {List<Role> roles = roleDao.findAll();for (Role role : roles) {System.out.println("--------每个角色的信息---------");System.out.println(role);System.out.println(role.getUsers());}}}

运行结果:

2021-02-13 00:05:47,481 349    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Opening JDBC Connection
2021-02-13 00:05:47,784 652    [           main] DEBUG source.pooled.PooledDataSource  - Created connection 1027007693.
2021-02-13 00:05:47,784 652    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
2021-02-13 00:05:47,791 659    [           main] DEBUG om.keafmd.dao.IRoleDao.findAll  - ==>  Preparing: select u.*,r.id as rid ,r.role_name ,r.role_desc from role r left outer join user_role ur on r.id = ur.rid left outer join user u on u.id=ur.uid
2021-02-13 00:05:47,842 710    [           main] DEBUG om.keafmd.dao.IRoleDao.findAll  - ==> Parameters:
2021-02-13 00:05:47,869 737    [           main] DEBUG om.keafmd.dao.IRoleDao.findAll  - <==      Total: 4
--------每个角色的信息---------
Role{roleId=1, roleName='院长', roleDesc='管理整个学院'}
[User{id=41, username='老王', sex='男', address='北京', birthday=Tue Feb 27 17:47:08 CST 2018}, User{id=45, username='新一', sex='男', address='北京', birthday=Sun Mar 04 12:04:06 CST 2018}]
--------每个角色的信息---------
Role{roleId=2, roleName='总裁', roleDesc='管理整个公司'}
[User{id=41, username='老王', sex='男', address='北京', birthday=Tue Feb 27 17:47:08 CST 2018}]
--------每个角色的信息---------
Role{roleId=3, roleName='校长', roleDesc='管理整个学校'}
[]
2021-02-13 00:05:47,871 739    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
2021-02-13 00:05:47,872 740    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
2021-02-13 00:05:47,872 740    [           main] DEBUG source.pooled.PooledDataSource  - Returned connection 1027007693 to pool.Process finished with exit code 0

实现 User 到 Role 的多对多

业务要求

需求:
当我们查询用户时,可以同时得到用户所包含的角色信息。

分析:
相比上面的实现 Role 到 User 多对多,主要变化就是sql语句的变化。

编写用户实体类

User:

package com.keafmd.domain;import java.io.Serializable;
import java.util.Date;
import java.util.List;/*** Keafmd** @ClassName: User* @Description:* @author: 牛哄哄的柯南* @date: 2021-02-08 15:16*/public class User implements Serializable {private Integer id;private String username;private String sex;private String address;private Date birthday;//多对多的关系映射,一个用户可以具备多个角色private List<Role> roles;public List<Role> getRoles() {return roles;}public void setRoles(List<Role> roles) {this.roles = roles;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", sex='" + sex + '\'' +", address='" + address + '\'' +", birthday=" + birthday +'}';}
}

编写 User持久层接口

IUserDao:

package com.keafmd.dao;import com.keafmd.domain.User;import java.util.List;/*** Keafmd** @ClassName: IUserDao* @Description: 用户的持久层接口* @author: 牛哄哄的柯南* @date: 2021-02-06 19:29*/public interface IUserDao {/*** 查询所有用户,同时获取到用户下所有账户的信息* @return*/List<User> findAll();}

实现的 SQL 语句

   select u.*,r.id as rid ,r.role_name ,r.role_desc from user u left outer join user_role ur on u.id = ur.uid left outer join role r on r.id=ur.rid

执行结果:

编写映射文件

IUserDao.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.keafmd.dao.IUserDao"><!--定义User的resultMap--><resultMap id="userMap" type="user"><id property="id" column="id"></id><result property="username" column="username"></result><result property="address" column="address"></result><result property="sex" column="sex"></result><result property="birthday" column="birthday"></result><!--配置角色集合的映射--><collection property="roles" ofType="role"><id property="roleId" column="rid"></id><result property="roleName" column="role_name"></result><result property="roleDesc" column="role_desc"></result></collection></resultMap><!--配置查询所有--><select id="findAll" resultMap="userMap">select u.*,r.id as rid ,r.role_name ,r.role_desc from user uleft outer join user_role ur on u.id = ur.uidleft outer join role r on r.id=ur.rid</select></mapper>

测试代码

UserTest :

package com.keafmd.test;import com.keafmd.dao.IUserDao;
import com.keafmd.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;import java.io.InputStream;
import java.util.List;/*** Keafmd** @ClassName: MybatisTest* @Description: 测试类,测试crud操作* @author: 牛哄哄的柯南* @date: 2021-02-08 15:24*/
public class UserTest {private InputStream in;private SqlSession sqlsession;private IUserDao userDao;@Before // 用于在测试方法执行前执行public void init()throws Exception{//1.读取配置文件,生成字节输入流in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.创建SqlSessionFactory工厂SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();SqlSessionFactory factory = builder.build(in);//3.使用工厂生产SqlSession对象sqlsession = factory.openSession(); //里面写个true,下面每次就不用了写 sqlsession.commit(); 了//4.使用SqlSession创建Dao接口的代理对象userDao = sqlsession.getMapper(IUserDao.class);}@After // 用于在测试方法执行后执行public void destory() throws Exception{//提交事务sqlsession.commit();//6.释放资源sqlsession.close();in.close();}/*** 查询所有* @throws Exception*/@Testpublic void testFindAll() {List<User> users = userDao.findAll();for (User user : users) {System.out.println("--------每个用户的信息---------");System.out.println(user);System.out.println(user.getRoles());}}}

运行结果:

2021-02-13 00:17:32,971 422    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Opening JDBC Connection
2021-02-13 00:17:33,275 726    [           main] DEBUG source.pooled.PooledDataSource  - Created connection 1027007693.
2021-02-13 00:17:33,275 726    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
2021-02-13 00:17:33,280 731    [           main] DEBUG om.keafmd.dao.IUserDao.findAll  - ==>  Preparing: select u.*,r.id as rid ,r.role_name ,r.role_desc from user u left outer join user_role ur on u.id = ur.uid left outer join role r on r.id=ur.rid
2021-02-13 00:17:33,319 770    [           main] DEBUG om.keafmd.dao.IUserDao.findAll  - ==> Parameters:
2021-02-13 00:17:33,343 794    [           main] DEBUG om.keafmd.dao.IUserDao.findAll  - <==      Total: 10
--------每个用户的信息---------
User{id=41, username='老王', sex='男', address='北京', birthday=Tue Feb 27 17:47:08 CST 2018}
[Role{roleId=1, roleName='院长', roleDesc='管理整个学院'}, Role{roleId=2, roleName='总裁', roleDesc='管理整个公司'}]
--------每个用户的信息---------
User{id=42, username='update', sex='男', address='XXXXXXX', birthday=Mon Feb 08 19:37:31 CST 2021}
[]
--------每个用户的信息---------
User{id=43, username='小二王', sex='女', address='北京', birthday=Sun Mar 04 11:34:34 CST 2018}
[]
--------每个用户的信息---------
User{id=45, username='新一', sex='男', address='北京', birthday=Sun Mar 04 12:04:06 CST 2018}
[Role{roleId=1, roleName='院长', roleDesc='管理整个学院'}]
--------每个用户的信息---------
User{id=50, username='Keafmd', sex='男', address='XXXXXXX', birthday=Mon Feb 08 15:44:01 CST 2021}
[]
--------每个用户的信息---------
User{id=51, username='update DAO', sex='男', address='XXXXXXX', birthday=Tue Feb 09 11:31:38 CST 2021}
[]
--------每个用户的信息---------
User{id=52, username='Keafmd DAO', sex='男', address='XXXXXXX', birthday=Tue Feb 09 11:29:41 CST 2021}
[]
--------每个用户的信息---------
User{id=53, username='Keafmd laset insertid 1', sex='男', address='XXXXXXX', birthday=Fri Feb 12 20:53:46 CST 2021}
[]
--------每个用户的信息---------
User{id=54, username='Keafmd laset insertid 2 auto', sex='男', address='XXXXXXX', birthday=Fri Feb 12 21:02:12 CST 2021}
[]
2021-02-13 00:17:33,345 796    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
2021-02-13 00:17:33,346 797    [           main] DEBUG ansaction.jdbc.JdbcTransaction  - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
2021-02-13 00:17:33,346 797    [           main] DEBUG source.pooled.PooledDataSource  - Returned connection 1027007693 to pool.Process finished with exit code 0

以上就是Mybatis的多表关联查询(多对多)的全部内容。

看完如果对你有帮助,感谢点赞支持!
如果你是电脑端的话,看到右下角的 “一键三连” 了吗,没错点它[哈哈]

加油!

共同努力!

Keafmd

Mybatis的多表关联查询(多对多)相关推荐

  1. MyBatis实现中间表关联查询

    MyBatis实现中间表关联查询 通常构建数据多对多模型的关系时,我们需要再建立一张中间表来关联另外两张表. 下面介绍一下,怎么用MyBatis来实现中间表关联查询并封装到实体类对象中. 现在有三张表 ...

  2. asp多表查询并显示_SpringBoot系列(五):SpringBoot整合Mybatis实现多表关联查询

    本文我们将继续分享介绍Spring Boot在整合Mybatis开发企业级应用时其他典型的业务场景,即Mybatis是如何实现多表关联查询时将查询结果集与对象进行映射的,主要的内容包含"一对 ...

  3. F005MyBatis学习笔记-MyBatis的多表关联查询

    一. 概述 1.一对一 举例:身份证号对人,一个身份证好只能对应一个人,一个人也只能对应一个身份证号,这就是一对一: 特例:Mybatis将多对一看做是一对一: 2.多对多 举例:学生对老师,一个老师 ...

  4. MyBatis之两表关联查询

    1. 数据库表 学生表: 教师表: 2. 需求 要求查询所有教师的信息, 包括他的学生信息. 查询结果样式: 3. 代码 实体类 pojo包下: Student.java package com.xx ...

  5. Mybatis高级应用 多表关联查询

    >以订单商品数据模型为例子: 存在以下四张表,用户表user,用户订单表orders,订单明细表orderdetail,商品表items.四张表之间的关系如下图所示: 下面给出四张表结构的详细定 ...

  6. mybatis 多表关联查询_Java修行第041天--MyBatis框架(下)--多表查询

    1 解决列名和属性名不一致问题 如果查询时使用 resultType 属性, 表示采用 MyBatis 的Auto-Mapping(自动映射)机制, 即相同的列名和属性名会自动匹配. 因此, 当数据库 ...

  7. MyBatis多表关联查询

    本文将向大家介绍 MyBatis 中的多表关联查询 主要通过两个示例来说明在 MyBatis 中如何实现 一对多,多对一 和 多对多 查询 第一个示例:老师和学生关联 ​ 老师和学生是一对多的关系,一 ...

  8. jpa多表关联查询_Spring Boot 整合mybatis如何自定义 mapper 实现多表关联查询

    上一篇文章已经介绍了自定义 mapper 实现自定义的方法,其实实现了通过自定义的mapper就可以做多表关联等复杂查询.但是很多朋友还是反馈说没有实现多表关联查询,所以,今天把文章又重新修改了,增加 ...

  9. MyBatis复习(五):获取多表关联查询结果

    Map保存查询结果 <select id="selectBlogMap" resultType="java.util.Map">select b.* ...

最新文章

  1. 信息系统项目管理师-论文要求
  2. 中国电信线CTF线下选拨writeup
  3. python编译环境对cpu要求高不高_解决Tensorflow 使用时cpu编译不支持警告的问题
  4. sap 标准委外和工序委外_SAP那些事-实战篇-74-公司间委外的几种方式探讨
  5. oss上传报错_layui+oss阿里云附件上传回调报错问题
  6. python中json怎么转换成字典
  7. java必学的技术,终于有人把Java程序员必学知识点整理出来了,令人有如醍醐灌顶...
  8. java语言程序设计第三版沈泽刚课后答案_Java语言程序设计(第3版)学习指导与习题解析...
  9. 计算机类专业试题及答案,计算机专业考试试题集及答案.doc
  10. qt之QTcpSocket
  11. CGB2202语言基础第1天
  12. Flutter 中TextField的hintText不居中与光标位置不一致
  13. 阿里P6+Java研发工程师,到底牛在哪儿?真了
  14. lol8月7号服务器维护,LOL8月7日更新了什么内容 8.15新版本更新维护公告
  15. 如何用photoshop输出html网页(转)
  16. 阿里云服务器域名备案全过程详细讲解
  17. 【分享】免费的国际一级域名和100M支持asp、cgi空间
  18. 迟到的 2019 年个人总结
  19. 解决 iOS 上 transform rotate 兼容问题
  20. Appium-安装与入门

热门文章

  1. oracle alter system set,alter system set control_files=..............
  2. python合并单元格处理_Python基于xlrd模块处理合并单元格
  3. GBase 8s 备份介绍
  4. win10系统鼠标被禁用了如何解决_win10鼠标被禁用了怎么恢复
  5. linux optix CmakeLists 编译.cu文件成.ptx
  6. 51单片机c语言试题及答案,C51单片机期末试卷.doc
  7. 使用JQuery完成网上商城的制作
  8. 在中国大陆,35岁以后的程序员该怎么做职业规划?去国企或体制内好呢?还是出国或出境工作好呢?
  9. 十大经典排序之冒泡排序
  10. Sweet Home 3D for Mac(室内设计软件)