MyBatis 从入门到实战:核心配置、映射开发与动态 SQL 全解析

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。
  • 灵活性:技术栈的组合没有固定标准,可根据项目需求选择(例如用 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>

依赖下载网址

Maven 依赖查询网站

aililibaba提供的查询

复制代码到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]

接口定义查询时 返回值尽量设置包装类如 IntegerLongBoolean

// 不推荐:基本数据类型可能导致歧义
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 会默认按照 “字段名 = 成员变量名” 的规则进行映射:

  • 数据库表字段名(如 idaccount
  • UserDO 的成员变量名(如 idaccount

例如,SQL 中 select id, account from user 的结果:

  • 字段 id 的值会自动赋值给 UserDOid 变量
  • 字段 account 的值会自动赋值给 UserDOaccount 变量

在这里插入图片描述

在这里插入图片描述

总结

  • 使用 UserDO 作为返回值,是为了实现数据库表与 Java 对象的直观映射,保证类型安全和代码可读性。
  • MyBatis 通过 “字段名 - 变量名匹配” 或 “resultMap 手动配置” 的方式,将查询结果自动映射到 UserDO 的成员变量中,底层通过反射调用 setter 方法完成赋值。

mybatis的事务管理

事物管理

在软件开发中,事务管理(Transaction Management) 是确保数据库操作一致性、完整性的核心机制。它主要解决多个关联操作要么 “全部成功”,要么 “全部失败” 的问题,避免出现数据不一致的中间状态

[!CAUTION]

事物的四大特性(ACID)

  1. 原子性(Atomicity)
    事务是一个不可分割的最小操作单元,要么所有操作都执行成功并提交,要么任何一个操作失败就全部回滚(撤销),不会留下部分完成的状态。
    例:转账时 “扣钱” 和 “加钱” 必须同时成功或同时失败。
  2. 一致性(Consistency)
    事务执行前后,数据库的状态必须从一个 “有效状态” 转变为另一个 “有效状态”,满足预设的业务规则。
    例:转账前后,两个账户的总金额保持不变。
  3. 隔离性(Isolation)
    多个并发事务之间相互隔离,一个事务的操作不会被其他事务干扰,避免因并发导致的数据错误(如脏读、不可重复读、幻读)。
    数据库通过隔离级别控制隔离性,常见级别:读未提交、读已提交、可重复读、串行化。
  4. 持久性(Durability)
    事务一旦提交,其修改会被永久保存到数据库中,即使系统崩溃也不会丢失。

mybatis的事务管理

  • 原理:依赖 JDBC 原生的事务管理机制,通过 java.sql.Connectioncommit()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 不为 null
    • test="age > 18":参数 age 大于 18
    • test="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
  • namenullage=20 时,生成的 SQL 为:
    select * from user where 1=1 and age=20

<where> 标签:智能处理条件前缀

<where> 标签用于替代传统的 WHERE 关键字,并智能处理条件片段前的 AND/OR 关键字,避免因条件不满足导致的 SQL 语法错误。

核心功能
  1. 当内部有满足条件的 <if> 片段时,自动添加 WHERE 关键字。
  2. 若内部条件片段以 ANDOR 开头,自动剔除多余的关键字(解决传统 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
  • namenullage=20 时,生成的 SQL 为:
    select * from user where age=20(自动剔除多余的 and
  • 当所有条件都不满足时,生成的 SQL 为:
    select * from user(不添加 where,避免语法错误)

foreach标签

在 MyBatis 动态 SQL 中,<foreach> 标签是处理集合或数组类型参数的核心标签,用于循环遍历集合元素并动态拼接 SQL 片段,广泛应用于批量查询、批量插入、批量更新等场景。

核心属性及作用

<foreach> 标签通过以下属性控制循环逻辑和 SQL 拼接格式,其中 collectionitemopencloseseparator 是最常用的:

属性含义与作用是否必填
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]

如果statusInteger会把 0 识别成空

这里用String就正常

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值