Mybatis3详解(十)----高级映射之多对多映射
1、案例分析
多对多映射其实就是一个双向的一对多映射,因为两边都是一对多。多对多主要是关联关系要找好,然后根据关联去查询。
由于前面的案例员工和部门一方是一对一,一方是一对多,所以不能形成多对多的条件,我重新换了一个案例——用户和角色。
- 一个用户可以拥有多个角色,User—>Role(一对多)。
- 一个角色可以赋予多个用户,Role—>User(一对多)。
这样就是形成了一个双向的一对多,从而变成了多对多,其实前面掌握了一对多就已经完全足够了,我为了再巩固一下所以继续写了个多对多的例子。数据库表如下:

对应mysql的sql脚本如下:
-- ---------------------------- -- 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语句
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实体类:
/**
* 用户实体类
*/
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接口:
/**
* UserMapperJ接口
*/
public interface UserMapper {
//查询所有用户信息
List<User> selectAllUser();
//根据用户id查询用户信息
User selectUserByUserId(@Param("id") Integer userId);
}
③、配置映射文件UserMapper.xml
<?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>
④、编写测试类
//查询所有用户信息
@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语句
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实体类:
/**
* 角色实体类
*/
public class Role {
private int roleId;
private String roleName;
private String remake;//备注
//该角色包含的用户
private List<User> users;
//getter、setter、toString方法省略......
}
RoleMapper接口:
/**
* 角色Mapper接口
*/
public interface RoleMapper {
//查询所有角色信息
List<Role> selectAllRole();
//根据角色id查询角色信息
Role selectRoleByRoleId(@Param("id") Integer roleId);
}
③、配置映射文件RoleMapper.xml
<?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>
④、编写测试类
//查询所有角色信息
@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
作者:
唐浩荣
本文版权归作者和博客园共有,欢迎转载,但是转载需在博客的合适位置给出原文链接,否则保留追究法律责任的权利。
浙公网安备 33010602011771号