java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > MyBatis-Plus UpdateWrapper 使用

MyBatis-Plus UpdateWrapper 使用常见陷阱和解决方案

作者:Api官方认证调用工程师

MyBatis-Plus是Mybatis的一个增强,简化了Mybatis的开发过程,不仅保持了Mybatis原有的功能,而且在无代码侵略下增加了许多的增强的功能,提供了丰富的CRUD操作,单表的CRUD操作无需编写SQL语句,本文介绍的是UpdateWrapper的常见陷阱和对应的解决方案,感兴趣的朋友一起看看吧

概要

MyBatis-Plus是Mybatis的一个增强,简化了Mybatis的开发过程,不仅保持了Mybatis原有的功能,而且在无代码侵略下增加了许多的增强的功能,提供了丰富的CRUD操作,单表的CRUD操作几乎无需编写SQL语句。虽然Mybatis-Plus方便了开发者的开发,但是也会遇到一些常见的陷阱和问题,了解这些潜在的陷阱并知道如何避免它们,可以帮助你更高效的和正确的使用Mybatis-Plus。本文中介绍的是UpdateWrapper的常见陷阱和对应的解决方案。

常见陷阱与解决方案

在我们的业务场景中,常常需要更新多条数据。在使用 MyBatis-Plus 进行更新操作时,由于错误地使用 UpdateWrapper,可能会导致数据更新出现不可预知的错误。这些错误包括条件重复使用、忽略逻辑删除字段、拼写错误、以及嵌套条件使用不当等问题。

用户表

1.条件重复使用导致更新错误

在使用Mybatis-Plus的 "UpdateWapeer" 时,如果在循环中重复使用一个 "UpdateWapeer" 对象,前一个循环中设置的条件和更新值会在后续的循环中继续生效,可能会导致更新操作受前一次条件的影响,导致最终只更新了部分的数据。

假设我们有一个用户表 'User' 需要根据不同用户Id批量删除用户,采用逻辑删除,如果我们在循环中使用同一个 ‘UpdateWarpper' 对象进行操作,就可能会导致部分更新错误。

public void updateByIds(UserIdsPO po) {
        List<Integer> userIds = po.getUserIds();
        userIds.forEach(userId ->{
            UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
            updateWrapper.set("is_delete",1)
                    .eq("id", userId);
            update(updateWrapper);
        });
}

在这个错误示例中,"UpdateWapeer" 在每次循环都会添加新的更新条件和设置值,导致前一次的条件和值影响后续的更新操作。这可能导致只有第一条数据被正确更新,后续的数据更新出现错误。

解决方案

 为了避免重复使用导致更新错误,我们应该在循环中创建一个新的 "UpdateWapeer" 对象,确保每次更新操作的条件和设置值是独立的。

 public void updateByIds(UserIdsPO po) {
        List<Integer> userIds = po.getUserIds();
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        userIds.forEach(userId ->{
            updateWrapper.set("is_delete",1)
                    .eq("id", userId);
            update(updateWrapper);
        });
}

当然建议不要再循环中去操作数据库,因为这样每次都要创建新的连接,向Mysql发送网络请求,增加额外的开销。建议批量操作,这样就连接一次数据库就好了,性能大大的提升。

public void updateByIds(UserIdsPO po) {
        List<Integer> userIds = po.getUserIds();
        //根据用户id查询用户
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", userIds);
        List<User> userList = list(queryWrapper);
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        List<User> updateList = new ArrayList<>();
        userList.forEach(user ->{
            updateWrapper.set("is_delete",1)
                    .eq("id", user.getId());
            //将要修改的用户添加到集合中
            updateList.add(user);
        });
        //批量更新
        updateBatchById(updateList);
}

只要确保每一次循环都是新的 "UpdateWapeer" 对象,就能更新成功。

2.Sql注入风险

直接拼接 SQL 语句时,可能会存在 SQL 注入风险。攻击者可以通过传入恶意构造的输入,执行未预期的 SQL 语句,导致数据泄露或破坏。

public void updateUserStatus(Long userId, String status) {
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.setSql("status = '" + status + "'")
         .eq("id", userId);
    update(updateWrapper);
}

 解决方案

使用 MyBatis-Plus 提供的条件构造器方法,避免手动拼接 SQL 语句,同时使用参数化查询来防止 SQL 注入。

public void updateUserStatus(Long userId, String status) {
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.set("status", status)
         .eq("id", userId);
    update(updateWrapper);
}

3.嵌套条件使用不当

在使用 and 和 or 嵌套条件时,如果嵌套条件使用不当,可能会导致条件逻辑错误,更新操作未达到预期效果。例如,条件 A and (B or C) 和 (A and B) or C 的逻辑是不同的,不正确的嵌套条件可能导致错误的更新结果。

public void updateUsersState(int state, int age) {
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.set("state", state);
         .lt("age", age).or().isNull("name");
    update(updateWrapper);
}

 在这个错误示例中,条件 lt("age", age)isNull("name") 是通过 or 连接的,但没有使用 and 进行正确的嵌套,可能导致逻辑错误。

解决方案

通过使用 and 方法将条件正确嵌套,确保条件 lt("age", age)isNull("name") 组合在一起,并与其他条件正确连接,从而实现预期的更新效果。 

public void updateUsersState(int state, int age) {
     UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
     updateWrapper.set("state", state)
          .and(wrapper -> wrapper.lt("age", age).or().isNull("name"));
     update(updateWrapper);
}

4.条件未正确设置导致全表更新

有时候我们需要批量更新用户的状态。如果没有设置任何条件,可能会导致全表更新,造成严重的后果。

public void updateAllUsersState(int state) {
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.set("state", state);
    update(updateWrapper);
}

在这个错误示例中,如果未设置任何条件,可能会导致全表更新。

解决方案

始终确保设置了适当的条件,或者在更新前进行条件检查。

public void updateUserStateById(Long userId, int state) {
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.set("state", state)
         .eq("id", userId);
    update(updateWrapper);
}

5.列名拼写错误

在使用 UpdateWrapper 时,如果列名拼写错误,可能会导致 SQL 语法错误或更新操作没有预期效果。拼写错误会导致生成的 SQL 语句不正确,从而无法执行预期的更新操作。

public void updateUserName(Long userId, String newName) {
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.set("nmae", newName)  // 拼写错误
         .eq("id", userId);
    update(updateWrapper);
}

解决方案

通过使用 LambdaUpdateWrapper,可以避免列名拼写错误,因为它使用实体类的字段而不是字符串来指定列名。

public void updateUserName(Long userId, String newName) {
    LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
    lambdaUpdateWrapper.set(User::getName, newName);
               .eq(User::getId, userId);
    update(lambdaUpdateWrapper);
}

小结

通过避免这些潜在的问题提高我们的数据库操作的安全性和效率,有效地防止这些问题。

到此这篇关于MyBatis-Plus UpdateWrapper 使用攻略的文章就介绍到这了,更多相关MyBatis-Plus UpdateWrapper 使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文