mybstis介绍
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射
官方网站https://mybatis.net.cn/
框架(Framework)
定义:是一套半成品的软件,为解决特定领域问题提供了基础架构、规范和通用功能,开发者需要在此基础上填充业务逻辑。
特点:
-
针对性
:专注于解决某一领域的问题,例如:- Spring:核心是依赖注入(DI)和面向切面(AOP),解决 Java 应用的分层架构和组件管理问题;
- MyBatis:专注于数据库访问层,简化 SQL 操作;
- Spring MVC:处理 Web 层的请求分发、参数绑定等问题。
-
约束性:框架通常有固定的设计模式和代码规范(如 Spring 的 IOC 容器要求对象由框架管理),开发者需遵循这些规范。
-
封装性:内置了大量通用功能(如事务管理、日志、安全校验),避免重复开发。
技术栈(Technology Stack)
定义:是一系列技术的组合,这些技术相互配合,共同支撑一个完整的应用系统开发和运行。
特点:
-
综合性
:涵盖从前端到后端、从开发到部署的多个技术领域,例如:
- 一个典型的 Java Web 技术栈可能包括:
- 后端框架:Spring Boot、Spring MVC、MyBatis;
- 数据库:MySQL、Redis;
- 前端技术:Vue.js、HTML/CSS;
- 部署工具:Docker、Jenkins。
- 一个典型的 Java Web 技术栈可能包括:
-
灵活性:技术栈的组合没有固定标准,可根据项目需求选择(例如用 Spring Data JPA 替代 MyBatis,用 PostgreSQL 替代 MySQL)。
-
完整性:目标是覆盖应用开发的全流程,确保各环节技术能无缝协作。
mybatis环境搭建教程
创建maven工程
具体步骤查看maven教程
导入依赖
在pom.xml导入依赖的方式
[!IMPORTANT]
[!NOTE]
<!--单个依赖--> <dependency> <!--组织名称--> <groupId>junit</groupId> <!-- 项目名称--> <artifactId>junit</artifactId> <!-- 版本号--> <version>3.8.1</version> <scope>test</scope> </dependency>依赖下载网址
复制代码到pom.xml即可导入到maven项目
示例
<!-- mysql jar包依赖导入-->
<dependency>
<groupId>com.mysql</groupId> //依赖出自的组织名称
<artifactId>mysql-connector-j</artifactId> //需要安装的依赖名称(可从依赖查询网站找)
<version>8.0.33</version> //版本号
</dependency>
//mybatis 依赖导入
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
创建配置文件
(mybstis-config.xml )

配置文件顺序要求
[!WARNING]
不可以乱改

核心文件配置
[!CAUTION]
mybatis核心配置文件约束头(官网可找到)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <!--核心配置文件--> <configuration> <!-- 所有的环境--> <environments default="jx2506"> <!-- 单个环境--> <environment id="jx2506"> <!-- 事务管理--> <transactionManager type="JDBC"/> <!-- 数据源(连接池)--> <dataSource type="POOLED"> <!-- 驱动--> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <!-- url--> <property name="url" value="jdbc:mysql://159.75.98.28:3306/JX2506"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> </configuration>

确认编码格式以及jdk版本信息

<properties>
<!-- 设置源代码的字符编码为 UTF-8 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 设置编译时使用的 JDK 版本为 8 -->
<maven.compiler.source>8</maven.compiler.source>
<!-- 设置编译时目标字节码的 JDK 版本为 8 -->
<maven.compiler.target>8</maven.compiler.target>
</properties>
创建标准结构
接口:负责制定查询内容(规范)
在包下新建mapper文件夹

对应的映射文件:写sql语句
[!IMPORTANT]
接口和他的mapper配置文件路径必须相同(或同一个包下) 如下
创建多层文件夹用/分割

[!WARNING]
接口与他的mapper配置文件必须同名

映射文件配置
这个xml文件也需要约束头
<?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">
<!--namespace与接口绑定-->
<mapper namespace="org.example.mapper.UserMapper"> //包名+类名==>全限定名
</mapper>

操作方式示例
操作方式如下
[!CAUTION]
注意图中id对应关系
xml中注意对应标签写对应sql语句

[!NOTE]
接口定义查询时 返回值尽量设置包装类如
Integer、Long、Boolean等
// 不推荐:基本数据类型可能导致歧义
int getUserIdByUsername(String username); // 查询不到时返回 0,无法区分「无此用户」和「用户ID为0」
// 推荐:包装类可明确表示「无结果」
Integer getUserIdByUsername(String username); // 查询不到时返回 null,清晰表示「无此用户」
用包装类接收查询结果,通过 null 明确表示「无数据」,避免基本数据类型默认值带来的歧义,减少潜在的 bug。这是 MyBatis 开发中一种简单且有效的最佳实践
注册接口信息
(指定mapper文件位置)
回到mybatis-config.xml注册接口信息
//包扫描注册 name中写接口所在的mapper包路径
<mappers>
<package name="org.example.mapper"/>
</mappers>
使用
public class MybatisTest {
public static void main(String[] args) throws Exception {
/*
* 1.读取mybatis 的配置文件
* 2.创建sqlSession工厂构造器
* 3.通过sqlSession工厂构造器 创建一个 sqlSession工厂
* 4. sqlSession工厂 获取一个连接
* 5.根据连接去获取mapper接口
* 6.调用方法
* */
// 1.读取mybatis 的配置文件
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
// 2.创建sqlSession工厂构造器
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//3.通过sqlSession工厂构造器 创建一个 sqlSession工厂
SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(reader);
//4.sqlSession工厂 获取一个连接
SqlSession sqlSession = sessionFactory.openSession(true);
//5.根据连接去获取mapper接口
UserMapper user = sqlSession.getMapper(UserMapper.class);
//6.执行mapper文件里的方法
Integer res = user.queryUserCount();
[!CAUTION]
使用api时 注意检查好对应的包

通过实体类存放数据库查询的数据
创建entity文件夹下存放用户实体类

当中变量表示字段名


lambok(小辣椒)
字段过多 写get/set/toString过于麻烦可使用
<!--小辣椒-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
在需要使用的类上添加注解
(@data /@NoArgsConstructor / @AllArgsConstructor)
[!TIP]
@Data
最常用的注解之一,是一个 “组合注解”,等价于同时添加@Getter、@Setter、@ToString、@EqualsAndHashCode、@RequiredArgsConstructor。
作用:为类的所有成员变量生成 getter、setter,生成toString()、equals()、hashCode()方法,以及包含所有final或@NonNull字段的构造方法。
@NoArgsConstructor:生成无参构造方法。@AllArgsConstructor:生成包含所有成员变量的全参构造方法。

接口与映射文件传参
接口与对应映射文件传参时名称要一致

@param注解
在 MyBatis 中,当接口方法有多个参数时,需要通过 @Param 注解,为每个参数指定一个名称,以便在 XML 映射文件或注解 SQL 中通过该名称引用参数。
通过 @Param 注解可以为参数自定义名称,在 SQL 中直接使用该名称引用参数,更清晰且不易出错。
@Param("acc")

实体类通过接口接收数据库查询信息
[!IMPORTANT]
MyBatis 会默认按照 “字段名 = 成员变量名” 的规则进行映射:
- 数据库表字段名(如
id、account)UserDO的成员变量名(如id、account)例如,SQL 中
select id, account from user的结果:
- 字段
id的值会自动赋值给UserDO的id变量- 字段
account的值会自动赋值给UserDO的account变量


总结
- 使用
UserDO作为返回值,是为了实现数据库表与 Java 对象的直观映射,保证类型安全和代码可读性。- MyBatis 通过 “字段名 - 变量名匹配” 或 “
resultMap手动配置” 的方式,将查询结果自动映射到UserDO的成员变量中,底层通过反射调用 setter 方法完成赋值。
mybatis的事务管理
事物管理
在软件开发中,事务管理(Transaction Management) 是确保数据库操作一致性、完整性的核心机制。它主要解决多个关联操作要么 “全部成功”,要么 “全部失败” 的问题,避免出现数据不一致的中间状态
[!CAUTION]
事物的四大特性(ACID)
- 原子性(Atomicity)
事务是一个不可分割的最小操作单元,要么所有操作都执行成功并提交,要么任何一个操作失败就全部回滚(撤销),不会留下部分完成的状态。
例:转账时 “扣钱” 和 “加钱” 必须同时成功或同时失败。- 一致性(Consistency)
事务执行前后,数据库的状态必须从一个 “有效状态” 转变为另一个 “有效状态”,满足预设的业务规则。
例:转账前后,两个账户的总金额保持不变。- 隔离性(Isolation)
多个并发事务之间相互隔离,一个事务的操作不会被其他事务干扰,避免因并发导致的数据错误(如脏读、不可重复读、幻读)。
数据库通过隔离级别控制隔离性,常见级别:读未提交、读已提交、可重复读、串行化。- 持久性(Durability)
事务一旦提交,其修改会被永久保存到数据库中,即使系统崩溃也不会丢失。
mybatis的事务管理
- 原理:依赖 JDBC 原生的事务管理机制,通过
java.sql.Connection的commit()、rollback()方法控制事务。 - 特点:需要手动管理事务的开启、提交和回滚,与 JDBC 原生事务行为一致。

使用方式
SqlSession sqlSession = sqlSessionFactory.openSession(); // 默认不自动提交事务
try {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 执行数据库操作
userMapper.updateBalance(1, -100); // 扣钱
userMapper.updateBalance(2, +100); // 加钱
sqlSession.commit(); // 全部成功,手动提交
} catch (Exception e) {
sqlSession.rollback(); // 失败回滚
} finally {
sqlSession.close();
}
动态sql语句
where+if标签
<if> 标签:条件判断
<if> 标签用于根据参数条件动态拼接 SQL 片段,只有当 test 属性中的表达式为 true 时,才会将标签内的 SQL 片段加入最终执行的 SQL 中。
核心属性
-
test
:必填属性,用于指定判断条件(使用 OGNL 表达式),例如:test="name != null":参数name不为nulltest="age > 18":参数age大于 18test="status != null and status != ''":参数status不为null且不为空字符串
示例 concat是字符串的拼接 (在这里模糊查找)
<select id="queryUser" resultType="UserDO">
select * from user
where 1=1 <!-- 传统方式:用恒真条件避免多余的AND -->
<if test="name != null and name != ''">
and name like concat('%', #{name}, '%') <!-- 条件满足时拼接该片段 -->
</if>
<if test="age != null">
and age = #{age} <!-- 条件满足时拼接该片段 -->
</if>
</select>
- 当
name="张三"且age=20时,生成的 SQL 为:
select * from user where 1=1 and name like '%张三%' and age=20 - 当
name为null且age=20时,生成的 SQL 为:
select * from user where 1=1 and age=20
<where> 标签:智能处理条件前缀
<where> 标签用于替代传统的 WHERE 关键字,并智能处理条件片段前的 AND/OR 关键字,避免因条件不满足导致的 SQL 语法错误。
核心功能
- 当内部有满足条件的
<if>片段时,自动添加WHERE关键字。 - 若内部条件片段以
AND或OR开头,自动剔除多余的关键字(解决传统where 1=1的冗余问题)。
<select id="queryUser" resultType="UserDO">
select * from user
<where> <!-- 替代 where 1=1 -->
<if test="name != null and name != ''">
and name like concat('%', #{name}, '%') <!-- 开头的AND会被自动处理 -->
</if>
<if test="age != null">
and age = #{age}
</if>
</where>
</select>
- 当
name="张三"且age=20时,生成的 SQL 为:
select * from user where name like '%张三%' and age=20(自动添加where,保留and) - 当
name为null且age=20时,生成的 SQL 为:
select * from user where age=20(自动剔除多余的and) - 当所有条件都不满足时,生成的 SQL 为:
select * from user(不添加where,避免语法错误)
foreach标签
在 MyBatis 动态 SQL 中,<foreach> 标签是处理集合或数组类型参数的核心标签,用于循环遍历集合元素并动态拼接 SQL 片段,广泛应用于批量查询、批量插入、批量更新等场景。
核心属性及作用
<foreach> 标签通过以下属性控制循环逻辑和 SQL 拼接格式,其中 collection、item、open、close、separator 是最常用的:
| 属性 | 含义与作用 | 是否必填 |
|---|---|---|
collection | 指定要遍历的集合 / 数组参数名称,需与 Mapper 接口中参数的命名(或 @Param 注解指定的名称)一致。 | 是 |
item | 循环中当前元素的别名,用于在标签内引用元素的值(如 #{item} 或 #{item.属性})。 | 是 |
index | 循环索引的别名(可选): - 遍历列表 / 数组时,index 表示元素的下标(从 0 开始); - 遍历 Map 时,index 表示键(key)。 | 否 |
open | 循环开始时拼接的字符串(如左括号 ()。 | 否 |
close | 循环结束时拼接的字符串(如右括号 ))。 | 否 |
separator | 多个元素之间的分隔符(如逗号 ,)。 | 否 |
<insert id="insertUserByList">
insert into user(account,password,name)
values
<foreach collection="list" item="item" separator=",">
(#{item.account},#{item.password},#{item.name})
</foreach>
</insert>
执行的sql语句 Preparing: insert into user(account,password,name) values (?,?,?) , (?,?,?)
插入的数据(两组) : 3(String), 2(String), 1(String), 33(String), 22(String), 11(String)
批量删除
使用foreach标签 动态sql
<delete id="deleteByIdList">
delete from user where id in
<foreach collection="list" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</delete>
批量修改
set标签会自动剔除最后一个逗号
执行的sql语句update user SET name = ?, balance = ?, status = ? where id = ?
<update id="updateUserByList">
update user
<set>
<if test="userDO.name !=null and userDO.name!='' ">
name = #{userDO.name},
</if>
<if test="userDO.balance!=null and userDO.balance!='' ">
name = #{userDO.balance},
</if>
<if test="userDO.status!=null and userDO.status!='' ">
name = #{userDO.status},
</if>
</set>
where id = #{userDO.id}
</update>
[!CAUTION]
如果
status为Integer会把 0 识别成空这里用
String就正常

1432

被折叠的 条评论
为什么被折叠?



