09【MyBatis多表关联查询】
创始人
2024-03-01 21:38:11
0

文章目录

  • 三、MyBatis多表关联查询
    • 3.1 表的关系
    • 3.2 一对一查询
      • 3.2.1 搭建环境
      • 3.2.2 需求分析
      • 3.2.3 dao接口
      • 3.2.3 mapper.xml
      • 3.2.4 测试
      • 3.2.5 配置MyBatis一对一关系
        • 1)传统映射:
        • 2)使用`association`标签映射
    • 3.3 一对多查询
      • 3.3.1 需求分析
      • 3.3.2 dao接口
      • 3.3.3 mapper.xml
      • 3.3.4 测试
    • 3.4 多对多关联
      • 3.4.1 需求分析
      • 3.4.2 建立表
      • 3.4.3 实体类
      • 3.4.4 dao
      • 3.4.5 实现User到Role的多对多
      • 3.4.6 实现Role到User的多对多

三、MyBatis多表关联查询

3.1 表的关系

表关系有如下几种

  • 一对多

  • 多对一(MyBatis就是一对一)

  • 一对一

  • 多对多(一对多+一对多)

  • 举例一:

一对多:一个部门下有多个员工

部门与员工的关系:一对多

多对一:多个员工属于一个部门。

员工与部门的关系:多对一

单独拿出一个员工来说,他都只能属于一个部门。所以,在mybatis中把多对一看成了一对一

  • 举例二:

一个用户对应一个身份证号码。那么用户与身份证号码关系就是一对一

  • 举例三:

多对多:一个老师教多个学生。

老师与学生的关系:一对多

一个学生有多个老师。

学生与老师:一对多,这种双向一对多,就是多对多。

3.2 一对一查询

3.2.1 搭建环境

  • SQL脚本:
drop table if exists dept;CREATE TABLE `dept`  (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '部门名称',`location` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '部门地址',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 ;INSERT INTO `dept` VALUES (1, '研发部', '中国台湾');
INSERT INTO `dept` VALUES (2, '市场部', '中国香港');
INSERT INTO `dept` VALUES (3, '行政部', '中国钓鱼岛');
INSERT INTO `dept` VALUES (4, '销售部', '中国江西');drop table if exists emp;
CREATE TABLE `emp`  (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '员工姓名',`age` int(11) NULL DEFAULT NULL COMMENT '员工年龄',`addr` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '籍贯',`salary` decimal(10, 2) NULL DEFAULT NULL COMMENT '薪资',`dept_id` int(11) NULL DEFAULT NULL COMMENT '部门id',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;INSERT INTO `emp` VALUES (1, '张三', 20, '广西来宾', 7600.00, 1);
INSERT INTO `emp` VALUES (2, '李四', 22, '浙江绍兴', 6800.00, 4);
INSERT INTO `emp` VALUES (3, '小明', 25, '广东云浮', 6600.00, 2);
INSERT INTO `emp` VALUES (4, '小红', 23, '河南信阳', 7000.00, 3);
INSERT INTO `emp` VALUES (5, '张明', 25, '山东临沂', 8000.00, 1);

Emp实体类:

package com.dfbz.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @author lscl* @version 1.0* @intro:*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Emp {private Integer id;private String name;private Integer age;private String addr;private Double salary;// 一个员工属于一个部门private Dept dept;
}

Dept实体类:

package com.dfbz.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;/*** @author lscl* @version 1.0* @intro:*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept {private Integer id;private String name;private String location;// 一个部门下有多个员工private List empList;
}

3.2.2 需求分析

表关系:

在这里插入图片描述

我们以前的理解是,部门和员工的关系是一对多,员工和部门的关系是多对一;

但是我们拿出单个员工来说,一个员工只属于一个部门,因此在MyBatis中,多对一的关系简化成了一对一;

案例需求:查询所有员工信息,关联查询所属部门信息;在查询过程中,即使有的员工还没有部门也需要查询这个员工的信息,此时在查询过程中,员工表应该是主表;

  • 分析SQL语句:
select e.*,d.* from emp e left join dept d on e.dept_id=d.id

3.2.3 dao接口

  • EmpDao:
public interface EmpDao {List findAll();
}

3.2.3 mapper.xml




3.2.4 测试

package com.dfbz.test;import com.dfbz.dao.EmpDao;
import com.dfbz.entity.Emp;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;
import java.util.List;/*** @author lscl* @version 1.0* @intro:*/
public class Demo01 {private SqlSessionFactory factory;private SqlSession session;private EmpDao empDao;@Beforepublic void before() throws IOException {InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();factory = builder.build(is);session = factory.openSession(true);empDao=session.getMapper(EmpDao.class);}@Afterpublic void after() throws IOException {session.close();}@Testpublic void test1() {List empList = empDao.findAll();System.out.println(empList);}
}

在这里插入图片描述

3.2.5 配置MyBatis一对一关系

  • 更改SQL语句:
SELECTe.id eId,e.NAME empName,e.age,e.addr,e.salary,e.dept_id deptId,d.NAME deptName,d.location 
FROMemp eleft JOIN dept d ON e.dept_id = d.id

1)传统映射:




2)使用association标签映射



Tips:映射多表关联的结果集时,即使查询出来的列名与属性名一致,也要建立手动映射关系,否则将会导致查询的值无法映射到对应的列;

3.3 一对多查询

3.3.1 需求分析

需求:查询部门信息以及部门下面所属员工信息

分析:部门和员工的信息为一对多关系,并且查询过程中,如果有的部门没有员工,此时也需要将部门信息查询出来,因此在查询中,部门表应该是主表;

  • 分析SQL语句:
SELECTe.id eId,e.NAME empName,e.addr,e.salary,e.dept_id deptId,d.NAME deptName,d.location 
FROMemp eright JOIN dept d ON e.dept_id = d.id

3.3.2 dao接口

List findAll();

3.3.3 mapper.xml




3.3.4 测试

@Test
public void test2() {List deptList = deptDao.findAll();System.out.println(deptList);
}

3.4 多对多关联

3.4.1 需求分析

示例:用户和角色

​ 一个用户可以有多个角色

​ 一个角色可以赋予多个用户

步骤:

​ 1、建立两张表:用户表,角色表让用户表和角色表具有多对多的关系。需要使用中间表,中间表需要外键引用用户表、角色表。

​ 2、建立两个实体类:用户实体类和角色实体类让用户和角色的实体类能体现出来多对多的关系各自包含对方一个集合引用

​ 3、建立两个配置文件用户的配置文件角色的配置文件

​ 4、实现配置:

​ 当我们查询用户时,可以同时得到用户所包含的角色信息

​ 当我们查询角色时,可以同时得到角色的所赋予的用户信息

3.4.2 建立表

DROP TABLE IF EXISTS `role`;
CREATE TABLE `role`  (`id` int(11) NOT NULL,`role_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`role_desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE,INDEX `id`(`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;INSERT INTO `role` VALUES (1, '保洁', '扫地');
INSERT INTO `role` VALUES (2, '厨师', '做饭');
INSERT INTO `role` VALUES (3, '保安', '维护治安');DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (`id` int(11) NOT NULL AUTO_INCREMENT,`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci 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 = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;INSERT INTO `user` VALUES (1, '张三', '1999-02-04', '男', '佛山');
INSERT INTO `user` VALUES (2, '李四', '1998-01-15', '女', '湛江');DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role`  (`uid` int(11) NOT NULL COMMENT '用户编号',`rid` int(11) NOT NULL COMMENT '角色编号',PRIMARY KEY (`uid`, `rid`) USING BTREE,INDEX `FK_Reference_10`(`rid`) USING BTREE,CONSTRAINT `FK_Reference_10` FOREIGN KEY (`rid`) REFERENCES `role` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,CONSTRAINT `FK_Reference_9` FOREIGN KEY (`uid`) REFERENCES `user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;INSERT INTO `user_role` VALUES (1, 1);
INSERT INTO `user_role` VALUES (2, 1);
INSERT INTO `user_role` VALUES (1, 2);
INSERT INTO `user_role` VALUES (2, 2);
INSERT INTO `user_role` VALUES (2, 3);

3.4.3 实体类

  • User:
package com.dfbz.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;
import java.util.List;/*** @author lscl* @version 1.0* @intro:*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private int  id;private String username;private Date birthday;private String sex;private String address;// 一个用户,有多个角色private List roles;
}
  • Role:
package com.dfbz.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;/*** @author lscl* @version 1.0* @intro:*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Role {private int  roleId;private String roleName;private String roleDesc;// 一个角色,对应多个用户private List users;
}

3.4.4 dao

  • UserDao:
public interface UserDao {List findAll();
}
  • RoleDao:
public interface RoleDao {List findAll();
}

3.4.5 实现User到Role的多对多

  • SQL语句:
SELECTu.*,r.id rid,r.role_name,r.role_desc 
FROMUSER uLEFT JOIN user_role ur ON u.id = ur.uidLEFT JOIN role r ON r.id = ur.rid
  • mapper.xml:



测试类:

@Test
public void test3() {List userList = userDao.findAll();System.out.println(userList);
}

3.4.6 实现Role到User的多对多

  • SQL语句:
SELECTr.*,u.id uid,u.username,u.birthday,u.sex,u.address 
FROMrole rLEFT JOIN user_role ur ON r.id = ur.ridLEFT JOIN USER u ON u.id = ur.uid
  • mapper.xml:




  • 测试类:
@Test
public void test4() {List roleList = roleDao.findAll();System.out.println(roleList);
}

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
Azure构建流程(Power... 这可能是由于配置错误导致的问题。请检查构建流程任务中的“发布构建制品”步骤,确保正确配置了“Arti...