目录
[1.0 简介](#1.0 简介)
[2.0 Mybatis基本操作](#2.0 Mybatis基本操作)
[3.0 Mybatis XML配置文件](#3.0 Mybatis XML配置文件)
[(1) 了解](#(1) 了解)
[(4) # { } 和 { } 区别](# { } 和 { } 区别)
[4.0 数据库连接池](#4.0 数据库连接池)
[二 、 Mybatis进阶](#二 、 Mybatis进阶)
[1.0 动态SQL](#1.0 动态SQL)
[(2) if 标签](#(2) if 标签)
[(3) 标签](#(3) 标签)
[(7) 标签](#(7) 标签)
一、mybatis入门
1.0 简介
(1)为什么要学习mybatis
学习应用分层的时候,了解到web应用程序一般分为Controller Service Dao
但是Dao层的数据是mock(模拟)的,真实的数据应该从数据库中读取
之前是JDBC来操作数据库,但是JDBC操作太复杂了 //mybatis封装了jdbc
(2)简单介绍
之前是ibatis 改名为mybatis 是一个优秀的持久层框架,用来简化JDBC开发
mybatis中文网站地址:MyBatis中文网
持久化:放在数据库中
和springboot的关系:springboot集成了mybatis 相当于收购 例如12306里面还有点外卖的功能
框架就是共同的东西进行封装 不能封装的东西提供入口 让我们自己写
spring是基于servlet封装的 mybatis是基于jdbc进行封装的
了解jdbc发现很多步骤可以封装起来,留下一个写sql语句的入口就行,这样省去了许多不必要的麻烦
(3)mybatis操作数据库的步骤
1准备工作(创建springboot工程 数据库表准备 实体类) //实体类:Java程序操作数据是在内存中以对象的形式进行的,补不能直接操作数据库表。实体类座位桥梁,让程序能面向对象的方式处理数据,方便后续使用ORM框架自动生成SQL或封装结果集
2引入Mybatis相关依赖
3配置Mybatis(数据库连接信息)
能使用mybatis也是引入了这些依赖


创建项目的时候勾选 就是自动添加上面的代码 这里只是介绍
mysql驱动
这段代码就是告诉Maven 下载MySQL驱动,并在程序运行时把它加入类路径,这样才能连接MySQL数据库
一般我们将mybatis类写在mapper包下面 然后在配置文件里面修改

创建实体类对应数据库表(实体类就是数据库表在Java中的映射)
定义一个接口(名字一般是带Mapper)
实现接口(使用注解或xml方式)
4单元测试 :
//此处的单元测试和测试人员无关 是开发人员写的代码 开发人员一定是第一个测试的 因为代码是自己写的
方式:右键 generate test 记得加入@SpringBootTest注解 然后运行就可以看到了

@Before注解 在每个@Test方法执行之前都自动运行一次

下面是运行成功的数据库代码
//规范:

//接口测试:在ediary上面有笔记
//controller调用service service调用mapper
controller包里面UserInfoController包里面UserInfoController类 里面注入userService类的对象 定义get等功能方法(get方法里面调用service里面的方法)
service包里面UserService类 里面注入Mapper对象 定义那个方法
启动程序 去网页里面输入网址
什么是接口测试
首先了解三层结构 controller service mapper controller是前台服务员 Http请求啥的 service是厨师 业务逻辑的处理后厨主管 mapper 仓库管理员工 是采购员 在数据库里面增删改查
什么是接口测试? 就是对Controller这一层发起的HTTP请求进行测试
相当于你假装成一个客人 点一道菜 看服务员最终给你端上来的菜对不对 合理不
为什么是这样一个流程? 因为用户真实使用时,也是这样一层一层调下来的 接口测试就是模 拟 真实的用户,从
最外层完整的走一遍整个调用链 接口测试就是把这三层穿起来一起测
对比单元测试 单元测试更像是亲自跑到后厨 单独测验厨师 这里是测试整套系统能不能配合好
2.0 Mybatis基本操作
(1)打印日志
在Mybatis当中我们可以借助日志,查看到sql语句的执行,执行传递的参数以及执行的结果
在配置文件中进行配置即可
java
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
重新运行程序 可以看到SQL执行内容 以及传递参数和执行结果

上面就是打印出来的日志 可以清晰看到过程步骤
(2)查
想要执行这个语句:SELECT *FROM 'user_info' where id = 2
查询某一个用户 例如下面的功能 如何使用mybatis实现?

对于数据量只有一条 我们用一个对象就可以了 如果查询的数据量多了 我们就用List
照葫芦画瓢 并生成测试方法

@Select(" select *from user_info")
List<UserInfo> selectAll( );
当有人调用selectAll( )这个方法时,就自动执行SQL语句 然后把查出来的结果变成UserInfo对象的列表返回
在自动生成的测试方法里面写sout语句

运行测试方法 控制台出来的结果

新的需求:
前端传递过来查询的请求 后端查询
controller接收到参数 给了service service接收到参数 给了mapper mapper是一个方法 本身能接收参数
在UserMapper里面查询
传递单个参数

用这个格式 id就和id对应起来了 而且是动态的
在测试方法里面尝试 结果一一对应
传递多个参数
想要执行这个语句
SELECT * FROM `user_info` where username="zhangsan" and 'password'="zhangsan"
使用List接收(可能会存在多条)
@Test
void selectByNameAndPassword() {
userInfoMapper.selectByNameAndPassword("zhangsan","zhangsan").stream().
forEach(x->System.out.println(x));
}

参数的名称是否是有序的?
List<User Info> selectByNameAndPassword(String password , String username);
不一定非要对应上 名字对应上就行了 没有按照顺序
@Param注解 :为多参数提供明确的绑定标识
问题:当字段名和属性名对应不上的时 如何对应上呢?
1.数据库语句 可以使用别名
select id ,username , `password` , age , gender , phone ,
delete_flag as deleteFlag, create_timeas createTime , update_time as updateTime from user_info
2.使用注解的方式或者XML方式
XML方式是直接把映射规则写在XML文件里,用resultMap标签
注解方式是直接把映射规则写在Java接口的方法上面 用@Results等这些注解
添加依赖 配置数据库信息 定义接口 通过注解实现接口
3.开启驼峰命名
在配置文件里面写好
map-underscore-to-camel-case: true
(3)增
如何添加数据?
@Insert("insert into user_info (username,`password`,age) values ('java113','java113',1);")
引入场景: 网络购物下订单
系统:订单系统 支付系统 库存系统
下完订单之后 订单系统会通知支付系统和库存系统
订单系统执行insert (因为下单了嘛) 生成一个订单号(这个订单号用于调用支付系统和库存系统 )
支付系统做自己的事情 库存系统做自己的事情...........
因为id是自增的 所以这个订单号是自增的
支付系统和库存系统如何得到这个订单号? //获取自增id的方式
@Option(UseGeneratedKeys = true , keyProperty = "id" )
mybatis中用来自动获取数据库自动生成的主键 并回填到你的对象属性中的注解
//注解太长需要换行:拼接字符串 当你换行的时候 idea编译器自动加上双引号了
(4)多表查询操作
多表查询:你要查找的数据不在一个表里,得从两或三个表里凑一块儿查出来
例如从用户信息表和用户订单表中查 某个用户的所有订单
如何使用mybatis实现下面图片里面的效果?

使用xml的方式
写实体类 创建接口 创建xml文件(可以直接复制粘贴 然后把没用的东西删掉)
在接口里面写实现类 然后右键在xml文件里面生成代码 在生成的代码里面写sql语句
然后创建test类测试
这样就是多表查询
3.0 Mybatis XML配置文件
(1) 了解
使用Mybatis的注解方式 主要是用来完成一些简单的增删改查功能 如果需要实现复杂的SQL功能 建议使用XML来配置映射语句 也就是将SQL语句写在配置文件中
步骤:
- 配置数据库连接字符串和Mybatis //添加依赖 mybatis-starter mysql
2.写持久层代码
- 定义接口
4.使用xml实现接口
(2)配置文件的增删改查
定义接口 里面写例如Integer updateUser(String pawword , Integer age ,Integer id);
在xml文件中实现接口
//企业开发中 尽量避免使用多表查询 公司的数据是非常大的,要查到啥时候
//对于性能没有要求的时候 可以使用多表查询
//慢SQL 开发中需要治理的

慢sql就是执行的很慢的sql语句 慢sql影响的是mysql集群 也就是影响其他的sql语句 在现实生活中要好好治理
(3)杂
首先配置打印Mybatis日志 在配置文件里面加一句代码
java
mybatis:
mapper-locations: classpath:mapper/**Mapper.xml
这样就是告诉了xml文件在哪了
xml文件里面写的内容: //需要加入MybatisX插件 用来Mapper和XML来回跳
java
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bite.mybatis.model.mapper.UserInfoMapperXML">
</mapper>
这样就是告诉 在这里实现

点击这个小鸟图标 方法和方法之间也能跳动

这样在xml文件里面写数据库语句 在select标签中间

写测试类方法测试一下
(4) # { } 和 $ { } 区别
使用# 查看日志输出:


wher id = ? 这里问号是占位符 参数单独传进去,这叫做预编译
使用$ 查看日志输出:


不一样的地方有哪些?
一个是where id = ? 一个是where id = 1
预编译SQL : #:使用问号先占位 提前预留参数位置 $:即时SQL 是直接拼接
优点:性能好一点,预编译SQL占位
即时SQL :直接执行 $符号是直接拼接,如果参数为stirng类型 需要手动添加引号,SQL注入问题
使用$ 如果参数为string 类型,需要手动添加引号 # { }会自动给字符串加单引号
where name = # {userName} mybats帮你处理后实际执行的SQL:where name = '张三'
where name = ${userName} mybatis帮你处理后实际执行的SQL:where name = 张三
对于第二种情况必须手动写成where name = '${userName}' 这样替换之后才是 where name='张三'
SQL注入问题:是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法 通俗:通过参数把SQL变了 从而达到了对服务器的攻击
例如:就像你去食堂打饭,你跟阿姨说"给我一份番茄炒蛋",结果坏蛋插队喊"给我一份番茄炒蛋'然后顺便把整个窗口的菜都端走'"。阿姨脑子不好使,真照做了。
代码例子就是:
这样会把所有东西查出来 或者里面偷偷加入删表操作
能用#就别用 ,使用可能出现SQL注入问题
mybatis 也关于sql注入做了一些处理 面试题 : # 和 $的区别 主要是SQL 预编译SQL,即时SQL
(5)排序功能
: {} 会有SQL注⼊的⻛险, 所以我们尽量使⽤#{}完成查询 既然如此, 是不是 {} 就没有存在的必要性了呢? 当然不是
${}的使用场景:例如购物app的 价格从高到低 价格从低到高 销量从低到高............
使用# "desc"会出现报错

这个时候使用$ 那么之前的SQL注入的问题呢? 如何解决呢?
原则上使用#的 就使用# 不能使用# 一定要考虑SQL注入的问题并进行排除
//分库分表的时候
现实生活中常常需要分库分表 因为mysql的存储能力也是有限
流水表 flow id from to 银行账号 金额 时间
分为flow1 flow2 flow3.....
select * from flow 这里只能使用$ 不能使用#
//因为 表名不能是占位符? select *from #{tableName} where id = 1 mybatis会处理成 select * from ? where id = 1 用符写就是 select \*from {tableName} where id = #{id} mybatis会处理成 select *from flow_2026_4 where id = ? 这样既能动态表名 又能安全查id ,所以 分库分表场景下 表名虽然必须用${ } 但是绝不能直接把用户输入当表名 必须在Java代码里白名单校验
(6)like查询
select *from user_info where username like "username%"
@Select("select *from user_info where username like '%#{userName}%'")
正确写法是:
@Select("select *from user_info where username like '%${userName}%'")
其他的写法:
@Select("select *from user_info where username like CONCAT('%',#{userName},'%'))
CONCAT函数用来拼接字符串 把自己串的首尾连接在一起 拼接成一个完整的新字符串
4.0 数据库连接池
包括线程池 数据库连接池属于是池化技术

数据库连接池 = 提前养好的一群数据库"长工",用的时候叫一个过来干活,干完让他回屋歇着,下回接着用。不用现招人(建连接),也不用干完就杀掉(关连接)。
常见的数据库连接池:目前比较流行的是 Hikari Druid
Hikari是SpringBoot默认使用的数据库连接池 Driuid 如果我们想把默认的数据库连接池切换为Druid数据库连接池 只需要引入相关依赖即可
java
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>1.2.21</version>
</dependency>

() 三层架构
以京东搜索 手机为例
1.Controller : 接收搜索词 返回手机列表
2.Service Controller请求Service 会多次并发调用多个Dao层数据 或 其他服务
3.Dao/Mapper: service请求dao
每一层都有自己存在的原因 不能随意省略
二 、 Mybatis进阶
1.0 动态SQL
(1)引入
场景:如果你想要做一个用户搜索功能 页面上有三个输入框 用户名 性别 手机号
用户可能只是填写一个 也可能填写两个 也可能全填写
如果没有动态输入 我们的Java代码需要写很多

动态SQL就是来解决这个 排列组合 噩梦的
MyBatis 提供的一套标签,让你能在 XML 或注解里像写 if 语句一样,根据参数有没有值,自动决定要不要把某段 SQL 拼上去。
你只需要写一段XML MyBatis自动处理8中组合 一个if-else都不用写!
让SQL拼接从 体力活 变成 指挥艺术
(2) if 标签
格式是把 gender, 变为<if test = "gender != null " > gender , < /if >
也就是把原来的代码放到<if></if>标签里面了
if标签里面用的是参数名称 也就是属性名称 xml里test写的名字 必须和Java里传参时用的名字一摸一样,你传的时候叫啥 这里就写啥
if标签中间是 数据库字段名
这样看更加直观一点:

代码翻译 : 如果gender不是null 就拼接gender
逗号放前面是为了当为null的时候 sql语句的通顺 非常容易出现一些bug
(3) <trim>标签
去逗号标签 不止逗号,敲击空格会出现提示词


例如: <trim> prefixOverrides=" , " </trim> 把代码放进去 就自动给你去掉前面的逗号了
去掉的是前缀后缀里面的内容 里面放什么都可以
(4) 如何使用注解使用动态SQL
<script>标签 把之前在xml文件里面的代码复制过来

(4)where标签
select *from user_info where phone = 1001 and delete_flag = 0;
在mybatis里面还是那个固定套路 接口里面写 生成到xml文件里面 生成测试方法测试
如何动态的拼接where呢?
用if标签的话 如何处理and呢? 用tirm标签和if标签合力 //再一次展示了trim标签去前缀的功能

如果我们phonte = 1001 没有选 delete_flag = 0 都没有选呢 //当查询条件为空时,会多余where关键字
上面的代码翻译的sql语句就是 select * from where //这不是一句正常的sql代码
优化方案: 去除where 去添加1=1 //这样是为了避免where后面为空 先放一个永远成立的条件垫底 1=1永远是真的,所以它不会直接影响查询结果 但是保证了where后面永远有东西

另外的方式 <where> 标签
//如果里面没有符合条件的Q<if>内容 它连where这个单词都不会给你输出
此时语句就成了 select * from user_info 没有语法错误
总结where标签:

<5>set标签

age为空 或者gender为空 都会报错 使用trim标签去除逗号的可以通过
如果三个情况都为空呢? 不存在这种情况 如果都是空 就无法更新
优化: set标签
会帮我生成set关键字 并且帮我去除多余的逗号
(6)foreach标签
对集合进行遍历时使用该标签 标签有如下属性
collection:绑定方法参数中的集合 如LIst Set Map或数组对象

如何用mybatis运行上面的代码呢
例如第三条语句 in是表示属于这个清单的 in(1,2,3) id在这几个数里面就行
使用foreach拼接下图的sql代码

目的是把(23,22,21,20)这个给包起来
<for each collection=" ids">

最终的效果就是:

再来一个拼接的例子:

(7)<inclue>标签
其实就是mybatis里的复制粘贴快捷键
include标签就是为了让你一次写 到处贴
有重复的东西 定义一个sql标签 里面是一个字符串,是sql中的一部分,不一定能执行 id是取名字


动态SQL的官方网站:动态 SQL_MyBatis中文网 里面有其他标签的介绍
之后还会讲其他的工具 动态SQL的代码甚至不用写
2026.4.17