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

SpringBoot 整合 MyBatis 完整实战

SpringBoot + MyBatis 可以说是国内后端开发最经典、最常用的组合了。本篇文章就来介绍一下SpringBoot如何整合MyBatis,实现数据表的增删改查。


一、引言

SpringBoot 整合 MyBatis 是国内 Java 后端最主流的持久层方案:

  • • 灵活可控,SQL 可优化、可维护

  • • 适合复杂查询、多表关联、统计报表

  • • 配合 XML 或注解开发效率极高

  • • 分页、事务、缓存生态成熟

这篇文章会带你完整实现:

  1. 1. 依赖与配置

  2. 2. 数据库建表

  3. 3. 实体类、Mapper接口、XML映射

  4. 4. 单表增删改查

  5. 5. 多条件动态查询

  6. 6. 分页查询(PageHelper)

  7. 7. Service 事务控制

  8. 8. Controller 接口统一返回

  9. 9. 真实开发规范 + 高频坑点解决


二、引入完整依赖(pom.xml)

包含:MyBatis启动器、MySQL驱动、分页插件、Lombok、连接池

<!-- SpringBoot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MyBatis SpringBoot Starter --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.3.2</version> </dependency> <!-- MySQL 驱动 --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <!-- 分页插件 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper-spring-boot-starter</artifactId> <version>1.4.7</version> </dependency> <!-- Lombok 简化实体 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>

三、application.yml 完整配置

server: port:8080 spring: # 数据源配置 datasource: url:jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true username:root password:123456 driver-class-name:com.mysql.cj.jdbc.Driver # MyBatis 配置 mybatis: # XML 文件路径 mapper-locations:classpath:mapper/*.xml # 实体类别名 type-aliases-package:com.demo.entity configuration: # 下划线自动转驼峰(必须开) map-underscore-to-camel-case:true # 打印SQL(开发环境打开) log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

四、建表 SQL(user 表)

CREATE TABLE `user` ( `id` bigintNOT NULL AUTO_INCREMENT COMMENT '主键ID', `username` varchar(50) NOT NULL COMMENT '用户名', `password` varchar(100) DEFAULTNULL COMMENT '密码', `age` intDEFAULTNULL COMMENT '年龄', `email` varchar(50) DEFAULTNULL COMMENT '邮箱', `create_time` datetime DEFAULTCURRENT_TIMESTAMP COMMENT '创建时间', `update_time` datetime DEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP COMMENT '更新时间', `deleted` tinyint DEFAULT0 COMMENT '逻辑删除 0未删 1已删', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

五、实体类(Entity)

package com.demo.entity; import lombok.Data; import java.time.LocalDateTime; @Data publicclassUser { private Long id; private String username; private String password; private Integer age; private String email; private LocalDateTime createTime; private LocalDateTime updateTime; private Integer deleted; }

六、Mapper 接口(数据访问层)

包含:CRUD + 多条件查询 + 分页

package com.demo.mapper; import com.demo.entity.User; import org.apache.ibatis.annotations.Param; import java.util.List; publicinterfaceUserMapper { // 新增 intinsert(User user); // 根据ID删除 intdeleteById(Long id); // 根据ID修改 intupdateById(User user); // 根据ID查询 User selectById(Long id); // 查询全部 List<User> selectAll(); // 多条件动态查询 List<User> selectByCondition(@Param("username") String username, @Param("age") Integer age); }

启动类添加 Mapper 扫描

@SpringBootApplication @MapperScan("com.demo.mapper") public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }

七、MyBatis XML 映射文件

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.demo.mapper.UserMapper"> <!-- 新增 --> <insert id="insert"> insert into user(username,password,age,email) values(#{username},#{password},#{age},#{email}) </insert> <!-- 删除 --> <delete id="deleteById"> delete from user where id=#{id} </delete> <!-- 修改 --> <update id="updateById"> update user set username=#{username},age=#{age},email=#{email} where id=#{id} </update> <!-- 根据ID查询 --> <select id="selectById" resultType="User"> select * from user where id=#{id} and deleted=0 </select> <!-- 查询全部 --> <select id="selectAll" resultType="User"> select * from user where deleted=0 </select> <!-- 多条件动态查询 --> <select id="selectByCondition" resultType="User"> select * from user <where> deleted=0 <if test="username != null and username != ''"> and username like concat('%',#{username},'%') </if> <if test="age != null"> and age = #{age} </if> </where> </select> </mapper>

八、Service 层(业务逻辑 + 事务)

8.1 UserService 接口

package com.demo.service; import com.demo.entity.User; import com.github.pagehelper.PageInfo; import java.util.List; publicinterfaceUserService { // 新增 booleanadd(User user); // 删除 booleandelete(Long id); // 修改 booleanupdate(User user); // 根据ID查询 User getById(Long id); // 查询全部 List<User> list(); // 多条件查询 List<User> search(String username, Integer age); // 分页查询 PageInfo<User> page(Integer pageNum, Integer pageSize); }

8.2 UserServiceImpl 实现类

package com.demo.service.impl; import com.demo.entity.User; import com.demo.mapper.UserMapper; import com.demo.service.UserService; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.List; @Service publicclassUserServiceImplimplementsUserService { @Resource private UserMapper userMapper; @Override @Transactional(rollbackFor = Exception.class) publicbooleanadd(User user) { return userMapper.insert(user) > 0; } @Override @Transactional(rollbackFor = Exception.class) publicbooleandelete(Long id) { return userMapper.deleteById(id) > 0; } @Override @Transactional(rollbackFor = Exception.class) publicbooleanupdate(User user) { return userMapper.updateById(user) > 0; } @Override public User getById(Long id) { return userMapper.selectById(id); } @Override public List<User> list() { return userMapper.selectAll(); } @Override public List<User> search(String username, Integer age) { return userMapper.selectByCondition(username, age); } @Override public PageInfo<User> page(Integer pageNum, Integer pageSize) { PageHelper.startPage(pageNum, pageSize); List<User> list = userMapper.selectAll(); returnnewPageInfo<>(list); } }

九、Controller 层(接口)

package com.demo.controller; import com.demo.common.Result; import com.demo.entity.User; import com.demo.service.UserService; import com.github.pagehelper.PageInfo; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; @RestController @RequestMapping("/user") publicclassUserController { @Resource private UserService userService; // 新增 @PostMapping("/add") public Result add(@RequestBody User user) { userService.add(user); return Result.success("新增成功"); } // 删除 @DeleteMapping("/delete/{id}") public Result delete(@PathVariable Long id) { userService.delete(id); return Result.success("删除成功"); } // 修改 @PutMapping("/update") public Result update(@RequestBody User user) { userService.update(user); return Result.success("修改成功"); } // 单个查询 @GetMapping("/detail/{id}") public Result detail(@PathVariable Long id) { return Result.success(userService.getById(id)); } // 列表 @GetMapping("/list") public Result list() { return Result.success(userService.list()); } // 多条件搜索 @GetMapping("/search") public Result search( @RequestParam(required = false) String username, @RequestParam(required = false) Integer age) { return Result.success(userService.search(username, age)); } // 分页 @GetMapping("/page") public Result page( @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize) { PageInfo<User> page = userService.page(pageNum, pageSize); return Result.success(page); } }

十、统一返回结果类

package com.demo.common; import lombok.Data; @Data publicclassResult<T> { privateint code; private String msg; private T data; publicstatic <T> Result<T> success(T data) { Result<T> r = newResult<>(); r.setCode(200); r.setMsg("操作成功"); r.setData(data); return r; } publicstatic <T> Result<T> success(String msg) { Result<T> r = newResult<>(); r.setCode(200); r.setMsg(msg); return r; } }

十一、重点功能

1. 分页查询(PageHelper)

  • • 必须在查询前一行使用

  • • 自动拼接 LIMIT,无需改 SQL

  • • 返回 PageInfo 包含:总条数、总页数、当前页、数据列表

2. 动态 SQL(if / where / foreach)

适合多条件搜索、后台管理系统查询。

3. 事务控制

@Transactional任何异常自动回滚。

4. 下划线自动转驼峰

map-underscore-to-camel-case: true
create_timecreateTime


十二、注意事项

  1. 1.Mapper 注入失败
    启动类必须加@MapperScan

  2. 2.XML 绑定异常
    namespace 必须和 Mapper 全类名一致

  3. 3.分页不生效
    PageHelper.startPage 必须紧跟查询

  4. 4.SQL 语句报错
    XML 中不能直接写&<,需要转义

  5. 5.字段映射不上
    开启驼峰转换

  6. 6.参数多个时必须用 @Param
    否则 MyBatis 识别不到


http://www.cnnetsun.cn/news/1643621.html

相关文章:

  • OpenClaw本地知识库整合:百川2-13B-4bits模型增强问答准确性
  • 二分法(Binary Search)
  • 多智能体系统一致性仿真:Matlab 实现探索
  • 3步定位Windows热键冲突:Hotkey Detective实用指南
  • HUNYUAN-MT 7B翻译终端Java集成指南:SpringBoot微服务调用实战
  • 效率倍增:用快马平台自动化生成类qoderwork官网的高质量模板
  • 美国力科WaveSurfer3034数字示器 力科3034 350M 4通道
  • RMBG-2.0部署案例:在国产昇腾/寒武纪平台适配的可行性验证
  • Ostrakon-VL-8B批量处理技巧:高效分析门店监控图片实战
  • QueryExcel:如何用这款免费工具5倍提升多Excel文件查询效率
  • 从王兴去“登味”到APP私删用户照片,看美团的AI焦虑
  • 3步解决魔兽争霸3现代适配难题:WarcraftHelper技术优化指南
  • 网易云音乐NCM格式转换神器:5分钟解锁你的音乐自由
  • ncmdumpGUI:3分钟解锁网易云音乐NCM文件转换的终极指南
  • Simullink仿真/matlab2019 双馈风机——自励风机+他励风机,可实现MPPT ...
  • 手机上看的网页,怎样自动在荣耀 MagicOS 10 平板上接着打开?
  • KaihongOS桌面版安装教程
  • Windows驱动管理解决方案:DriverStore Explorer效率指南
  • 实测Z-Image-Turbo镜像:无需下载,直接运行文生图脚本
  • 突破QQ音乐格式壁垒:QMCDecode全方位解密方案与跨场景应用指南
  • 3步让旧款iOS设备重获新生:Legacy-iOS-Kit性能拯救全指南
  • 百川2-13B模型在网络安全领域的应用:威胁情报分析与报告生成
  • 异步Python开发实战:Tortoise ORM在FastAPI中的高效数据管理
  • GHelper终极指南:解锁华硕笔记本隐藏性能,告别臃肿控制中心
  • 颠覆式AI编程助手:DeepSeek Coder 5大场景提升开发效率80%
  • 3步打造智能文档下载助手:kill-doc用户脚本全面指南
  • 仅剩127天!Python 3.14+原生AOT将成标准解释器默认后端:企业级迁移路线图与兼容性断点预警
  • 如何通过GSE宏编译器实现智能技能管理?高效提升魔兽世界战斗表现的完整指南
  • 力扣239.滑动窗口最大值
  • 好写作AI|AI辅助硕士初稿:从数据分析到结论生成的完整链路