Mybatis高级

devtools/2024/9/25 21:21:34/


1. Mybatis多表查询概念

​    在学习多表查询的之前,我们要先明确多表的关系都有哪些,如何划分。

1.1 多表关系的划分

一对一
        一对一的关系是两张表之间 A表的一条数据只能对应B表的一条数据。比如 订单表和用户表         一个订单只能属于一个用户,所以是一对一的关系。
一对多
        一对多的关系是两张表之间 A表的一条数据可以对应B表的多条数据。比如用户表和订单表,          一个用户可以拥有多个订单,所以是一对多的关系
多对多
       多对多的关系是两张表之前 A表的一条数据可以对应B表的多条数据,反之,B表的数据也可         以对应A表的多条数据,但这只是在业务理解层面的意义。实际上两张表如果是多对多的关            系,那么这两张表不能直接关联,需要一张中间表来联系起来。

划分表关系的技巧

1. 先从业务层面理解2张表的关系,然后看需求要查询的主表是哪张表

2. 比如订单表和用户表,如果从订单的表的角度来看,那么就是一对一,如果从用户的角度来看,那么就是一对多

3. 看需求:如果需求是查询订单表以及关联查询该订单的所属用户,那么就是一对一,如果是查询用户以及关联查询该用户的订单,那么就是一对多

4. 在写之前一定要明确表关系!不然怎么写都是错的。

5. 多表关系大多数都是通过id字段来关联的

6. 其实多对多的需求本质上就是双向的一对多

   ​

1.2表关系划分的练习

1. 文章表和评论表
            从文章表的角度来看 是1对多
            从评论表的角度来看 是1对1

2. 学生表和班级表
            从学生表的角度来看 是1对1
            从班级表点的角度来看 是1对多

3. 用户表和角色表
            从用户表的角度来看 是1对多
            从角色表的角度来看 是1对多
            表的关系是 多对多

4. 用户表和身份证表
            从用户表的角度来看 是1对1
            从身份证表的角度来看 是1对1
            表的关系是1对1
5. 桌子表和椅子表
            从桌子的角度来看 1对多
            从椅子的角度来看 1对1

2. Mybatis多表查询

​    Mybatis多表查询,只要编写好Sql语句,设置好查询结果的映射就非常简单了

2.1 一对一查询

​    已知有用户表和订单表 表结构如下

​   

​    需求:

         查询出订单信息,并且查询出每个订单信息所属的用户信息

    分析表关系

         从订单表角度来看,那就是一对一
         订单表的uid字段 代表 所属用户的id 和用户表的id关联

2.1.1 查询的sql语句

select * from orders o ,user u where o.uid = u.id

2.1.2 创建实体类

        在订单类中声明一个用户对象

public class Order {private int id;private Date ordertime;private double total;//代表当前订单从属于哪一个客户private User user;//省略set get。。。。
}public class User {private int id;private String username;private String password;private String birthday;//省略set

2.1.3 创建IOrderMapper接口

public interface OrderMapper {List<Order> findAll();
}

 2.1.4 创建OrderMapper.xml文件

​    方式一

<mapper namespace="com.demo.mapper.OrderMapper"><resultMap id="orderMap" type="com.demo.bean.Orders"><result column="username" property="user.username"></result><result column="password" property="user.password"></result><result column="birthday" property="user.birthday"></result></resultMap><select id="findAll" resultMap="orderMap">select * from orders o,user u where o.uid=u.id</select>
</mapper>

    方式二

<resultMap id="orderMap" type="com.demo.bean.Orders"><result property="id" column="id"></result><result property="ordertime" column="ordertime"></result><result property="total" column="total"></result><result property="uid" column="uid"></result><association property="user" javaType="com.demo.bean.User"><result property="id" column="id"></result><result column="username" property="username"></result><result column="password" property="password"></result><result column="birthday" property="birthday"></result></association></resultMap>

resutMap知识点:
作用:
         1. 当表中的列名和类中的属性名 不一致的时候 可以手动的修改映射
         2. 做多表查询的时候 给表中没有的字段 但是类中有的属性赋值
  一对一:
 2种方式映射
         1. <resultMap> + <association>
         2. 直接用<resultMap>种的<result>
         3. 强烈推荐使用第一种

2.1.5 测试结果

编写单元测试 通过mapper调用方法 查看结果

//查询全部订单信息 包含用户@Testpublic void findAllOrders(){List<Orders> ordersList = mapper.findAllOrder();//遍历结果for (Orders orders : ordersList) {System.out.println(orders);}}

2.2 一对多查询

 同样还是上面的订单表和用户表 

 需求:

         查询每个用户以及该用户关联的订单列表

分析表关系

         从用户表角度来看,那就是一对多
         用户表的主键id和订单表的uid进行关联

2.2.1 查询的Sql语句

select *,o.id oid from user u left join orders o on u.id=o.uid;

一对多的查询 其实可以和一对一的查询同样的sql 但是不建议。建议使用左连接来查询。

2.2.2 修改实体类

​          在User实体类中声明一个代表订单的集合

public class User {private Integer id;private String username;private String password;private String birthday;private List<Orders> ordersList;
}

2.2.3 创建IUserMapper接口

public interface IUserMapper {List<User> findAll();
}

2.2.4 创建UserMapper.xml文件

<mapper namespace="com.demo.mapper.IUserMapper"><resultMap id="userMap" type="com.zrrd.bean.User"><result column="id" property="id"></result><result column="username" property="username"></result><result column="password" property="password"></result><result column="birthday" property="birthday"></result><collection property="ordersList" ofType="com.demo.bean.Orders"><result column="uid" property="uid"></result><result column="ordertime" property="ordertime"></result><result column="total" property="total"></result></collection></resultMap><select id="findAll" resultMap="userMap">select * from user u left join orders o on u.id=o.uid</select>
</mapper>

2.2.5 测试结果

编写单元测试 通过mapper调用方法 查看结果

//查询全部订单信息 包含用户@Testpublic void findAllOrders(){List<User> userList = mapper.findAllUser();for (User user : userList) {System.out.println("当前用户:"+user.getUsername());System.out.println("关联订单:"+user.getOrdersList());System.out.println("================================");}}

小总结:
     1对1和1对多的写法区别:
         1. 一对一用<resultMap> + <association>  用javaType
         2. 一对多用<resultMap> + <collection> 用ofType

2.3 多对多查询

完成学生表和课程表的需求

         学生表(id name age sex )
         课程表(id name hour)

多对多表之间不能有直接关联 要创建中间表

         中间表(id sid cid)

 

需求:

         查询每个学生的信息以及学生学习了哪些课程
         查询每个课程的信息以及课程被哪些学生学习了

表关系分析:

         其实多对多直接可以拆分成一对多
         从学生表的角度查询 一对多
         从课程表的角度查询 一对多

2.3.1 查询的sql语句

select * from student s left join stu_cour sc on sc.sid = s.id inner join course c on sc.cid = c.id

参照一对多的写法 完成功能

步骤:

        1. 创建实体类和接口
        2. 编写核心配置文件MapperConfig
        3. 分别创建Mapper映射文件并编写返回的resultMap
        4. 测试结果

实操:

1. 创建实体类

public class Student {private Integer id;private String name;private Integer age;private String sex;//关联的课程集合private List<Course> courseList;省略 get和set方法
}
public class Course {private Integer id;private String name;private Integer hour;//关联的学生的集合private List<Student> studentList;省略get和set方法
}

创建接口

public interface StudentMapper {//查询全部学生 并且查询出学生关联的课程集合List<Student> findAllStudent();
}
public interface CourseMapper {//查询全部学生 并且查询出学生关联的课程集合List<Course> findAllCouerse();
}

关联查询情况: 

  2. 编写核心配置文件MapperConfig

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--加载其他的配置文件--><properties resource="jdbcConfig.properties"></properties><!--给实体类起别名--><typeAliases><typeAlias type="com.demo.bean.Student" alias="s"></typeAlias><typeAlias type="com.demo.bean.Course" alias="c"></typeAlias></typeAliases><!--必须要放这里不然报错--><plugins><!-- 注意:分页助手的插件  配置在通用馆mapper之前 --><plugin interceptor="com.github.pagehelper.PageHelper"><!-- 指定方言 --><property name="dialect" value="mysql"/></plugin></plugins><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><mappers><mapper resource="StudentMapper.xml"/><mapper resource="CourseMapper.xml"/></mappers>
</configuration>

3. 分别创建Mapper映射文件并编写返回的resultMap

<mapper namespace="com.demo.mapper.StudentMapper"><resultMap id="studenrtMap" type="s"><result column="id" property="id"></result><result column="name" property="name"></result><result column="age" property="age"></result><result column="sex" property="sex"></result><collection property="courseList" ofType="c"><result column="cid" property="id"></result><result column="cname" property="name"></result><result column="chour" property="hour"></result></collection></resultMap><!--查询全部学生   需要起别名,因为两个表id都是这个属性名,name也是相同属性名,容易识别不出来--><select id="findAllStudent" resultMap="studenrtMap">select s.*,c.id cid,c.name cname,c.hour chour from student s left join stu_cour sc on s.id = sc.sid inner joincourse c on c.id = sc.cid;</select></mapper>
<mapper namespace="com.demo.mapper.CourseMapper"><resultMap id="courseMap" type="c"><result column="id" property="id"></result><result column="name" property="name"></result><result column="hour" property="hour"></result><collection property="studentList" ofType="s"><result column="sid" property="id"></result><result column="sname" property="name"></result><result column="sage" property="age"></result><result column="ssex" property="sex"></result></collection></resultMap><select id="findAllCouerse" resultMap="courseMap">select c.*,s.id sid,s.name sname,s.age sage,s.sex ssexfrom course cleft join stu_cour sc on c.id = sc.cidinner join student son s.id = sc.sid;</select></mapper>

4. 测试结果

public class StudentTest {SqlSession sqlSession;StudentMapper mapper;@Beforepublic void init() throws IOException {//加载核心配置文件InputStream stream = Resources.getResourceAsStream("MapperConfig.xml");//创建Sqlseesion工厂对象SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(stream);//通过工厂对象 获取Sqlseesion对象sqlSession = ssf.openSession();//获取Mapper对象mapper = sqlSession.getMapper(StudentMapper.class);}//查询全部订单信息 包含用户@Testpublic void findAllOrders(){List<Student> students = mapper.findAllStudent();for (Student student : students) {System.out.println("学生姓名:"+student.getName());System.out.print("学习课程:");List<Course> courseList = student.getCourseList();for (Course course : courseList) {System.out.print(course.getName()+"\t");}System.out.println();}}@Afterpublic void close(){//提交事务sqlSession.commit();//关闭资源sqlSession.close();}
}
public class CourseTest {SqlSession sqlSession;CourseMapper mapper;@Beforepublic void init() throws IOException {//加载核心配置文件InputStream stream = Resources.getResourceAsStream("MapperConfig.xml");//创建Sqlseesion工厂对象SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(stream);//通过工厂对象 获取Sqlseesion对象sqlSession = ssf.openSession();//获取Mapper对象mapper = sqlSession.getMapper(CourseMapper.class);}//查询全部订单信息 包含用户@Testpublic void findAllOrders(){List<Course> couerseList = mapper.findAllCouerse();for (Course course : couerseList) {System.out.println("课程名称:"+course.getName());System.out.println("课程学生:"+course.getStudentList());}}@Afterpublic void close(){//提交事务sqlSession.commit();//关闭资源sqlSession.close();}
}


http://www.ppmy.cn/devtools/35068.html

相关文章

《亲密关系》阅读笔记

0 引言 由于博主的情感关系较少&#xff0c;社交也很少&#xff0c;最近遇到一个女孩子&#xff0c;但是发现自己完全不了解女生&#xff0c;对人与人之间的亲密关系了解太少&#xff0c;对人性的理解太过浅显。因此&#xff0c;开始涉略心理学方面书籍&#xff0c;同时现实中…

04 深入浅出JVM

本课时的主题是 JVM 原理。JVM 是 Java 程序运行基础&#xff0c;面试时一定会遇到 JVM 相关的题。本课时会先对面试中 JVM 的考察点进行汇总介绍。然后对 JVM 内存模型、Java 的类加载机制、常用的 GC 算法这三个知识点进行详细讲解。最后汇总 JVM 考察点和加分项&#xff0c;…

MySQL性能调优全面指南

MySQL作为广泛使用的开源关系型数据库管理系统&#xff0c;其性能调优对于确保数据库高效、稳定运行至关重要。本文将介绍MySQL性能调优的多个方面&#xff0c;包括查询性能调优策略、服务器性能调优&#xff08;内存、CPU、I/O等&#xff09;&#xff0c;以及监控工具如Percon…

getchar和putchar函数详解

getchar和putchar函数详解 1.getchar函数1.1函数概述1.2函数返回值1.3函数注意事项1.4函数的使用 2.putchar函数2.1函数概述2.2函数返回值2.3函数使用实例 1.getchar函数 1.1函数概述 从一个流中读取一个字符&#xff0c;或者从标准输入中获得一个字符 函数原型&#xff1a; …

秋招后端开发面试题 - JVM垃圾回收器

目录 JVM垃圾回收器前言面试题常见的垃圾回收器有哪些&#xff1f;CMS 收集器&#xff1f;G1 收集器有了 CMS&#xff0c;为什么还要引入 G1&#xff1f;垃圾收集器应该如何选择&#xff1f; JVM垃圾回收器 前言 已经找到工作了&#xff0c;分享秋招时的笔记。祝大家都能顺利…

图像处理-图像平滑

图像平滑 前言一、概念介绍1.1 图像的平滑1.2 图像中噪声的分类1.3 MATLAB的添加噪音代码 二、空间域平滑滤波2.1 均值滤波2.2 原理计算 总结 前言 在图像的获取、传输和存储过程常常收到各种噪声的干扰和影响&#xff0c;使得图像的质量下降&#xff0c;为了获得高质量的数字…

第08章 IP分类编址和无分类编址

8.1 本章目标 了解IP地址的用途和种类了解分类编址和无分类编址区别掌握IP地址、子网掩码、网关概念及使用掌握子网划分及超网划分方法掌握无分类编址的改变和使用 8.2 IP地址的用途和种类 分类编址&#xff1a;造成地址的浪费&#xff0c;以及地址不够用&#xff1b;无分类编…

基于SpringBoot的教务管理系统 - 源码免费(私信领取)

1. 研究目的 本项目旨在设计并实现一个基于Spring Boot的教务管理系统&#xff0c;以提升学校教务管理效率&#xff0c;优化教学资源配置&#xff0c;提高教学质量&#xff0c;满足学生、教师和管理人员的需求。 2. 研究要求 a. 需求分析 通过调研学校教务管理流程和现有系…