mybatis plus update(手把手讲解)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
前言
在 Java 后端开发领域,数据库操作是应用的核心功能之一。MyBatis Plus(以下简称 MP)作为 MyBatis 的增强工具包,凭借其简洁的 API 和高效的功能,成为许多开发者的首选。其中,mybatis plus update 操作是开发者日常工作中高频使用的场景。无论是修改用户信息、更新订单状态,还是调整库存数量,理解并掌握 MP 的更新机制都至关重要。
本文将从基础到进阶,分层次讲解 mybatis plus update 的实现方式,并通过实际案例和代码示例,帮助读者快速掌握这一核心技能。无论是编程新手还是有一定经验的开发者,都能从中获得实用的指导。
一、MyBatis Plus 更新操作的基础用法
1.1 基础更新:updateById
方法
MP 提供了最直接的更新方法 updateById
,其核心逻辑是根据主键值更新指定对象的非空字段。
代码示例:
// 假设 User 表的主键为 id
User user = new User();
user.setId(1L);
user.setAge(25); // 仅修改年龄字段
// 调用 updateById 方法
userMapper.updateById(user);
核心逻辑解释:
- 主键校验:必须显式设置主键值(
setId(1L)
),否则会因主键缺失导致更新失败。 - 字段覆盖:默认仅更新对象中非空的字段,空字段会被忽略。
比喻说明:
这就像快递员送包裹时,必须明确知道收件人的地址(主键),才能将包裹(数据)送达正确的地点。
1.2 批量更新:saveOrUpdate
方法
当需要根据主键是否存在自动执行插入或更新操作时,可以使用 saveOrUpdate
方法。
代码示例:
User user = new User();
user.setId(1L); // 存在则更新,不存在则插入
user.setName("张三");
userMapper.saveOrUpdate(user);
注意事项:
- 此方法会先查询主键是否存在,存在则调用
updateById
,不存在则调用insert
。 - 频繁调用可能引发性能问题,需结合业务场景谨慎使用。
二、进阶用法:灵活的条件更新
2.1 条件更新:update
方法与 Wrapper
当需要根据条件批量更新数据时,update
方法配合 Wrapper
(如 QueryWrapper
或 LambdaUpdateWrapper
)能精准控制更新范围。
代码示例(LambdaUpdateWrapper):
LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(User::getAge, 18) // 条件:年龄等于18岁
.set(User::getIsAdult, true); // 设置 isAdult 字段为 true
userMapper.update(null, wrapper);
核心逻辑说明:
update
方法参数:第一个参数为实体对象(可传null
,但需通过set
方法指定更新字段),第二个参数为Wrapper
。LambdaUpdateWrapper
:使用 Lambda 表达式避免字段名硬编码,提升代码可读性。
比喻说明:
这就像在超市打折时,商家根据商品种类(条件)对特定商品(符合条件的数据)统一降价(更新操作)。
2.2 动态字段更新:set
方法的灵活用法
通过 set
方法,开发者可以动态指定需要更新的字段,避免不必要的字段覆盖。
代码示例:
// 仅更新 name 和 email 字段
userMapper.update(new UpdateWrapper<User>()
.set("name", "李四")
.set("email", "li@si.com")
.eq("id", 1L));
优势:
- 可避免因实体对象中其他字段(如
createTime
)为空而被错误覆盖。 - 支持 SQL 片段拼接(如
set("age = age + 1")
)。
2.3 批量更新多条记录
当需要更新多条记录时,可通过 updateBatchById
方法实现。
代码示例:
List<User> users = new ArrayList<>();
User user1 = new User(1L, "王五", 30);
User user2 = new User(2L, "赵六", 28);
users.add(user1);
users.add(user2);
userMapper.updateBatchById(users); // 根据 id 批量更新
性能提示:
此方法底层通过循环调用 updateById
实现,若数据量过大,建议结合分页或原生 SQL 优化。
三、高级技巧与最佳实践
3.1 乐观锁更新:version
字段的使用
通过版本号机制(version
字段)实现乐观锁,防止并发更新导致的数据覆盖。
实现步骤:
- 在实体类中添加
version
字段,并在数据库表中对应列设置为INT
。 - 在 Mapper 接口或 XML 中声明
@Version
注解。
代码示例:
@Data
public class User {
private Long id;
private String name;
@Version // 标记为版本号字段
private Integer version;
}
// 更新逻辑
User user = userMapper.selectById(1L);
user.setName("王小二");
userMapper.updateById(user); // 自动增加 version 值
工作原理:
- 更新时会自动附加
version = version + 1
的条件,若版本不匹配则更新失败。
比喻说明:
这类似于图书馆的座位预约系统:用户只能在座位未被他人占用(版本号匹配)时成功续借。
3.2 原生 SQL 与自定义更新语句
当 MP 的内置方法无法满足复杂需求时,可通过 BaseMapper
的 update
方法执行原生 SQL。
代码示例:
String sql = "UPDATE user SET age = age + 1 WHERE create_time BETWEEN #{startDate} AND #{endDate}";
Map<String, Object> params = new HashMap<>();
params.put("startDate", "2023-01-01");
params.put("endDate", "2023-12-31");
userMapper.update(new User(), new UpdateWrapper<User>().sql(sql, params));
注意事项:
- 需自行处理 SQL 注入风险,建议使用参数化查询。
- 复杂逻辑建议通过 XML 文件管理 SQL 语句,提升可维护性。
3.3 事务管理与回滚策略
更新操作通常需要事务支持,确保数据一致性。
代码示例:
@Transactional
public void updateUsers() {
// 更新用户信息
User user = new User(1L, "陈七", 35);
userMapper.updateById(user);
// 更新订单状态
Order order = new Order();
order.setId(1001L);
order.setStatus("COMPLETED");
orderMapper.updateById(order);
// 若任意步骤失败,回滚所有操作
}
关键点:
- 使用
@Transactional
注解或编程式事务管理。 - 确保资源释放(如数据库连接)和异常处理。
四、常见问题与解决方案
4.1 更新操作后返回影响行数为 0
可能原因:
- 主键未正确设置。
- 条件查询未命中任何记录。
- 乐观锁版本号不匹配。
解决方法:
- 检查主键值是否正确。
- 使用
selectById
确认数据是否存在。 - 在日志中查看生成的 SQL 语句,验证条件逻辑。
4.2 多字段同时更新时性能下降
当更新涉及大量字段或大数据量时,可能出现性能瓶颈。
优化建议:
- 分批处理:使用
updateBatchById
时分批次提交。 - 字段选择性更新:仅更新必要字段,避免全字段覆盖。
- 索引优化:为条件字段添加索引(如
age
字段)。
结论
mybatis plus update 操作是后端开发中不可或缺的技能。通过本文的讲解,读者可以掌握从基础到高级的更新方法,包括条件更新、批量操作、乐观锁机制以及性能优化策略。无论是处理简单的单条数据更新,还是应对复杂的并发场景,MP 的灵活 API 都能提供高效解决方案。
建议读者在实践中多尝试不同场景的代码示例,并结合项目需求选择最优实现方式。同时,持续关注 MyBatis Plus 的版本更新,以充分利用其不断优化的新特性。通过理论与实践的结合,开发者能够更自信地应对数据库更新操作的挑战。