Mybatis多表查询之多对多(角色到用户的查询,用户到角色的查询)

Mybatis多表查询之多对多

实现用户和角色之间的多对多

用户与角色之间的关系模型:
	一个用户可以有多个角色。
	一个角色可以赋予多个用户。
步骤:
	1.建立两张表,用户表和角色表。
		让用户表和角色表之间具有多对多的关系。
		需要使用中间表,中间表包含各自的主键,在中间表中是外键。
	2.建立两个实体类:用户实体类和角色实体类。
		让用户和角色的实体类能体现出来多对多的关系。
		各自包含对方的一个集合引用。
	3.建立两个配制文件
		用户的配制文件。
		角色的配制文件。
	4.实现配置:
		当我们查询用户时,可以同时得到用户所包含的角色信息。
		当我们查询角色时,可以同时得到角色所赋予的用户信息。

角色到用户的多对多查询

SQL语句的实现

需求:
	实现查询所有对象并且加载它所分配的用户信息。
分析:
	查询角色我们要用到Role表,但角色分配的用户的信息我们并不能直接找到用户信息,而是要通过中间表(USER_ROLE表)才能关联到用户信息。
下面是实现的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 ur.uid=u.id

编写角色实体类

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;
    }

    @Override
    public String toString() {
        return "Role{" +
                "roleId=" + roleId +
                ", roleName='" + roleName + '\'' +
                ", roleDesc='" + roleDesc + '\'' +
                '}';
    }
}

编写Role持久层接口

public interface IRoleDao {
    /*查询所有角色*/
    List<Role> findAll();
}

编写映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.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 r
         left outer join user_role ur on r.id=ur.rid
         left outer join user u on u.id=ur.uid
    </select>
</mapper>

编写测试类

public class RoleTest {
    private InputStream resourceAsStream;
    private SqlSession sqlSession;
    private IRoleDao roleDao;
    @Before
    public void init() throws IOException {
        //读取配制文件,生成字节输入流
        resourceAsStream = Resources.getResourceAsStream("SqlMapperConfig.xml");
        //获取SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        //获取SqlSession对象
        //如果这里传入一个参数true,那么就可以自动实现提交事务。后面就不需要再commit事务了。
        sqlSession = factory.openSession(true);
        //sqlSession = factory.openSession();
        //获取dao的代理对象
        roleDao = this.sqlSession.getMapper(IRoleDao.class);
    }
    @After
    public void destory() throws IOException {
        //提交事务
        //sqlSession.commit();//这里就不要再提交事务了
        //释放资源
        sqlSession.close();
        resourceAsStream.close();
    }
    //测试查询所有
    @Test
    public void testFindAll(){
        List<Role> roles = roleDao.findAll();
        for (Role role : roles) {
            System.out.println("--每个角色的信息--");
            System.out.println(role);
            System.out.println(role.getUsers());
        }
    }
}

用户到角色的多对多查询

	从User出发,我们也可以发现一个用户可以具有多个角色,这样用户到角色的关系也是一对多关系,
这样我们就可以认为User到Role的多对多关系,可以被拆分成两个一对多关系来实现。

SQL语句的实现

需求:
	实现查询所有对象并且加载它所分配的角色信息。
分析:
	查询角色我们要用到Role表,但角色分配的用户的信息我们并不能直接找到用户信息,而是要通过
中间表(USER_ROLE表)才能关联到用户信息。
下面是实现的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

编写用户实体类

public class User implements Serializable {
    private Integer id;
    private String username;
    private String address;
    private String sex;
    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 getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", address='" + address + '\'' +
                ", sex='" + sex + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}

编写User持久层接口

/*
* 用户的持久层接口
* */
public interface IUserDao {
    //查询所有的用户,同时获取到用户下所有账户的信息
    List<User> findAll();
    //查询方法,根据id进行查询用户信息
    User findById(Integer userId);
}

编写映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.dao.IUserDao">
    <!--定义User的resultMap-->
    <resultMap id="userAccountMap" 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="userAccountMap">
        /*根据用户找角色*/
        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
    </select>

    <!--根据id查询用户-->
    <!--这里需要一个返回值类型,因此得写上resultType-->
    <select id="findById" parameterType="java.lang.Integer" resultType="com.itheima.domain.User">
        select * from user where id=#{uid}
    </select>
</mapper>

编写测试类

public class UserTest {
    private InputStream resourceAsStream;
    private SqlSession sqlSession;
    private IUserDao userDao;
    @Before
    public void init() throws IOException {
        //读取配制文件,生成字节输入流
        resourceAsStream = Resources.getResourceAsStream("SqlMapperConfig.xml");
        //获取SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        //获取SqlSession对象
        //如果这里传入一个参数true,那么就可以自动实现提交事务。后面就不需要再commit事务了。
        sqlSession = factory.openSession(true);
        //sqlSession = factory.openSession();
        //获取dao的代理对象
        userDao = this.sqlSession.getMapper(IUserDao.class);
    }
    @After
    public void destory() throws IOException {
        //提交事务
        //sqlSession.commit();//这里就不要再提交事务了
        //释放资源
        sqlSession.close();
        resourceAsStream.close();
    }
    //测试查询所有
    @Test
    public void testFindAll(){
        List<User> users = userDao.findAll();
        for (User user : users) {
            System.out.println("------这是每个用户到角色的信息------");
            System.out.println(user);
            System.out.println(user.getRoles());
        }
    }
}

课程简介: 历经半个多月的时间,Debug亲自撸的 “企业员工角色权限管理平台” 终于完成了。正如字面意思,本课程讲解的是一个真正意义上的、企业级的项目实战,主要介绍了企业级应用系统中后端应用权限的管理,其中主要涵盖了六大核心业务模块、十几张数据库。 其中的核心业务模块主要包括用户模块、部门模块、岗位模块、角色模块、菜单模块和系统日志模块;与此同时,Debug还亲自撸了额外的附属模块,包括字典管理模块、商品分类模块以及考勤管理模块等等,主要是为了更好地巩固相应的技术栈以及企业应用系统业务模块的开发流程! 核心技术栈列: 值得介绍的是,本课程在技术栈层面涵盖了前端和后端的大部分常用技术,包括Spring Boot、Spring MVC、MybatisMybatis-Plus、Shiro(身份认证与资源授权跟会话等等)、Spring AOP、防止XSS攻击、防止SQL注入攻击、过滤器Filter、验证码Kaptcha、热部署插件Devtools、POI、Vue、LayUI、ElementUI、JQuery、HTML、Bootstrap、Freemarker、一键打包部署运行工具Wagon等等,如下图所示: 课程内容与收益: 总的来说,本课程是一门具有很强实践性质的“项目实战”课程,即“企业应用员工角色权限管理平台”,主要介绍了当前企业级应用系统中员工、部门、岗位、角色、权限、菜单以及其他实体模块的管理;其中,还重点讲解了如何基于Shiro的资源授权实现员工-角色-操作权限、员工-角色-数据权限的管理;在课程的最后,还介绍了如何实现一键打包上传部署运行项目等等。如下图所示为本权限管理平台的数据库设计图: 以下为项目整体的运行效果截图: 值得一提的是,在本课程中,Debug也向各位小伙伴介绍了如何在企业级应用系统业务模块的开发中,前端到后端再到数据库,最后再到服务器的上线部署运行等流程,如下图所示:
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页