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

MyBatis完全学习指南

目录

1. MyBatis简介

1.1 什么是MyBatis?

1.2 MyBatis架构

1.3 MyBatis与其他持久层框架对比

2. 环境搭建与配置

2.1 Maven依赖配置

2.2 项目结构

3. 核心配置文件详解

3.1 mybatis-config.xml主配置文件

3.2 database.properties配置文件

3.3 重要设置详解

4. 映射文件(Mapper)详解

4.1 基本映射文件结构

4.2 实体类示例

4.3 Mapper接口

5. 基本CRUD操作

5.1 查询操作(Select)

5.2 插入操作(Insert)

5.3 更新操作(Update)

5.4 删除操作(Delete)

5.5 使用示例

6. 参数传递详解

6.1 单个参数

6.2 多个参数

方式1:使用@Param注解(推荐)

方式2:使用Map传参

方式3:使用实体对象传参

6.3 集合参数

7. 结果映射详解

7.1 基础结果映射

自动映射(列名与属性名一致)

列名与属性名不一致的处理

7.2 自定义结果映射(ResultMap)

7.3 复杂对象映射

一对一关联

一对多关联

7.4 分步查询(延迟加载)

8. 动态SQL详解

8.1 if标签

8.2 where标签

8.3 choose、when、otherwise标签

8.4 trim标签

8.5 set标签

8.6 foreach标签

8.7 bind标签

8.8 sql标签和include标签

9. 缓存机制

9.1 一级缓存(SqlSession级别)

9.2 二级缓存(Mapper级别)

开启二级缓存

二级缓存配置详解

控制缓存行为

9.3 自定义缓存

集成EhCache

9.4 缓存最佳实践

10. 注解开发

10.1 基本CRUD注解

10.2 复杂查询注解

动态SQL

SQL提供者类

10.3 关联映射注解

一对一关联

一对多关联

10.4 注解配置缓存

10.5 混合使用XML和注解

11. 插件机制

11.1 插件工作原理

11.2 自定义插件示例

SQL执行时间监控插件

分页插件

11.3 插件注册

在mybatis-config.xml中注册

使用示例

11.4 常用开源插件

PageHelper分页插件

12. 与Spring集成

12.1 Spring配置方式

Maven依赖

Spring配置文件

12.2 Spring Boot配置方式

依赖配置

application.yml配置

启动类配置

12.3 Service层实现

12.4 Controller层实现

13. 最佳实践与常见问题

13.1 最佳实践

命名规范

性能优化

代码组织

13.2 常见问题及解决方案

问题1:参数传递问题

问题2:结果映射问题

问题3:SQL注入问题

问题4:事务失效问题

问题5:缓存问题

问题6:连接池配置问题

13.3 调试技巧

开启SQL日志

使用MyBatis日志插件

性能监控

总结

优点

适用场景

学习建议


1. MyBatis简介

1.1 什么是MyBatis?

MyBatis是一个优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射。MyBatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。

核心特点:

  • 简单易学:本身就很小且简单
  • 灵活:不会对应用程序或者数据库的现有设计强加任何影响
  • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离
  • 支持动态SQL:根据不同条件拼接SQL语句

1.2 MyBatis架构

应用程序↓
SqlSession (会话)↓
Executor (执行器)↓
StatementHandler (语句处理器)↓
ParameterHandler (参数处理器) → ResultSetHandler (结果处理器)↓
JDBC↓
数据库

1.3 MyBatis与其他持久层框架对比

特性MyBatisHibernateJPA
学习难度简单复杂中等
SQL控制完全控制部分控制部分控制
性能优化容易复杂中等
开发效率中等

2. 环境搭建与配置

2.1 Maven依赖配置

<!-- pom.xml -->
<dependencies><!-- MyBatis核心依赖 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.13</version></dependency><!-- 数据库驱动,以MySQL为例 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><!-- 日志依赖(可选) --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.36</version></dependency>
</dependencies>

2.2 项目结构

src/main/java/
├── com/example/
│   ├── entity/          # 实体类
│   ├── mapper/          # Mapper接口
│   ├── service/         # 业务层
│   └── utils/           # 工具类
src/main/resources/
├── mybatis-config.xml   # MyBatis主配置文件
├── mapper/              # SQL映射文件
└── log4j.properties     # 日志配置

3. 核心配置文件详解

3.1 mybatis-config.xml主配置文件

<?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="database.properties"/><!-- 设置 --><settings><!-- 开启驼峰命名转换 --><setting name="mapUnderscoreToCamelCase" value="true"/><!-- 开启延迟加载 --><setting name="lazyLoadingEnabled" value="true"/><!-- 设置超时时间 --><setting name="defaultStatementTimeout" value="30"/><!-- 开启二级缓存 --><setting name="cacheEnabled" value="true"/></settings><!-- 类型别名 --><typeAliases><!-- 单个别名 --><typeAlias type="com.example.entity.User" alias="User"/><!-- 包扫描 --><package name="com.example.entity"/></typeAliases><!-- 类型处理器 --><typeHandlers><typeHandler handler="com.example.handler.MyTypeHandler"/></typeHandlers><!-- 环境配置 --><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="mapper/UserMapper.xml"/><!-- 使用完全限定资源定位符(URL) --><!-- <mapper url="file:///var/mappers/UserMapper.xml"/> --><!-- 使用映射器接口实现类的完全限定类名 --><!-- <mapper class="com.example.mapper.UserMapper"/> --><!-- 将包内的映射器接口实现全部注册为映射器 --><!-- <package name="com.example.mapper"/> --></mappers>
</configuration>

3.2 database.properties配置文件

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
jdbc.username=root
jdbc.password=123456

3.3 重要设置详解

设置名描述有效值默认值
mapUnderscoreToCamelCase开启驼峰命名转换true/falsefalse
lazyLoadingEnabled延迟加载的全局开关true/falsefalse
cacheEnabled全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存true/falsetrue
defaultStatementTimeout设置超时时间任意正整数未设置

4. 映射文件(Mapper)详解

4.1 基本映射文件结构

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper"><!-- 这里写SQL映射 -->
</mapper>

4.2 实体类示例

public class User {private Long id;private String username;private String password;private String email;private Date createTime;// 构造方法public User() {}public User(String username, String password, String email) {this.username = username;this.password = password;this.email = email;}// getter和setter方法public Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }// ... 其他getter/setter方法@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +", email='" + email + '\'' +", createTime=" + createTime +'}';}
}

4.3 Mapper接口

public interface UserMapper {// 根据ID查询用户User selectById(Long id);// 查询所有用户List<User> selectAll();// 添加用户int insert(User user);// 更新用户int update(User user);// 删除用户int deleteById(Long id);// 根据用户名查询User selectByUsername(String username);// 分页查询List<User> selectByPage(@Param("offset") int offset, @Param("limit") int limit);
}

5. 基本CRUD操作

5.1 查询操作(Select)

<!-- 根据ID查询用户 -->
<select id="selectById" resultType="User">SELECT id, username, password, email, create_timeFROM user WHERE id = #{id}
</select><!-- 查询所有用户 -->
<select id="selectAll" resultType="User">SELECT id, username, password, email, create_timeFROM userORDER BY create_time DESC
</select><!-- 根据用户名查询 -->
<select id="selectByUsername" resultType="User">SELECT id, username, password, email, create_timeFROM user WHERE username = #{username}
</select><!-- 分页查询 -->
<select id="selectByPage" resultType="User">SELECT id, username, password, email, create_timeFROM userORDER BY create_time DESCLIMIT #{offset}, #{limit}
</select>

5.2 插入操作(Insert)

<!-- 插入用户 -->
<insert id="insert" parameterType="User">INSERT INTO user(username, password, email, create_time)VALUES(#{username}, #{password}, #{email}, NOW())
</insert><!-- 插入用户并返回主键 -->
<insert id="insertAndReturnKey" parameterType="User" useGeneratedKeys="true" keyProperty="id">INSERT INTO user(username, password, email, create_time)VALUES(#{username}, #{password}, #{email}, NOW())
</insert><!-- 批量插入 -->
<insert id="insertBatch" parameterType="list">INSERT INTO user(username, password, email, create_time)VALUES<foreach collection="list" item="user" separator=",">(#{user.username}, #{user.password}, #{user.email}, NOW())</foreach>
</insert>

5.3 更新操作(Update)

<!-- 更新用户 -->
<update id="update" parameterType="User">UPDATE user SET username = #{username},password = #{password},email = #{email}WHERE id = #{id}
</update><!-- 动态更新(只更新不为空的字段) -->
<update id="updateSelective" parameterType="User">UPDATE user<set><if test="username != null and username != ''">username = #{username},</if><if test="password != null and password != ''">password = #{password},</if><if test="email != null and email != ''">email = #{email},</if></set>WHERE id = #{id}
</update>

5.4 删除操作(Delete)

<!-- 根据ID删除用户 -->
<delete id="deleteById" parameterType="long">DELETE FROM user WHERE id = #{id}
</delete><!-- 批量删除 -->
<delete id="deleteBatch" parameterType="list">DELETE FROM user WHERE id IN<foreach collection="list" item="id" open="(" separator="," close=")">#{id}</foreach>
</delete><!-- 根据条件删除 -->
<delete id="deleteByCondition">DELETE FROM user WHERE create_time &lt; #{beforeDate}
</delete>

5.5 使用示例

public class UserService {private SqlSession sqlSession;private UserMapper userMapper;public UserService() {// 获取SqlSessionsqlSession = MyBatisUtils.getSqlSession();userMapper = sqlSession.getMapper(UserMapper.class);}// 查询用户public User getUserById(Long id) {return userMapper.selectById(id);}// 添加用户public boolean addUser(User user) {try {int result = userMapper.insert(user);sqlSession.commit(); // 提交事务return result > 0;} catch (Exception e) {sqlSession.rollback(); // 回滚事务e.printStackTrace();return false;}}// 关闭资源public void close() {if (sqlSession != null) {sqlSession.close();}}
}

6. 参数传递详解

6.1 单个参数

<!-- 基本类型参数 -->
<select id="selectById" resultType="User">SELECT * FROM user WHERE id = #{id}
</select><!-- 字符串参数 -->
<select id="selectByUsername" resultType="User">SELECT * FROM user WHERE username = #{username}
</select>
// 接口方法
User selectById(Long id);
User selectByUsername(String username);

6.2 多个参数

方式1:使用@Param注解(推荐)
// 接口方法
List<User> selectByUsernameAndEmail(@Param("username") String username, @Param("email") String email);
<select id="selectByUsernameAndEmail" resultType="User">SELECT * FROM user WHERE username = #{username} AND email = #{email}
</select>
方式2:使用Map传参
// 接口方法
List<User> selectByMap(Map<String, Object> params);
<select id="selectByMap" resultType="User">SELECT * FROM user WHERE username = #{username} AND email = #{email}
</select>
// 使用示例
Map<String, Object> params = new HashMap<>();
params.put("username", "admin");
params.put("email", "admin@example.com");
List<User> users = userMapper.selectByMap(params);
方式3:使用实体对象传参
// 查询条件实体
public class UserQuery {private String username;private String email;private Date startDate;private Date endDate;// getter/setter...
}// 接口方法
List<User> selectByQuery(UserQuery query);
<select id="selectByQuery" resultType="User">SELECT * FROM user WHERE 1=1<if test="username != null and username != ''">AND username LIKE CONCAT('%', #{username}, '%')</if><if test="email != null and email != ''">AND email = #{email}</if><if test="startDate != null">AND create_time >= #{startDate}</if><if test="endDate != null">AND create_time &lt;= #{endDate}</if>
</select>

6.3 集合参数

// 接口方法
List<User> selectByIds(@Param("ids") List<Long> ids);
int deleteBatch(@Param("ids") List<Long> ids);
<!-- 根据ID列表查询 -->
<select id="selectByIds" resultType="User">SELECT * FROM user WHERE id IN<foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach>
</select><!-- 批量删除 -->
<delete id="deleteBatch">DELETE FROM user WHERE id IN<foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach>
</delete>

7. 结果映射详解

7.1 基础结果映射

自动映射(列名与属性名一致)
<select id="selectById" resultType="User">SELECT id, username, password, email FROM user WHERE id = #{id}
</select>
列名与属性名不一致的处理

方式1:使用别名

<select id="selectById" resultType="User">SELECT id,username,password,email,create_time AS createTimeFROM user WHERE id = #{id}
</select>

方式2:开启驼峰命名转换

<!-- mybatis-config.xml中配置 -->
<setti
http://www.dtcms.com/a/269799.html

相关文章:

  • 算法题练习3-判定链表是否是回文串
  • 【踩坑随笔】PlatformIO导入Arduino项目出现的问题
  • STM32第十八天 ESP8266-01S和电脑实现串口通信
  • HTTP/3.x协议详解:基于QUIC的下一代Web传输协议
  • 小红书APP品牌升级,启用新品牌口号“你的生活兴趣社区”
  • 2025年社会学与安全科学国际会议 (ICSSS 2025)
  • 【AI News | 20250707】每日AI进展
  • C++ dijkstra 最短路径算法
  • c语言学习_函数递归
  • 数学建模:非线性规划:凸规划问题
  • 【AI智能体】智能音视频-基于乐鑫 ESP32 实现音视频通话
  • ICML 2025 | TimeBridge : 巧妙化解非平稳性难题,精准预测长短结合!
  • Redis:高性能内存数据库与缓存利器
  • 验证KANO问题时合适的行为指标(如点击率、转化率等)来匹配问卷目标的一些尝试
  • 【论文翻译】用于大感受野的小波卷积 Wavelet Convolutions for Large Receptive Fields
  • 一天一道Sql题(day01)
  • Java武林:虚拟机之道 第二章:心法传承 - 类加载机制
  • three案例 Three.js波纹效果演示
  • “Jmeter中 xxx.jtl:1:1: Fatal Error! 前言中不允许有内容”的解决办法
  • 开源 SIP 协议栈介绍
  • INNER JOIN, LEFT JOIN, RIGHT JOIN 的区别
  • 字节面试被问到“手机号存储选 Int 还是 String”!
  • 区块链技术促进算力生态发展的具体案例
  • Python 机器学习核心入门与实战进阶 Day 6 - 模型保存与加载(joblib / pickle)
  • 2025年Linux安装MySQL详细教程
  • mysql-笔记
  • 服务器经常出现蓝屏是什么原因导致的?如何排查和修复?
  • Nature子刊:EPFL-ANU团队实现晶格对称性编程手性,双通道光学加密动态范围创1.6新高
  • Element-Plus-全局自动引入图标组件,无需每次import
  • 集群与集群应用