Mybatis3详解(十)----高级映射之多对多映射
1、案例分析
多对多映射其实就是一个双向的一对多映射,因为两边都是一对多。多对多主要是关联关系要找好,然后根据关联去查询。
由于前面的案例员工和部门一方是一对一,一方是一对多,所以不能形成多对多的条件,我重新换了一个案例——用户和角色。
- 一个用户可以拥有多个角色,User—>Role(一对多)。
- 一个角色可以赋予多个用户,Role—>User(一对多)。
这样就是形成了一个双向的一对多,从而变成了多对多,其实前面掌握了一对多就已经完全足够了,我为了再巩固一下所以继续写了个多对多的例子。数据库表如下:
对应mysql的sql脚本如下:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | -- ---------------------------- -- Table structure for t_role -- ---------------------------- DROP TABLE IF EXISTS `t_role`; CREATE TABLE `t_role` ( `roleId` int ( 11 ) NOT NULL AUTO_INCREMENT, `roleName` varchar( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `remake` varchar( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`roleId`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of t_role -- ---------------------------- INSERT INTO `t_role` VALUES ( 1 , '管理员' , '权限最大' ); INSERT INTO `t_role` VALUES ( 2 , '总经理' , '公司老大' ); INSERT INTO `t_role` VALUES ( 3 , '项目经理' , '项目好好搞,你们需求最多,工资最少!好好干哦' ); INSERT INTO `t_role` VALUES ( 4 , '销售经理' , '销量就靠你们了,销量高,老板才能开上法拉利!' ); INSERT INTO `t_role` VALUES ( 5 , '仓库管理员' , '仓库就归你管了,货不能出错!' ); INSERT INTO `t_role` VALUES ( 6 , '普通员工' , '打工人,打工魂,打工都是人上人,加油!' ); -- ---------------------------- -- Table structure for t_user -- ---------------------------- DROP TABLE IF EXISTS `t_user`; CREATE TABLE `t_user` ( `id` int ( 11 ) NOT NULL AUTO_INCREMENT, `username` varchar( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `age` int ( 11 ) NULL DEFAULT NULL, `birthday` date NULL DEFAULT NULL, `sex` varchar( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `address` varchar( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of t_user -- ---------------------------- INSERT INTO `t_user` VALUES ( 1 , '唐浩荣' , 18 , '2020-11-10' , '1' , '上海' ); INSERT INTO `t_user` VALUES ( 2 , '蔡徐坤' , 18 , '2018-01-18' , '0' , '北京' ); INSERT INTO `t_user` VALUES ( 3 , '黄飞鸿' , 42 , '2020-11-12' , '1' , '大清' ); INSERT INTO `t_user` VALUES ( 4 , '十三姨' , 18 , '2020-11-10' , '0' , '大清' ); INSERT INTO `t_user` VALUES ( 5 , '梁宽' , 42 , '2020-11-10' , '0' , '大清' ); INSERT INTO `t_user` VALUES ( 6 , '马保国' , 33 , '2020-11-14' , '1' , '深圳' ); INSERT INTO `t_user` VALUES ( 7 , '纳兰元述' , 42 , '2020-11-12' , '1' , '大清' ); -- ---------------------------- -- Table structure for t_user_role -- ---------------------------- DROP TABLE IF EXISTS `t_user_role`; CREATE TABLE `t_user_role` ( `ur_id` int ( 11 ) NOT NULL AUTO_INCREMENT, `user_id` int ( 11 ) NULL DEFAULT NULL, `role_id` int ( 11 ) NULL DEFAULT NULL, PRIMARY KEY (`ur_id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of t_user_role -- ---------------------------- INSERT INTO `t_user_role` VALUES ( 1 , 1 , 2 ); INSERT INTO `t_user_role` VALUES ( 2 , 2 , 4 ); INSERT INTO `t_user_role` VALUES ( 3 , 5 , 1 ); INSERT INTO `t_user_role` VALUES ( 4 , 3 , 3 ); INSERT INTO `t_user_role` VALUES ( 5 , 4 , 6 ); INSERT INTO `t_user_role` VALUES ( 6 , 6 , 6 ); INSERT INTO `t_user_role` VALUES ( 7 , 7 , 4 ); INSERT INTO `t_user_role` VALUES ( 8 , 2 , 5 ); |
创建步骤分析:
- User表和Role表具有多对多关系,需要使用中间表(t_user_role)关联,中间表中包含各自的主键,在中间表中是外键;
- 建立两个实体类:用户实体类中包含对角色的集合引用,角色实体类中包含对用户的集合引用;
- 建立两个Mapper接口:用户的Mapper接口和角色的Mapper接口;
- 建立两个配置文件:用户的配置文件和角色的配置文件;
- 实现功能: 查询用户时,同时得到用户所包含的角色信息; 查询角色时,同时得到角色对应的用户信息;
- 编写测试代码并查看运行结果,能否查询出相应的数据;
2、用户到角色的多对多查询
①、查询所有数据的sql语句
01 02 | SELECT * FROM t_user u,t_user_role ur,t_role r WHERE u.id = ur.user_id AND ur.role_id = r.roleId ORDER BY id |
运行结果如下:
②、编写User实体类和UserMapper接口
User实体类:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | /** * 用户实体类 */ public class User { private int userId; private String userName; private int userAge; private Date userBirthday; private int userSex; private String userAddress; //用户拥有的角色 private List<Role> roles; //getter、setter、toString方法省略...... } |
UserMapper接口:
01 02 03 04 05 06 07 08 09 | /** * UserMapperJ接口 */ public interface UserMapper { //查询所有用户信息 List<User> selectAllUser(); //根据用户id查询用户信息 User selectUserByUserId( @Param ( "id" ) Integer userId); } |
③、配置映射文件UserMapper.xml
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | <? xml version="1.0" encoding="UTF-8"?> <! DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> < mapper namespace="com.thr.mapper.UserMapper"> < resultMap id="userMap" type="com.thr.pojo.User"> < id property="userId" column="id"/> < result property="userName" column="username"/> < result property="userAge" column="age"/> < result property="userBirthday" column="birthday"/> < result property="userSex" column="sex"/> < result property="userAddress" column="address"/> <!--一对多映射--> < collection property="roles" ofType="role"> < id property="roleId" column="roleId"/> < result property="roleName" column="roleName"/> < result property="remake" column="remake"/> </ collection > </ resultMap > <!-- 查询所有用户--> < select id="selectAllUser" resultMap="userMap"> SELECT * FROM t_user u, t_user_role ur, t_role r WHERE u.id = ur.user_id AND ur.role_id = r.roleId ORDER BY id </ select > <!--根据用户id查询用户信息--> < select id="selectUserByUserId" resultMap="userMap"> SELECT * FROM t_user u, t_user_role ur, t_role r WHERE u.id = ur.user_id AND ur.role_id = r.roleId AND u.id = #{id} </ select > </ mapper > |
④、编写测试类
01 02 03 04 05 06 07 08 09 10 11 12 13 14 | //查询所有用户信息 @Test public void testSelectAllUser(){ List<User> userList = mapper.selectAllUser(); for (User user : userList) { System.out.println(user); } } //根据用户id查询用户信息 @Test public void testSelectUserByUserId(){ User user = mapper.selectUserByUserId( 2 ); System.out.println(user); } |
⑤、运行结果
查询所有用户信息:
根据用户id查询用户信息:
3、角色到用户的多对多查询
①、查询所有数据的sql语句
01 02 | SELECT * FROM t_user u,t_user_role ur,t_role r WHERE u.id = ur.user_id AND ur.role_id = r.roleId ORDER BY roleID |
运行结果如下:
②、编写Role实体类和RoleMapper接口
Role实体类:
01 02 03 04 05 06 07 08 09 10 11 12 13 | /** * 角色实体类 */ public class Role { private int roleId; private String roleName; private String remake; //备注 //该角色包含的用户 private List<User> users; //getter、setter、toString方法省略...... } |
RoleMapper接口:
01 02 03 04 05 06 07 08 09 | /** * 角色Mapper接口 */ public interface RoleMapper { //查询所有角色信息 List<Role> selectAllRole(); //根据角色id查询角色信息 Role selectRoleByRoleId( @Param ( "id" ) Integer roleId); } |
③、配置映射文件RoleMapper.xml
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | <? xml version="1.0" encoding="UTF-8"?> <! DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> < mapper namespace="com.thr.mapper.RoleMapper"> < resultMap id="roleMap" type="com.thr.pojo.Role"> < id property="roleId" column="roleId"/> < result property="roleName" column="roleName"/> < result property="remake" column="remake"/> < collection property="users" ofType="user"> < id property="userId" column="id"/> < result property="userName" column="username"/> < result property="userAge" column="age"/> < result property="userBirthday" column="birthday"/> < result property="userSex" column="sex"/> < result property="userAddress" column="address"/> </ collection > </ resultMap > <!-- 查询所有角色--> < select id="selectAllRole" resultMap="roleMap"> SELECT * FROM t_user u, t_user_role ur, t_role r WHERE u.id = ur.user_id AND ur.role_id = r.roleId ORDER BY roleId </ select > <!-- 根据角色id查询角色信息--> < select id="selectRoleByRoleId" resultMap="roleMap"> SELECT * FROM t_user u, t_user_role ur, t_role r WHERE u.id = ur.user_id AND ur.role_id = r.roleId AND r.roleId = #{id} </ select > </ mapper > |
④、编写测试类
01 02 03 04 05 06 07 08 09 10 11 12 13 14 | //查询所有角色信息 @Test public void testSelectAllRole(){ List<Role> roleList = mapper.selectAllRole(); for (Role role : roleList) { System.out.println(role); } } //根据角色id查询角色信息 @Test public void testSelectRoleByRoleId(){ Role role = mapper.selectRoleByRoleId( 1 ); System.out.println(role); } |
⑤、运行结果
查询所有角色信息:
根据用户id查询角色信息:
这一节的代码我给它放到了云盘上,有需要参考可以下载:链接:https://pan.baidu.com/s/1mCI74OpdqMlnIxcuiNp7TA ;提取码:s03n
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!