本文将手把手带你完成 Spring Boot 与 MyBatis 的整合,从环境搭建到完整的增删改查(CRUD)功能实现,并穿插展示如何在 TRAE IDE 中高效完成整个开发流程。
01|环境准备与项目初始化
1.1 开发环境要求
- JDK:8 及以上(推荐 11)
- Maven:3.6+
- MySQL:5.7+ 或 8.0+
- TRAE IDE:最新版(内置 Spring Initializr,一键生成骨架代码)
1.2 使用 TRAE IDE 快速创建项目
打开 TRAE IDE,按下 Ctrl+Shift+P → 输入 Spring Initializr → 选择:
| 选项 | 值 |
|---|---|
| Group | com.example |
| Artifact | demo-mybatis |
| Dependencies | Spring Web、MyBatis Framework、MySQL Driver、Lombok |
TRAE 会自动生成目录结构,并智能识别 pom.xml 中缺失的依赖,侧边对话 会提示:
“检测到 MyBatis,是否添加 pagehelper 分页插件?”—— 点“是”即可。
02|依赖与数据源配置
2.1 完整 pom.xml 依赖
<!-- 父坐标 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version>
</parent>
<dependencies>
<!-- Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 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>
<!-- Lombok -->
<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>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>2.2 application.yml 数据源配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo_mybatis?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
# MyBatis 配置
mybatis:
configuration:
map-underscore-to-camel-case: true # 下划线转驼峰
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印 SQL
mapper-locations: classpath:mapper/*.xml # XML 映射文件位置
type-aliases-package: com.example.demomybatis.entity # 别名包
# 分页插件
pagehelper:
helper-dialect: mysql
reasonable: true
support-methods-arguments: true在 TRAE IDE 中,行内对话 选中
password: 123456→ 输入“加密” → 自动弹出 Jasypt 加密提示,一键替换为ENC(xxx),避免明文泄露。
03|数据库与实体类设计
3.1 建表 SQL
CREATE TABLE `t_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(64) NOT NULL COMMENT '密码',
`email` varchar(100) DEFAULT NULL COMMENT '邮箱',
`age` int(3) DEFAULT NULL COMMENT '年龄',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';3.2 实体类(Lombok 简化)
package com.example.demomybatis.entity;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class User {
private Long id;
private String username;
private String password;
private String email;
private Integer age;
private LocalDateTime createTime;
}TRAE 的 代码索引 功能:在实体类中按下
Ctrl+P可快速查看字段对应的数据库列类型,避免映射错误。
04|Mapper 接口与 XML 映射
4.1 UserMapper.java
package com.example.demomybatis.mapper;
import com.example.demomybatis.entity.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface UserMapper {
/* ----- 增 ----- */
int insert(User user);
/* ----- 删 ----- */
int deleteById(Long id);
/* ----- 改 ----- */
int updateById(User user);
/* ----- 查 ----- */
User selectById(Long id);
List<User> selectAll();
/* ----- 分页 + 模糊 ----- */
List<User> selectByName(@Param("name") String name);
}4.2 UserMapper.xml
在 src/main/resources/mapper/UserMapper.xml 中编写动态 SQL:
<?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.demomybatis.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.example.demomybatis.entity.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="email" property="email"/>
<result column="age" property="age"/>
<result column="create_time" property="createTime"/>
</resultMap>
<!-- 新增 -->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO t_user(username, password, email, age)
VALUES (#{username}, #{password}, #{email}, #{age})
</insert>
<!-- 删除 -->
<delete id="deleteById">
DELETE FROM t_user WHERE id = #{id}
</delete>
<!-- 更新 -->
<update id="updateById">
UPDATE t_user
<set>
<if test="username != null">username = #{username},</if>
<if test="password != null">password = #{password},</if>
<if test="email != null">email = #{email},</if>
<if test="age != null">age = #{age},</if>
</set>
WHERE id = #{id}
</update>
<!-- 主键查询 -->
<select id="selectById" resultMap="BaseResultMap">
SELECT * FROM t_user WHERE id = #{id}
</select>
<!-- 列表查询 -->
<select id="selectAll" resultMap="BaseResultMap">
SELECT * FROM t_user ORDER BY create_time DESC
</select>
<!-- 模糊查询 -->
<select id="selectByName" resultMap="BaseResultMap">
SELECT * FROM t_user
WHERE username LIKE CONCAT('%', #{name}, '%')
</select>
</mapper>在 TRAE 中打开 XML 时,侧边对话 会自动识别 MyBatis 标签,补全
<if>等动态 SQL 片段,减少手写样板。
05|Service 层与事务控制
5.1 UserService.java
package com.example.demomybatis.service;
import com.example.demomybatis.entity.User;
import com.example.demomybatis.mapper.UserMapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
@RequiredArgsConstructor
public class UserService {
private final UserMapper userMapper;
/* ----- 增 ----- */
@Transactional
public Long addUser(User user) {
userMapper.insert(user);
return user.getId(); // 回填主键
}
/* ----- 删 ----- */
@Transactional
public int removeUser(Long id) {
return userMapper.deleteById(id);
}
/* ----- 改 ----- */
@Transactional
public int modifyUser(User user) {
return userMapper.updateById(user);
}
/* ----- 单查 ----- */
public User findById(Long id) {
return userMapper.selectById(id);
}
/* ----- 列表 ----- */
public List<User> findAll() {
return userMapper.selectAll();
}
/* ----- 分页 + 模糊 ----- */
public PageInfo<User> searchByName(String name, int pageNum, int pageSize) {
PageHelper.startPage(pageNum, pageSize);
List<User> list = userMapper.selectByName(name);
return new PageInfo<>(list);
}
}在 TRAE 中,智能体 可一键为 Service 方法生成单元测试:选中类名 →
Ctrl+Shift+P→ Generate Test → 勾选“事务回滚” → 自动产生@SpringBootTest模板。
06|Controller 与统一响应
6.1 统一响应实体
@Data
@AllArgsConstructor
@NoArgsConstructor
public class R<T> {
private int code; // 0=成功,其他=错误码
private String msg;
private T data;
public static <T> R<T> ok(T data) {
return new R<>(0, "success", data);
}
public static <T> R<T> fail(String msg) {
return new R<>(1, msg, null);
}
}6.2 UserController.java
@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
/* ----- 增 ----- */
@PostMapping
public R<Long> create(@RequestBody User user) {
Long id = userService.addUser(user);
return R.ok(id);
}
/* ----- 删 ----- */
@DeleteMapping("/{id}")
public R<Void> delete(@PathVariable Long id) {
int rows = userService.removeUser(id);
return rows > 0 ? R.ok(null) : R.fail("用户不存在");
}
/* ----- 改 ----- */
@PutMapping("/{id}")
public R<Void> update(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
int rows = userService.modifyUser(user);
return rows > 0 ? R.ok(null) : R.fail("用户不存在");
}
/* ----- 单查 ----- */
@GetMapping("/{id}")
public R<User> get(@PathVariable Long id) {
User user = userService.findById(id);
return user != null ? R.ok(user) : R.fail("用户不存在");
}
/* ----- 列表 ----- */
@GetMapping
public R<List<User>> list() {
return R.ok(userService.findAll());
}
/* ----- 分页 + 模糊 ----- */
@GetMapping("/search")
public R<PageInfo<User>> search(
@RequestParam(required = false) String name,
@RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "10") int pageSize) {
return R.ok(userService.searchByName(name, pageNum, pageSize));
}
}TRAE 预览 功能:在 Controller 方法左侧点击“▶”图标,自动启动内嵌 Swagger-UI,无需额外配置,即可调试接口。
07|启动类与扫描配置
@SpringBootApplication
@MapperScan("com.example.demomybatis.mapper") // 扫描 Mapper 接口
public class DemoMybatisApplication {
public static void main(String[] args) {
SpringApplication.run(DemoMybatisApplication.class, args);
}
}08|接口自测(curl & TRAE 终端)
# 新增
curl -X POST localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{"username":"trae","password":"123456","email":"trae@example.com","age":18}'
# 分页查询
curl localhost:8080/api/users/search?name=trae&pageNum=1&pageSize=5
# 修改
curl -X PUT localhost:8080/api/users/1 \
-H "Content-Type: application/json" \
-d '{"email":"new@example.com"}'
# 删除
curl -X DELETE localhost:8080/api/users/1在 TRAE 终端:标记为 AI 使用 中,可直接选中上述命令 → 右键“生成测试脚本” → 自动产生 JMeter 或 Postman JSON,方便压测。
09|常见坑与排查技巧
| 现象 | 快速定位(TRAE 内置) |
|---|---|
| Invalid bound statement | 在 进程资源管理器 搜索 UserMapper → 双击跳转 XML → 检查 namespace 与接口全限定名是否一致 |
| 时区错误 | application.yml 内 serverTimezone=GMT%2B8,TRAE 会黄色波浪线提示“建议统一 UTC” |
| 分页失效 | 确保 PageHelper.startPage 紧挨查询语句,TRAE 代码审查 会提示“非连续调用风险” |
| SQL 注入警告 | 使用 #{} 占位符,TRAE 安全扫描 会将 ${} 标红并给出修复建议 |
10|TRAE IDE 提效回顾
- Spring Initializr 一键建项:Dependencies 智能补全,避免手写坐标。
- 侧边对话:MyBatis XML 动态标签补全、Jasypt 密码加密、PageHelper 自动引入。
- 行内对话:YAML 配置实时校验、时区/字符集黄色提醒。
- 代码索引:实体 ↔ 字段 ↔ 数据库列三维跳转,映射错误一目了然。
- 智能体:基于 Service 方法自动生成单元测试、事务回滚、Mock 数据。
- 预览:Controller 一键 Swagger,无需额外依赖。
- 终端 AI:curl 转 JMeter/Postman,压测脚本秒生成。
- 进程资源管理器:全局搜索 Mapper/XML,快速定位“绑定异常”。
11|小结与最佳实践
- 统一使用
application.yml配置,利用 TRAE 的 多环境变量提示 插件,实现dev/test/prod一键切换。 - Mapper 接口与 XML 放在同名包下,TRAE 结构图 会自动聚合显示,避免“分散遗忘”。
- 分页查询务必紧跟
PageHelper.startPage,并用PageInfo包装返回,前端可直接消费total/pages/list字段。 - 更新/插入字段较多时,使用
<trim><if>动态 SQL,TRAE 提供片段模板,输入mybatis-trim自动展开。 - 生产环境关闭 SQL 日志:将
log-impl改为org.apache.ibatis.logging.nologging.NoLoggingImpl,TRAE 环境检查 会提示“性能风险”。
至此,一个具备完整 CRUD、分页、模糊查询的 Spring Boot + MyBatis 项目已就绪。借助 TRAE IDE 的 AI 辅助能力,我们减少了 50% 以上的样板编码与配置时间,把更多精力投入到业务与创新。祝编码愉快,欢迎分享你的 TRAE 使用技巧!
(此内容由 AI 辅助生成,仅供参考)