Mybatis入门:4(多表查询操作)

多表查询操作

Mybatis的多表操作

表之间的关系有几种:一对多、一对一、多对一、多对多
举例:
用户和订单就是一对多——一个用户可以下多个订单
订单和用户就是多对一——多个订单属于同一个用户

人和身份证号就是一对一
一个人只能有一个身份证号
一个身份证号只能属于一个人

老师和学生之间就是多对多
一个学生可以被多个老师教过
一个老师可以教多个学生
特例:
如果拿出每-一个订单,他都只能属于一个用户。
所以Mybatis就把多对一看成了一对一。

我们首先建立了两个新的表格方便操作,如下:
account表格:
在这里插入图片描述
user表格:
在这里插入图片描述

mybatis中的多表查询:

示例:用户和账户
一个用户可以有多个账户
一个账户只能属于一个用户(多个账户也可以属于同一个用户)

步骤:

  1. 建立两张表:用户表,账户表
    让用户表和账户表之间具备一对多的关系:需要使用外键在账户表中添加
    MySQL外键的作用:主要目的是控制存储在外键表中的数据。使两张表形成关联,外键只能引用外表中列的值!
    当创建或更改表时可通过定义 FOREIGN KEY 约束来创建外键
  2. 建立两个实体类:用户实体类和账户实体类
    让用户和账户的实体类能体现出啦一-对多的关系
  3. 建立两个配置文件
    用户的配置文件
    账户的配置文件
  4. 实现配置:
    当我们查询用户时,可以同时得到用户下所包含的账户信息
    当我们查询账户时,可以同时得到账户的所属用户信息

一对一操作

一.通过写Account子类的方式查询(不太常用)

    <!--查询所有账户同时包含用户名和地址信息-->
    <select id="findAllAccount" resultType="accountuser">
        select a.*,u.username,u.address from account a , user u
        where u.id = a.uid;
    </select>

Account类

package com.domain;

import java.io.Serializable;

public class Account implements Serializable {
    private Integer id;
    private Integer uid;    //外键
    private Double money;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", uid=" + uid +
                ", money=" + money +
                '}';
    }
}

AccountUser类(Account子类)

package com.domain;

public class AccountUser extends Account {		//继承了Account类

    private String username;
    private String address;

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

    @Override
    public String toString() {
        return super.toString()+"        AccountUser{" +        //super.toString()调用父类的toString()方法
                "username='" + username + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

User类

package com.domain;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

public class User implements Serializable {
    private Integer id;
    private String username;
    private String address;
    private String sex;
    private Date birthday;

    //一对多关系映射:主表实体应该包含从表实体的集合引用
    private List<Account> accounts;

    public List<Account> getAccounts() {
        return accounts;
    }

    public void setAccounts(List<Account> accounts) {
        this.accounts = accounts;
    }

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

测试类

    /**
     * 测试查询所有账户,同时包含用户名称和地址
     */
    @Test
    public void testFindAllAccountUser(){
        List<AccountUser> aus = accountDao.findAllAccount();
        for(AccountUser au : aus){
            System.out.println(au);
        }
    }

结果:
在这里插入图片描述
大概思路
1.测试类findAllAccount()方法返回AccountUser集合,输出集合
2.执行findAllAccount()方法,转入xml配置文件,执行sql语句查询
3.返回AccountUser类型的查询结果,执行子类的toString方法
4.super.toString()执行父类的toString方法

二.通过建立实体类关系的方式(常用)

    <!-- 定义封装account和user的resultMap -->
    <!-- 一对一的关系映射:配置封装user的内容-->
    <resultMap id="accountUserMap" type="account">
        <id property="id" column="aid"/>    <!--此处的aid为表中id的别名-->
        <result property="uid" column="uid"/>
        <result property="money" column="money"/>
        <association property="user" javaType="user">   <!--由于使用了别名,所以直接写user就行了-->
            <!--为了防止我们开发出错,在没有特别要求的情况下,column名可以完全和property名称一致,否则当我们没有对应上的时候,数据库匹配不到-->
            <id property="id" column="id"/>
            <result column="username" property="username"/>
            <result column="address" property="address"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
        </association>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="accountUserMap">
        <!-- as可理解为:用作、当成,作用;一般是重命名列名或者表名。(主要为了查询方便)-->
        select u.*,a.id as aid,a.uid,a.money from account a,user u where u.id = a.uid;
    </select>

association标签的作用:就是将另一张表的字段关联过来 然后一起映射到实体类

Account类(在之前的基础上改造)

package com.domain;

import java.io.Serializable;

public class Account implements Serializable {
    private Integer id;
    private Integer uid;    //外键
    private Double money;

    //从表实体应该包含一个主表实体的对象引用
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public Double getMoney() {
        return money;
    }

    public void setMoney(Double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", uid=" + uid +
                ", money=" + money +
                '}';
    }
}

User类(跟上面一样,不变)

测试类

    @Test
    public void testFindAll(){
        List<Account> accounts = accountDao.findAll();
        for(Account account : accounts){
            System.out.println("--------每个account的信息------------");
            System.out.println(account);
            System.out.println(account.getUser());//其实可以直接在Account类那里将toString()方法重写一遍,加上user,就不用调用getUser()方法了
        }
    }

结果:
在这里插入图片描述

一对多操作

一个用户存在多个账户的情况

    <!-- 定义User的resultMap-->
    <!--一对多查询-->
    <resultMap id="userAccountMap" type="user">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="address" column="address"/>
        <result property="sex" column="sex"/>
        <result property="birthday" column="birthday"/>
        <!-- 配置user对象中accounts集合的映射 -->
        <collection property="accounts" ofType="account">   <!--ofType指的是集合accounts的类型-->
            <id column="aid" property="id"/>    <!--aid为列别名,起别名是因为主子表都有该字段-->
            <result column="uid" property="uid"/>
            <result column="money" property="money"/>
        </collection>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="userAccountMap">
        <!-- left join(左联接)返回包括左表(user)中的所有记录和右表(account)中联结字段相等(即u.id = a.uid)的记录,即返回user表和满足u.id = a.uid条件的account表 -->
        select * from user u left outer join account a on u.id = a.uid
    </select>

注:

  • left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录
  • right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录
  • inner join(等值连接) 只返回两个表中联结字段相等的行
  • outer join(外连接) 可分为左外连接left outer join和右外连接right outer join

上面的left join(左联结)表示返回所有user表和满足u.id = a.uid条件的account表内容

User类(添加上了Account集合属性)

package com.domain;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

public class User implements Serializable {
    private Integer id;
    private String username;
    private String address;
    private String sex;
    private Date birthday;

    //一对多关系映射:主表实体应该包含从表实体的集合引用
    private List<Account> accounts;

    public List<Account> getAccounts() {
        return accounts;
    }

    public void setAccounts(List<Account> accounts) {
        this.accounts = accounts;
    }

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

测试类

@Test
    public void testFindAll(){
        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println("-----每个用户的信息------");
            System.out.println(user);
            System.out.println(user.getAccounts());
        }
    }

结果:
在这里插入图片描述

多对多操作

示例:用户和角色
一个用户可以有多个角色
一个角色可以赋予多个用户

步骤:

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

1.查询角色获取角色下所包含的用户信息

    <!--定义role表的resultMap-->
    <resultMap id="roleMap" type="role">
        <id property="roleId" column="rid"/>
        <result property="roleName" column="role_name"/>
        <result property="roleDesc" column="role_desc"/>
        <collection property="users" ofType="user">
            <id column="id" property="id"/>
            <result column="username" property="username"/>
            <result column="address" property="address"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
        </collection>
    </resultMap>

    <!--查询所有-->
    <select id="findAll" resultMap="roleMap">
        select u.*,r.id as rid,r.role_name,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>

多对多查询的精华基本都在sql语句的书写上面了…

Role类

package com.domain;

import java.io.Serializable;
import java.util.List;

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 + '\'' +
                '}';
    }
}

User类

package com.domain;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {
    private Integer id;
    private String username;
    private String address;
    private String sex;
    private Date birthday;

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

测试类

    @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());
        }
    }

结果:
在这里插入图片描述

2.查询用户获取用户所包含的角色信息

    <!--多对多查询-->
    <resultMap id="userMap" type="user">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="address" column="address"/>
        <result property="sex" column="sex"/>
        <result property="birthday" column="birthday"/>
        <!--配置角色集合的映射-->
        <collection property="roles" ofType="role">
            <id property="roleId" column="rid"/>
            <result property="roleName" column="role_name"/>
            <result property="roleDesc" column="role_desc"/>
        </collection>
    </resultMap>

    <!-- 查询所有 -->
    <select id="findAll" resultMap="userMap">
        select u.*,r.id as rid,r.role_name,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>

通过观察我们可以发现UserDao的配置文件中的sql查询语句刚好是和上面查询角色时的反过来的。

Role类不变

User类(加上Role类型的集合属性)

package com.domain;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

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

测试类

    @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());
        }
    }
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符 “速评一下”
课程简介: 历经半个多月的时间,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 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页