• Mybatis3详解(十)——高级映射之多对多映射


    1、案例分析

           多对多映射其实就是一个双向的一对多映射,因为两边都是一对多。多对多主要是关联关系要找好,然后根据关联去查询。

           由于前面的案例员工和部门一方是一对一,一方是一对多,所以不能形成多对多的条件,我重新换了一个案例——用户和角色。

    1. 一个用户可以拥有多个角色,User—>Role(一对多)。
    2. 一个角色可以赋予多个用户,Role—>User(一对多)。

           这样就是形成了一个双向的一对多,从而变成了多对多,其实前面掌握了一对多就已经完全足够了,我为了再巩固一下所以继续写了个多对多的例子。数据库表如下:

    image

           对应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);

           创建步骤分析:

    1. User表和Role表具有多对多关系,需要使用中间表(t_user_role)关联,中间表中包含各自的主键,在中间表中是外键;
    2. 建立两个实体类:用户实体类中包含对角色的集合引用,角色实体类中包含对用户的集合引用;
    3. 建立两个Mapper接口:用户的Mapper接口和角色的Mapper接口;
    4. 建立两个配置文件:用户的配置文件和角色的配置文件;
    5. 实现功能: 查询用户时,同时得到用户所包含的角色信息; 查询角色时,同时得到角色对应的用户信息;
    6. 编写测试代码并查看运行结果,能否查询出相应的数据;

    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

          运行结果如下:

    image

           ②、编写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);
        }

           ⑤、运行结果

           查询所有用户信息:

    image

           根据用户id查询用户信息:

    image

    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

          运行结果如下:

    image

           ②、编写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);
        }

          

           ⑤、运行结果

           查询所有角色信息:

    image

           根据用户id查询角色信息:

    image

           这一节的代码我给它放到了云盘上,有需要参考可以下载:链接:https://pan.baidu.com/s/1mCI74OpdqMlnIxcuiNp7TA ;提取码:s03n

  • 相关阅读:
    MySQL常用维护管理工具 枫
    sql触发器 枫
    MySQL函数大全 枫
    使用Cscope阅读Linux源码 枫
    ASP.NET文件下载,直接向客户端输出文件 枫
    网站设计数据库集群和数据库垂直分割,水平分割,库表散列 枫
    西点成品分类 枫
    asp函数列表 枫
    [笔记]一道C语言面试题:实现 itoa() 函数
    [笔记]Arduino平台使用US100超声波测距模块的电平模式测距实验
  • 原文地址:https://www.cnblogs.com/tanghaorong/p/13995915.html
Copyright © 2020-2023  润新知