Spring Boot 实战:MyBatis 操作数据库
(2026年3月视角,基于 Spring Boot 4.x + MyBatis 纯原生 / MyBatis-Plus 增强版)
在 2026 年,Spring Boot 项目中操作数据库的主流选择仍是:
- JPA/Hibernate:适合快速 CRUD + 对象关系复杂场景
- MyBatis:适合复杂 SQL、性能敏感、对 SQL 掌控欲强的项目
- MyBatis-Plus:MyBatis 的“增强版”,CRUD 零 SQL + 代码生成 + 条件构造器,生产使用率已超过纯 MyBatis
我们今天重点实战 两种方式(纯 MyBatis + MyBatis-Plus),从零到生产可用级别。
一、项目初始化(推荐方式)
使用 Spring Initializr 或 IDEA 创建项目:
- Spring Boot:4.0.x 或更高
- 依赖(Maven):
<!-- 核心 web + MyBatis 方式一:纯 MyBatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>4.0.0</version> <!-- 2026年最新稳定版 -->
</dependency>
<!-- 方式二:MyBatis-Plus(推荐生产使用,省事 70%+) -->
<!-- 替换上面 mybatis-spring-boot-starter,用下面这个 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot4-starter</artifactId>
<version>3.5.16</version> <!-- 最新版 2026年1月发布 -->
</dependency>
<!-- 数据库驱动(以 MySQL 为例) -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 可选:连接池 Druid(监控强)或 Hikari(默认轻量) -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>1.2.23</version>
</dependency>
<!-- Lombok 简化实体 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
application.yml(通用配置):
spring:
datasource:
url: jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource # 或不写默认 Hikari
mybatis-plus: # 如果用 MyBatis-Plus
mapper-locations: classpath*:mapper/**/*.xml
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 开发阶段打印 SQL
# 如果纯 MyBatis(不带 -plus)
# mybatis:
# mapper-locations: classpath:mapper/*.xml
# configuration:
# map-underscore-to-camel-case: true
二、方式一:纯 MyBatis(XML + 注解混合)
1. 实体类
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class User {
private Long id;
private String username;
private String password;
private Integer age;
private LocalDateTime createTime;
}
2. Mapper 接口
import org.apache.ibatis.annotations.*;
@Mapper
public interface UserMapper {
@Select("SELECT * FROM user WHERE id = #{id}")
User findById(Long id);
@Insert("INSERT INTO user (username, password, age, create_time) " +
"VALUES (#{username}, #{password}, #{age}, #{createTime})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
// 动态 SQL 用 XML
List<User> findByCondition(@Param("username") String username,
@Param("minAge") Integer minAge);
}
3. XML Mapper(resources/mapper/UserMapper.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 namespace="com.example.mapper.UserMapper">
<select id="findByCondition" resultType="com.example.entity.User">
SELECT * FROM user
<where>
<if test="username != null and username != ''">
AND username LIKE CONCAT('%', #{username}, '%')
</if>
<if test="minAge != null">
AND age >= #{minAge}
</if>
</where>
ORDER BY create_time DESC
</select>
</mapper>
4. Service + Controller 简单使用
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User getUser(Long id) {
return userMapper.findById(id);
}
}
三、方式二:MyBatis-Plus(强烈推荐,CRUD 基本零 SQL)
1. 实体类(加 MP 注解)
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("user") // 可省略,如果表名=类名小写
public class User {
@TableId(type = IdType.AUTO) // 自增主键
private Long id;
private String username;
private String password;
private Integer age;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
@TableLogic // 逻辑删除
private Integer deleted = 0;
}
2. 配置自动填充(可选,但推荐)
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}
3. Mapper 接口(继承 BaseMapper 即可获得 20+ CRUD 方法)
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 自定义方法仍可写
@Select("SELECT * FROM user WHERE username = #{username}")
User findByUsername(String username);
}
4. Service(推荐继承 IService / ServiceImpl)
public interface UserService extends IService<User> {
// 自定义业务方法
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
// 自动获得 save、removeById、getById、updateById、list 等方法
}
5. 常用 MP 操作示例
// 新增
User user = new User();
user.setUsername("zhongyang");
user.setAge(18);
userService.save(user); // 自动填充 createTime 等
// 修改
userService.updateById(user);
// 查询
User one = userService.getById(1L);
// 条件构造器(最强大功能)
LambdaQueryWrapper<User> qw = new LambdaQueryWrapper<>();
qw.like(User::getUsername, "yang")
.ge(User::getAge, 18)
.orderByDesc(User::getCreateTime);
List<User> list = userService.list(qw);
// 分页
IPage<User> page = userService.page(new Page<>(1, 10), qw);
四、2026年生产避坑 & 最佳实践对比
| 维度 | 纯 MyBatis | MyBatis-Plus(推荐) | 建议选择场景 |
|---|---|---|---|
| CRUD 代码量 | 多(需写 insert/select 等) | 极少(继承 BaseMapper/Service) | MP 胜出 |
| 动态 SQL | XML 强大 | 条件构造器 + XML 都强 | 差不多 |
| 代码生成 | 需第三方插件 | 内置 Generator(可生成 entity/mapper/service/controller) | MP 胜出 |
| 分页 | 需 PageHelper 或手动 | 内置 PaginationInterceptor | MP 更方便 |
| 逻辑删除 | 手动 | @TableLogic 自动 | MP 胜出 |
| 性能 | 接近原生 | 略有增强器开销,但差距微乎其微 | 几乎相同 |
| 学习曲线 | 稍陡 | 更平滑(CRUD 零 SQL) | 新手/中型项目首选 MP |
一句话总结:
2026 年,除非对 SQL 极致掌控或遗留系统迁移,否则 直接上 MyBatis-Plus,能省 60%+ 的重复代码,维护性更好。
你的项目现在是用纯 MyBatis 还是想直接切 MyBatis-Plus?
需要我贴出 代码生成器完整示例、多表关联查询、事务 + 分布式事务、druid 监控集成 等具体代码吗?
告诉我你的当前阶段(刚起步 / 已接入但想优化 / 遇到具体问题),我继续陪你写下去。