Mybatis高级


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.xdnf.cn/news/1410435.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Vue阶段练习:组件拆分

页面开发思路 分析页面&#xff0c;按模块拆分组件&#xff0c;搭架子&#xff08;局部或全局注册&#xff09;根据设计图&#xff0c;编写html结构css样式拆分封装通用小组件&#xff08;局部或全局注册&#xff09;将来通过js动态渲染实现功能 BaseBrandItem.vue <templ…

408数据结构-二叉树的遍历 自学知识点整理

前置知识&#xff1a;二叉树的概念、性质与存储结构 二叉树的遍历 二叉树的遍历是指按某条搜索路径访问树中每个结点&#xff0c;使得每个结点均被访问一次&#xff0c;而且仅被访问一次。 二叉树的递归特性: ①要么是棵空二叉树&#xff1b; ②要么就是由“根节点左子树右子树…

渗透之sql注入联合查询的注入

sql注入产生的原因&#xff1a; 由于程序过滤不严谨&#xff0c;导致用户有一些异常输入&#xff0c;最终触发数据库的查询。所以会出现sql注入这个问题。有些恶意的人就会利用这些信息导致数据库泄露。 注意&#xff1a;一般我们存在注入点我们会查询管理员的账号和密码&#…

Q1季度家用健身器械行业线上市场销售数据分析

自疫情开始&#xff0c;全民健身的浪潮就持续至今。然而&#xff0c;水能载舟亦能覆舟&#xff0c;一边是不断释放的健身需求&#xff0c;另一边却是无数健身房的闭店潮。 越来越多人倾向于选择家用健身器械来运动或是直接选择无器械的健身运动&#xff0c;比如各类健身操。而…

【跟马少平老师学AI】-【神经网络是怎么实现的】(六)过拟合问题

一句话归纳&#xff1a; 1&#xff09;过拟合问题&#xff1a; 图中的点为样本直线欠拟合曲线2过拟合 2&#xff09;迭代次数与拟合情况&#xff1a; 训练次数过多可能导致过拟合。 3&#xff09;正则化项法弱化过拟后问题&#xff1a; 加正则项&#xff0c;在最小化损失函数时…

电脑自带dll修复在哪里,使用dll修复工具解决dll问题

在我们日常与电脑相伴的工作与学习过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中最常见的就是“无法找到.dll”或“找不到.dll文件”。这种情况通常是由于dll文件丢失或损坏导致的。dll文件是动态链接库文件&#xff0c;它包含了许多程序运行所需的函数和资源…

场景文本检测识别学习 day06(Vi-Transformer论文精读、MAE论文阅读)

Vi-Transformer论文精读 在NLP领域&#xff0c;基于注意力的Transformer模型使用的非常广泛&#xff0c;但是在计算机视觉领域&#xff0c;注意力更多是和CNN一起使用&#xff0c;或者是单纯将CNN的卷积替换成注意力&#xff0c;但是整体的CNN 架构没有发生改变VIT说明&#x…

B树:原理、操作及应用

B树&#xff1a;原理、操作及应用 一、引言二、B树概述1. 定义与性质2. B树与磁盘I/O 三、B树的基本操作1. 搜索&#xff08;B-TREE-SEARCH&#xff09;2. 插入&#xff08;B-TREE-INSERT&#xff09;3. 删除&#xff08;B-TREE-DELETE&#xff09; 四、B树的C代码实现示例五、…

一文全面了解 wxWidgets 布局器(Sizers)

目录 Sizers背后的理念 共同特征 最小大小 边框 对齐方式 伸缩因子 使用 Sizer 隐藏控件 wxBoxSizer wxStaticBoxSizer wxGridSizer wxFlexGridSizer 布局器&#xff08;Sizers&#xff09;&#xff0c;由wxWidgets类层次结构中的wxSizer类及其派生类表示&#xff0…

基于 Wireshark 分析 IP 协议

一、IP 协议 IP&#xff08;Internet Protocol&#xff09;协议是一种网络层协议&#xff0c;它用于在计算机网络中实现数据包的传输和路由。 IP协议的主要功能有&#xff1a; 1. 数据报格式&#xff1a;IP协议将待传输的数据分割成一个个数据包&#xff0c;每个数据包包含有…

android init进程启动流程

Android系统完整的启动流程 android 系统架构图 init进程的启动流程 init进程启动服务的顺序 bool Service::Start() {// Starting a service removes it from the disabled or reset state and// immediately takes it out of the restarting state if it was in there.flags_…

JAVA面试专题-微服务篇

Spring cloud Spring Cloud 5大组件有哪些 注册中心/配置中心&#xff1a;nacos 负载均衡&#xff1a;Ribbon 服务远程调用&#xff1a;Feign 服务保护&#xff1a;sentinel 服务网关&#xff1a;Gateway 微服务注册和发现 nacos和eureka的区别 负载均衡 微服务向Ribbon发送…

[1678]旅游景点信息Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 旅游景点信息管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql…

Word页脚设置“第X页共X页”的方法【域实现】

Word页脚设置“第X页共X页”的方法【域实现】 在设置Word页码格式的要求中&#xff0c;有时需要设置为“第X页共X页”这种格式&#xff0c;使用Word中的域功能可实现&#xff0c;同时&#xff0c;在某些情况下&#xff0c;可能还需要减去封面的页码&#xff0c;接下来为具体步…

软件标准建设体系规范过程性文档(软件开发,管理,安全,运维等各阶段全文档)

软件标准建设体系规范是确保软件开发过程标准化、高质量和可维护性的关键。它通常包括一系列文档、规范、流程和最佳实践&#xff0c;以确保软件项目的成功实施和交付。以下是一个软件标准建设体系规范的基本框架&#xff1a; 软件全套资料获取方式1&#xff1a;进主页。 获取…

C#描述-计算机视觉OpenCV(3):重映射

C#描述-计算机视觉OpenCV&#xff08;3&#xff09;&#xff1a;重映射 前言色彩波形图像重映射 前言 C#描述-计算机视觉OpenCV&#xff08;1&#xff09;&#xff1a;基础操作 C#描述-计算机视觉OpenCV&#xff08;2&#xff09;&#xff1a;图像处理 在前文中&#xff0c;描…

【跟马少平老师学AI】-【神经网络是怎么实现的】(四)卷积神经网络

一句话归纳&#xff1a; 1&#xff09;用1个小粒度的模式&#xff0c;逐个与图像的局部区域进行运算&#xff0c;运算结果反映模式与区域的匹配程度。 2&#xff09;卷积神经网络与全连接神经网络的区别&#xff1a; 卷积神经网络的输出只与局部输入有连接。参数较少&#xff0…

如何将手机投屏到mac电脑

1、将iphone手机和mac电脑连接到同一个网络 2、点击电脑上的QuickTime Player 3、点击之后&#xff0c;这个QuickTime Player的进程就开启了 4、鼠标点到这个上面&#xff0c;然后右击&#xff0c;选择新建影片录制 5、点击这个按钮后&#xff0c;来到这个界面&#xff0c;点击…

汉王科技亮相世界数字健康论坛:以AI定义第四代血压计

作为科技行业的年度盛会&#xff0c;2024年中关村论坛年会于近日在北京揭幕。 作为中关村知名的人工智能企业&#xff0c;汉王科技携大模型的最新垂直应用、柯氏音法电子血压计等创新成果&#xff0c;在4月29日中关村论坛平行论坛“2024世界数字健康论坛”上亮相。 在《AI赋能血…

jupyter notebook使用与本地位置设置

本地安装好Anaconda之后&#xff0c;自带的有Jupter notebook。 使用jupyter notebook 使用jupyter notebook时&#xff0c;可以直接打开或者搜索打开&#xff1a; 打开后&#xff0c;我们生成的或者编辑的一些文件&#xff0c;都可以看到&#xff0c;如下&#xff1a; j…