视频课程地址:黑马商城项目
上一节:MybatisPlus(二)核心功能01 — 条件构造器
下一节:MybatisPlus(二)核心功能03 — IService接口
本节学习MybatisPlus(MP)的核心功能 — 自定义SQL:
- 在业务层拼接SQL的问题
- 自定义SQL的用法
一、自定义SQL简介
自定义SQL:我们可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,然后自己定义SQL语句中剩下的部分。
二、问题出现
下面的案例是完全手写SQL的方式。
上一节中我们遇到了相似的案例,使用了 LambdaUpdateWrapper
,写法如下:
@Test
void testLambdaUpdateWrapper() {
List<Long> idList = List.of(1L, 2L, 4L);
LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<User>()
.setSql(true, "balance = (balance - 200)")
.in(User::getId, idList);
userMapper.update(null, wrapper);
}
而上面的代码是有问题的:
代码中 .setSql()
部分是写的SQL语句,但是这整段代码一般情况下是在service层的,也就是业务逻辑层。
而在业务逻辑层代码拼写应该在持久层出现的SQL语句,这是一种很不规范的写法。
那么怎么办呢?
那就将复杂的SQL拼写分为两个部分:
- 一部分可以由MP直接构建的,交给MP
- 另一部分相对复杂,MP无法构建的就自定义SQL(手写SQL)
当然这个手写的SQL不是在业务层进行拼写,而是在Mapper层。
只要将业务层中MP构建的传递到Mapper层和自定义SQL组装起来就可以了。
三、自定义SQL用法
用上面的代码进行改写:
3.1 基于Wrapper构建where条件
模拟在业务层进行MP构建:
@Test
void testCustomSqlSegment() {
List<Long> idList = List.of(1L, 2L, 4L);
int amount = 200;
// 1. 构建条件
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>().in(User::getId, idList);
// 2. 自定义SQL方法调用
userMapper.updateBalanceByIds(wrapper, amount);
}
3.2 Mapper.java中自定义方法
在mapper层的方法参数中用 @Param
注解声明wrapper变量名称,必须是ew
。
void updateBalanceByIds(@Param("ew")LambdaQueryWrapper<User> wrapper, @Param("amount") int amount);
3.3 Mapper.xml中自定义SQL
<update id="updateBalanceByIds">
UPDATE user SET balance = balance - #{amount} ${ew.customSqlSegment}
</update>
代码解析:
${ew.customSqlSegment}
: 会拼接MP构建好的SQL片段
运行结果:
成功修改数据。
3.4 总结
通过这个方式,我们成功将MP构建放在了业务层,把自定义SQL放在了Mapper层。分层正确。
使用场景:
SQL语句,where条件之外的部分,我们无法通过MP更方便的实现,只能用拼接。
那么为了不违背编写规范,采用这种方式:where条件使用MP构建,其余部分进行自定义SQL。