MyBatis是一个优秀的 Java持久层框架,它通过XML或注解的方式将 SQL 与 Java 对象进行映射,简化了JDBC操作。
MyBatis优点:
- 灵活性强:SQL可定制化
- 减少JDBC样板代码:自动处理连接、参数、结果集
- 学习成本低:相比Hibernate更简单
- 与Spring集成良好:通过MyBatis-Spring整合
一、与 SpringBoot 集成
1.添加依赖
手动添加依赖
xml
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.5.0</version>
</dependency>
基于SpringBoot创建工程(推荐)
通过IDEA创建:

pom.xml依赖如下:
xml
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.5</version>
<scope>test</scope>
</dependency>
</dependencies>
2.配置 application.yml
yaml
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/数据库名
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
mybatis:
configuration:
# 控制台输出日志(调试专用)
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 自动驼峰命名转换
map-underscore-to-camel-case: true
3.数据准备
- 数据库创建用户表user
- 创建对应实体类User,存放在
com.example.pojo包下。
java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id; //ID
private String username; //用户名
private String password; //密码
private String name; //姓名
private Integer age; //年龄
}
4.编写MyBatis程序
在SpringBoot工程中引导类 所在的包下,创建一个mapper 包。在mapper 包下创建一个接口UserMapper,这是一个持久层接口。
UserMapper接口:
java
import com.example.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface UserMapper {
@Select("select * from user")
public List<User> findAll();
}
- @Mapper注解:作用在单个 Mapper 接口上,标记这个接口是MyBatis的Mapper接口,告诉 Spring 要为这个接口创建代理实现类并纳入容器管理
- @Select注解:用于在 Mapper 方法上声明 查询类SQL语句 ,替代XML中的
<select>标签
5.在Service层使用
在 com.example.service 包创建 UserService 类:
java
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public List<User> findAll() {
return userMapper.findAll();
}
}
6.启动项目
通过 Controller 层调用 Service 层,再调用 Mapper 接口,执行SQL语句并返回结果集。
二、占位符
MyBatis中提供两种符号:
- #{...}:占位符,执行时会将
#{...}替换成?,生成预编译SQL - ${...}:拼接符,直接将参数拼接在SQL语句中,存在SQL注入问题
使用示例:
java
/**
* 根据id查询
*/
@Select("select * from user where id = #{id}")
public User selectUserById(Integer id);
如果在SQL语句中,需要传递多个参数,可以把多个参数封装到一个对象中。然后在SQL语句中通过 #{对象属性名} 的方式,获取到对象中封装的属性值。
封装对象使用示例:
java
/**
* 添加用户
*/
@Insert("insert into user(username,password,name,age) values(#{username},#{password},#{name},#{age})")
public void insert(User user);
三、SQL执行注解(CURD基础)
这是最常用的四类注解,分别对应增、删、改、查操作,覆盖绝大多数基础 SQL 场景:
| 注解 | 作用 | 对应XML标签 | 返回值说明 |
|---|---|---|---|
| @Select | 执行查询(SELECT)语句 | <select> | 单条结果返回实体 / Map / 基本类型;多条返回 List;无结果返回 null / 空 List |
| @Insert | 执行插入(INSERT)语句 | <insert> | 无特殊配置返回受影响行数;配置 useGeneratedKeys 可返回自增主键 |
| @Update | 执行更新(UPDATE)语句 | <update> | 返回受影响的行数(int/Integer) |
| @Delete | 执行删除(DELETE)语句 | <delete> | 返回受影响的行数(int/Integer) |
四、XML映射文件
使用MyBatis的注解方式,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,推荐使用XML映射文件。
1.基本使用步骤
1.1.创建XML映射文件
XML映射文件位置建议与 Mapper 接口同包,如果Mapper 接口在 src/main/java/com/example/mapper 包下,那么XML映射文件建议放在 src/main/resources/com/example/mapper 目录下。如果使用IDEA创建,建议右击 resources 新建目录 com/example/mapper。
1.2.编写XML映射文件
xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace 必须对应 Mapper 接口的全限定名 -->
<mapper namespace="com.example.mapper.UserMapper">
<!--查询操作-->
<!--id 要与 Mapper 接口中的方法名一致,并且 resultType 要与返回类型保持一致-->
<select id="findAll" resultType="com.example.pojo.User">
select * from user
</select>
</mapper>
1.3.Mapper 文件
java
package com.example.mapper;
import com.example.pojo.User;
@Mapper
public interface UserMapper {
/**
* 查询所有的用户
*/
public List<User> findAll();
}
2.其他常用标签
2.1.动态SQL标签
| 标签 | 作用 |
|---|---|
| <if> | 根据条件判断是否拼接某段 SQL(如 test="name != null") |
| <where> | 自动包裹条件 SQL,且智能去除开头的 AND/OR,避免 SQL 语法错误 |
| <set> | 用于 UPDATE 语句,自动包裹更新字段,且去除末尾的逗号 |
| <foreach> | 遍历集合 / 数组,拼接批量 SQL(如 IN 条件、批量插入) |
动态SQL标签示例:
- <if> + <where>(多条件查询)
xml
<select id="selectUsers" resultType="User">
SELECT id, name, age FROM user
<where>
<!-- 非空时才拼接该条件,且 where 自动处理开头的 AND -->
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
- <set>(动态更新)
xml
<update id="updateUser">
UPDATE user
<set>
<!-- 非空字段才更新,set 自动去除末尾逗号 -->
<if test="name != null">name = #{name},</if>
<if test="age != null">age = #{age},</if>
</set>
WHERE id = #{id}
</update>
- <foreach>(批量查询 / 插入)
xml
<!-- 批量查询(IN 条件) -->
<select id="selectUserByIds" resultType="User">
SELECT id, name, age FROM user
WHERE id IN
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>
<!-- 批量插入 -->
<insert id="batchInsertUsers">
INSERT INTO user(name, age) VALUES
<foreach collection="users" item="user" separator=",">
(#{user.name}, #{user.age})
</foreach>
</insert>
2.2.结果映射标签(处理字段与实体的映射)
用于解决数据库列名与Java实体属性名不一致、关联查询(一对一/一对多)等场景的映射问题:
| 标签 | 作用 |
|---|---|
| <resultMap> | 定义自定义结果映射规则(核心标签),可复用 |
| <result> | 映射普通字段(列名→属性名) |
| <id> | 映射主键字段(与 类似,但标记为主键,优化性能) |
| <association> | 一对一关联映射(如 User 关联 UserInfo) |
| <collection> | 一对多关联映射(如 User 关联多个 Order) |
结果映射标签示例:
xml
<!-- 定义结果映射,解决列名与属性名不一致 + 一对一关联 -->
<resultMap id="UserResultMap" type="User">
<!-- 主键映射 -->
<id column="id" property="userId"/>
<!-- 普通字段映射 -->
<result column="user_name" property="userName"/>
<result column="user_age" property="userAge"/>
<!-- 一对一关联(User 关联 UserInfo) -->
<association property="userInfo" javaType="UserInfo">
<id column="info_id" property="infoId"/>
<result column="phone" property="phone"/>
</association>
<!-- 一对多关联(User 关联多个 Order) -->
<collection property="orders" ofType="Order">
<id column="order_id" property="orderId"/>
<result column="order_name" property="orderName"/>
</collection>
</resultMap>
<!-- 使用自定义 resultMap -->
<select id="selectUserById" resultMap="UserResultMap">
SELECT u.id, u.user_name, u.user_age,
ui.info_id, ui.phone,
o.order_id, o.order_name
FROM user u
LEFT JOIN user_info ui ON u.id = ui.user_id
LEFT JOIN order o ON u.id = o.user_id
WHERE u.id = #{id}
</select>