当前位置: 首页 > news >正文

MyBatis 从入门到进阶:数据库操作全指南

在 Java 后端开发中,数据库交互是核心环节之一。JDBC 作为 Java 原生的数据库操作方案,流程繁琐且代码冗余,而 MyBatis 作为优秀的持久层框架,能极大简化数据库操作。本文将从 MyBatis 基础入门到进阶应用,结合实战案例全面讲解其使用方法与核心特性。

一、MyBatis 入门:告别 JDBC 的繁琐

1.1 为什么选择 MyBatis?

回顾 JDBC 操作流程,从创建连接池、获取连接,到编写 SQL、绑定参数、处理结果集,再到释放资源,整个过程需要大量重复代码。以添加图书为例,仅基础操作就需数十行代码,且参数绑定、资源清理等逻辑在每个方法中都要重复实现。

MyBatis 的出现完美解决了这些问题:它是一款专注于简化 JDBC 开发的持久层框架,前身为 Apache 的 iBatis 项目,2010 年迁移后更名并持续迭代。其核心优势在于将 SQL 与 Java 代码解耦,自动完成参数映射与结果封装,大幅减少模板代码。

1.2 入门环境搭建

(1)项目初始化

创建 Spring Boot 工程,引入 MyBatis 起步依赖与 MySQL 驱动:

<!-- MyBatis依赖 -->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version>
</dependency>
<!-- MySQL驱动 -->
<dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope>
</dependency>

注意:Spring Boot 3.x 对应 MyBatis 3.x 版本,版本兼容关系可参考官方文档。

(2)数据库与实体类准备

以图书管理系统为例,创建数据库与表结构:

-- 创建数据库
DROP DATABASE IF EXISTS book_test;
CREATE DATABASE book_test DEFAULT CHARACTER SET utf8mb4;
USE book_test;-- 图书表
CREATE TABLE `book_info` (`id` INT NOT NULL AUTO_INCREMENT,`book_name` VARCHAR(127) NOT NULL,`author` VARCHAR(127) NOT NULL,`count` INT NOT NULL,`price` DECIMAL(7,2) NOT NULL,`publish` VARCHAR(256) NOT NULL,`status` TINYINT DEFAULT 1 COMMENT '0-无效,1-可借阅,2-不可借阅',`create_time` DATETIME DEFAULT now(),`update_time` DATETIME DEFAULT now() ON UPDATE now(),PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;

创建对应实体类BookInfo(使用 Lombok 简化 getter/setter):

import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;@Data
public class BookInfo {private Integer id;private String bookName; // 对应表中book_name字段private String author;private Integer count;private BigDecimal price;private String publish;private Integer status;private Date createTime; // 对应表中create_time字段private Date updateTime;
}
(3)数据库配置

application.yml中配置数据库连接与 MyBatis 基础参数:

spring:datasource:url: jdbc:mysql://127.0.0.1:3306/book_test?characterEncoding=utf8&useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver # MySQL 8.x驱动mybatis:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印SQL日志map-underscore-to-camel-case: true # 驼峰命名自动转换

1.3 基础 CRUD 实现

MyBatis 提供注解与 XML 两种开发方式,简单场景推荐注解,复杂 SQL 建议使用 XML。

(1)注解方式

创建 Mapper 接口,通过注解编写 SQL:

import org.apache.ibatis.annotations.*;
import java.util.List;@Mapper // 标识为MyBatis映射接口
public interface BookInfoMapper {// 新增图书@Insert("insert into book_info(book_name,author,count,price,publish,status) " +"values(#{bookName},#{author},#{count},#{price},#{publish},#{status})")@Options(useGeneratedKeys = true, keyProperty = "id") // 返回自增主键Integer insertBook(BookInfo bookInfo);// 根据ID查询@Select("select * from book_info where id=#{id} and status<>0")BookInfo queryById(Integer id);// 更新图书@Update("update book_info set book_name=#{bookName},author=#{author} where id=#{id}")Integer updateBook(BookInfo bookInfo);// 删除图书(逻辑删除)@Delete("update book_info set status=0 where id=#{id}")Integer deleteBook(Integer id);
}
(2)XML 方式

当 SQL 逻辑复杂时,XML 方式更易维护。首先在配置文件中指定 XML 路径:

mybatis:mapper-locations: classpath:mapper/**Mapper.xml # XML文件存放路径

创建BookInfoMapper.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"><!-- 命名空间对应Mapper接口全路径 -->
<mapper namespace="com.example.demo.mapper.BookInfoMapper"><!-- 新增图书 --><insert id="insertBook" useGeneratedKeys="true" keyProperty="id">insert into book_info(book_name,author,count,price,publish,status)values(#{bookName},#{author},#{count},#{price},#{publish},#{status})</insert><!-- 动态更新图书 --><update id="updateBook">update book_info<set><if test="bookName!=null">book_name=#{bookName},</if><if test="author!=null">author=#{author},</if><if test="price!=null">price=#{price},</if></set>where id=#{id}</update>
</mapper>
(3)单元测试

使用 Spring Boot Test 验证功能:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class BookInfoMapperTest {@Autowiredprivate BookInfoMapper bookInfoMapper;@Testvoid testInsert() {BookInfo book = new BookInfo();book.setBookName("MyBatis实战");book.setAuthor("张三");book.setCount(10);book.setPrice(new BigDecimal("59.9"));book.setPublish("机械工业出版社");book.setStatus(1);bookInfoMapper.insertBook(book);System.out.println("新增图书ID:" + book.getId()); // 自增ID已赋值}
}

二、MyBatis 进阶:动态 SQL 与实战技巧

2.1 动态 SQL 核心标签

动态 SQL 是 MyBatis 的强大特性,能根据条件动态拼接 SQL,常见标签如下:

(1)<if>:条件判断

用于实现可选字段的动态处理,例如注册用户时的非必填字段:

<insert id="insertUser">INSERT INTO user_info (username,password,<if test="gender!=null">gender,</if>phone)VALUES (#{username},#{password},<if test="gender!=null">#{gender},</if>#{phone})
</insert>

注意:test属性中引用的是实体类属性,而非数据库字段。

(2)<trim>:去除多余符号

解决多条件拼接时的逗号、AND 等多余符号问题,例如动态新增:

<insert id="insertUserByTrim">INSERT INTO user_info<trim prefix="(" suffix=")" suffixOverrides=","><if test="username!=null">username,</if><if test="password!=null">`password`,</if><if test="phone!=null">phone,</if></trim>VALUES<trim prefix="(" suffix=")" suffixOverrides=","><if test="username!=null">#{username},</if><if test="password!=null">#{password},</if><if test="phone!=null">#{phone},</if></trim>
</insert>
  • prefix:添加前缀
  • suffix:添加后缀
  • suffixOverrides:去除末尾多余符号
(3)<where>:动态条件拼接

自动处理 WHERE 子句开头的 AND/OR,例如多条件查询:

<select id="queryByCondition" resultType="BookInfo">select * from book_info<where><if test="bookName!=null">and book_name like concat('%',#{bookName},'%')</if><if test="author!=null">and author=#{author}</if><if test="status!=null">and status=#{status}</if></where>
</select>
(4)<foreach>:集合遍历

用于批量操作,例如批量删除:

<delete id="batchDelete">delete from book_info where id in<foreach collection="ids" item="id" open="(" close=")" separator=",">#{id}</foreach>
</delete>
  • collection:集合参数名
  • item:遍历元素别名
  • open/close:包裹符号
  • separator:分隔符
(5)<include>:SQL 片段复用

抽取重复 SQL 片段,提升可维护性:

<!-- 定义SQL片段 -->
<sql id="allColumns">id,book_name,author,count,price,publish,status,create_time,update_time
</sql><!-- 引用SQL片段 -->
<select id="queryAll" resultType="BookInfo">select <include refid="allColumns"/> from book_info
</select>

2.2 #{} 与 ${} 的核心区别

两者均用于参数注入,但存在本质差异:

特性#{}${}
处理方式预编译 SQL,? 占位符字符串直接替换
安全性防止 SQL 注入存在 SQL 注入风险
类型处理自动添加引号需手动添加引号
使用场景普通参数注入排序字段、表名等动态标识符

示例:排序功能实现排序字段无法使用#{}(会自动加引号导致语法错误),需使用${}

@Select("select * from book_info order by ${sortField} ${sortOrder}")
List<BookInfo> queryBySort(@Param("sortField") String sortField, @Param("sortOrder") String sortOrder);

注意:使用${}时需严格校验参数,避免 SQL 注入。

2.3 分页实现

当数据量较大时,分页查询是必备功能。MyBatis 可通过LIMIT关键字手动实现分页:

(1)分页请求与结果封装
// 分页请求参数
@Data
public class PageRequest {private int currentPage = 1; // 当前页码private int pageSize = 10;   // 每页条数// 计算起始索引public int getOffset() {return (currentPage - 1) * pageSize;}
}// 分页结果封装
@Data
public class PageResult<T> {private int total;        // 总记录数private List<T> records;  // 当前页数据public PageResult(int total, List<T> records) {this.total = total;this.records = records;}
}
(2)分页查询实现
// Mapper接口
public interface BookInfoMapper {// 查询总记录数@Select("select count(1) from book_info where status<>0")Integer count();// 分页查询列表@Select("select * from book_info where status<>0 order by id desc limit #{offset},#{pageSize}")List<BookInfo> queryByPage(PageRequest pageRequest);
}// Service层
@Service
public class BookService {@Autowiredprivate BookInfoMapper bookMapper;public PageResult<BookInfo> getPage(PageRequest pageRequest) {int total = bookMapper.count();List<BookInfo> records = bookMapper.queryByPage(pageRequest);return new PageResult<>(total, records);}
}

2.4 数据库连接池

MyBatis 依赖数据库连接池管理连接,Spring Boot 默认使用 Hikari(性能优异),也可切换为 Druid(功能丰富)。

(1)切换为 Druid 连接池

引入依赖:

<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-3-starter</artifactId><version>1.2.21</version>
</dependency>

配置无需修改,Spring Boot 会自动识别并启用。

三、实战案例:图书管理系统核心功能

结合 Spring MVC 实现图书管理系统的核心功能,包含登录校验、图书 CRUD、分页查询等。

3.1 强制登录实现

通过 Session 校验用户登录状态,未登录则跳转至登录页:

// 常量定义
public class Constants {public static final String SESSION_USER_KEY = "session_user_key";
}// 登录接口
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/login")public boolean login(String username, String password, HttpSession session) {UserInfo user = userService.queryByUsername(username);if (user != null && password.equals(user.getPassword())) {user.setPassword(""); // 清空密码session.setAttribute(Constants.SESSION_USER_KEY, user);return true;}return false;}
}// 图书列表接口(登录校验)
@RestController
@RequestMapping("/book")
public class BookController {@Autowiredprivate BookService bookService;@RequestMapping("/getList")public Result<PageResult<BookInfo>> getList(PageRequest pageRequest, HttpSession session) {// 登录校验UserInfo user = (UserInfo) session.getAttribute(Constants.SESSION_USER_KEY);if (user == null) {return Result.unlogin(); // 未登录响应}PageResult<BookInfo> pageResult = bookService.getPage(pageRequest);return Result.success(pageResult);}
}

3.2 批量删除功能

// Mapper XML
<update id="batchDelete">update book_info set status=0 where id in<foreach collection="ids" item="id" open="(" close=")" separator=",">#{id}</foreach>
</update>// Controller
@RequestMapping("/batchDelete")
public boolean batchDelete(@RequestParam List<Integer> ids) {try {bookService.batchDelete(ids);return true;} catch (Exception e) {return false;}
}

四、MyBatis Generator:代码自动生成

MyBatis Generator(MBG)可根据数据库表结构自动生成实体类、Mapper 接口及 XML 文件,大幅提升开发效率。

4.1 配置 MBG 插件

pom.xml中添加插件:

<plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.6</version><configuration><configurationFile>src/main/resources/mybatis-generator/generatorConfig.xml</configurationFile><overwrite>true</overwrite></configuration><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency></dependencies>
</plugin>

4.2 编写配置文件

创建generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC"-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><generatorConfiguration><context id="Mysql" targetRuntime="MyBatis3Simple"><!-- 禁用注释 --><commentGenerator><property name="suppressAllComments" value="true"/></commentGenerator><!-- 数据库连接 --><jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://127.0.0.1:3306/book_test?serverTimezone=Asia/Shanghai"userId="root" password="root"></jdbcConnection><!-- 生成实体类 --><javaModelGenerator targetPackage="com.example.demo.model" targetProject="src/main/java"><property name="trimStrings" value="true"/></javaModelGenerator><!-- 生成XML文件 --><sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"/><!-- 生成Mapper接口 --><javaClientGenerator targetPackage="com.example.demo.mapper" targetProject="src/main/java" type="XMLMAPPER"/><!-- 生成指定表 --><table tableName="book_info" domainObjectName="BookInfo"><generatedKey column="id" sqlStatement="Mysql" identity="true"/></table></context>
</generatorConfiguration>

4.3 生成代码

在 Maven 插件中执行mybatis-generator:generate,即可自动生成实体类、Mapper 接口和 XML 文件。

五、总结与最佳实践

  1. 开发方式选择:简单 CRUD 用注解,复杂 SQL(动态 SQL、多表关联)用 XML。
  2. 参数注入:优先使用#{} 防止 SQL 注入,仅在排序字段、表名等场景使用${}并做好参数校验。
  3. 命名规范:数据库表 / 字段用蛇形命名(book_name),实体类用驼峰命名(bookName),开启map-underscore-to-camel-case自动转换。
  4. 代码复用:使用<sql><include>抽取重复 SQL 片段,减少冗余。
  5. 性能优化:合理使用数据库连接池,避免SELECT *查询,分页查询减少数据传输量。

MyBatis 以其轻量、灵活的特性成为 Java 持久层框架的主流选择,掌握其基础用法与进阶特性,能显著提升数据库操作效率与代码质量。建议结合实际项目多做练习,深入理解其参数映射与动态 SQL 的实现原理。

http://www.dtcms.com/a/392309.html

相关文章:

  • spring cloud 同一服务多实例 websocket跨实例无法共享Session 的解决
  • 如何通过pycharm使用AutoDL服务器
  • 【Linux】4G网卡-AT命令
  • 新版本附近停车场推荐系统demo,基于python+flask+协同推荐+空车位识别+yolov人工智能开发,开发语言python,数据库mysql
  • 《UE5_C++多人TPS完整教程》学习笔记55 ——《P56 网络更新频率(Net Update Frequency)》
  • 华为鸿蒙 ArkTS 实战:基于 RelationalStore 的 SQLite 实现本地数据持久化
  • 流行的 3D 文件格式及其用途指南
  • 腾讯发布一站式工作平台“混元3D Studio
  • TGRS2025 | 视觉语言模型 | 文本驱动自适应网络实现高光谱跨场景零样本分类
  • PyQt6之选项卡示例
  • 研学小程序前端平台开发项目需求规格说明书
  • 【Linux】netplan配置网络;ntp搭建时间服务器;shc将脚本转二进制;ty0tty创建虚拟串口
  • C# ADO.NET 操作学习记录
  • PIT 定时器寄存器配置
  • 算法代码讲座6:最小二乘法理论原理、典型案例与MATLAB实现
  • 【深入浅出】交叉熵损失函数——原理、公式与代码示例
  • Vue实现路由守卫
  • Coze源码分析-资源库-删除工作流-前端源码-核心接口
  • 安踏集团 X OB Cloud:新零售创新如何有“底”和有“数”
  • Web3艺术品交易应用方案
  • Spring 事务管理详解:保障数据一致性的实践指南
  • 软考中级-软件设计师 答题解题思路
  • Java IDEA学习之路:第二周课程笔记归纳
  • SQL语句一文通
  • Ubuntu22.04 双显卡系统使用集显 DRM 渲染的完整流程记录
  • Coze源码分析-资源库-删除工作流-后端源码-IDL/API/应用/领域
  • MySQL库和表的操作语句
  • python、类
  • NumPy高级技巧:向量化、广播与einsum的高效使用
  • GD32VW553-IOT 基于 vscode 的 msdk 移植(基于Cmake)