mybatis-plus学习
insertBatchSomeColumn 是 MyBatis-Plus 提供的批量插入方法,可以让你在批量插入数据时指定只插入部分字段,而不插入所有字段。这个方法非常有用,特别是在你不想插入某些字段(例如 null 字段)时。示例#方法insertBatchSomeColumn(Collection<T> entityList, String... column);// 使用 insertBat
1. QueryWrapper和QueryChainWrapper的比较
QueryWrapper和QueryChainWrapper都是条件构造器,其中QueryChainWrapper支持链式操作。且name使用的表字段。
- QueryWrapper示例
// 假设有一个 QueryWrapper 对象,设置查询条件为 age > 25
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
List<User> users = userService.list(queryWrapper);
for (User user : users) {
System.out.println("User: " + user);
}
- QueryChainWrapper示例
List<User> users = userService.query().gt("age", 25).list();
for (User user : users) {
System.out.println("User: " + user);
}
2. LambdaQueryWrapper和LambdaQueryChainWrapper的比较
LambdaQueryWrapper和LambdaQueryChainWrapper都是条件构造器,支持lambda表达式,其中LambdaQueryChainWrapper支持链式操作。且name使用的实体字段。
- LambdaQueryWrapper示例
// 假设有一个 QueryWrapper 对象,设置查询条件为 age > 25
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.gt(User::getAge, 25);
List<User> users = userService.list(queryWrapper);
for (User user : users) {
System.out.println("User: " + user);
}
- LambdaQueryChainWrapper示例
List<User> users = userService.lambdaQuery().gt(User::getAge, 25).list();
for (User user : users) {
System.out.println("User: " + user);
}
3. 更新实体是否使用UpdateWrapper的区别
update支持boolean update(Wrapper updateWrapper)和update(T updateEntity, Wrapper whereWrapper),如果只想更新某些字段,推荐使用 前者,避免 updateEntity 里 null 误更新。其中,Wrapper whereWrapper既可以使用QueryWrapper也可以使用UpdateWrapper。
- updateEntity 和 UpdateWrapper 更新相同字段
User updateEntity = new User();
updateEntity.setName("Entity Name"); // 在实体对象中设置 name
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("name", "Wrapper Name").eq("id", 1); // 在 UpdateWrapper 中设置 name
boolean result = userService.update(updateEntity, updateWrapper);
#最终sql语句如下(UpdateWrapper 的 set优先级更高):
UPDATE user SET name = 'Wrapper Name' WHERE id = 1;
- 示例:更新字段为null
User user = new User();
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id", 1) // 只更新 id 为 1 的用户
.set("name", null); // 显式设置 name 为 null
boolean result = userService.update(user, updateWrapper);
注意
- 使用 update(T updateEntity, Wrapper whereWrapper) 方法时,如果你没有显式地设置字段为 null(即 user.setName(null)),那么即使 name 是 null,它也不会更新为 null。这是因为 MyBatis-Plus 默认情况下不会将字段值为 null 的属性纳入更新操作。为了防止无意中将字段更新为 null,MyBatis-Plus 会忽略 null 值的字段。
- 要显式更新 null 值,可以使用 UpdateWrapper 的 set 方法来确保将字段更新为 null,而不是依赖于实体类的字段值。
4. updateById和alwaysUpdateSomeColumnById的区别
alwaysUpdateSomeColumnById 是 MyBatis-Plus 的一个扩展方法,用于强制更新某些字段,即使这些字段的值是 null。
- updateById示例
User updateEntity = new User();
updateEntity.setId(1);
updateEntity.setName(null); // 默认 updateById 不会更新 null
updateEntity.setAge(25);
boolean result = userService.updateById(updateEntity);
#最终的sql语句
UPDATE user SET age = 25 WHERE id = 1;
- alwaysUpdateSomeColumnById示例
// 创建 User 对象
User updateEntity = new User();
updateEntity.setId(1); // 必须提供 id
updateEntity.setName(null); // 这里设为 null
updateEntity.setAge(25); // 这里设为 25
// 指定要更新的字段
boolean result = userService.alwaysUpdateSomeColumnById(updateEntity);
#最终的sql语句
UPDATE user SET name = NULL, age = 25 WHERE id = 1;
注意:
- updateById 会忽略 null 值的字段(name 不更新);
- alwaysUpdateSomeColumnById 会强制更新 null(name 变为 NULL)。
5. insertBatchSomeColumn介绍
insertBatchSomeColumn 是 MyBatis-Plus 提供的批量插入方法,可以让你在批量插入数据时指定只插入部分字段,而不插入所有字段。这个方法非常有用,特别是在你不想插入某些字段(例如 null 字段)时。
- 示例
#方法insertBatchSomeColumn(Collection<T> entityList, String... column);
List<User> userList = new ArrayList<>();
User user1 = new User();
user1.setName("John");
user1.setAge(30);
User user2 = new User();
user2.setName("Alice");
user2.setAge(25);
userList.add(user1);
userList.add(user2);
// 使用 insertBatchSomeColumn 方法批量插入数据
boolean result = userService.insertBatchSomeColumn(userList, "name", "age");
if (result) {
System.out.println("Batch insert successful!");
} else {
System.out.println("Batch insert failed!");
}
注意:
- 在 insertBatchSomeColumn 中,字段的顺序和类型要与数据库表一致。
- 如果插入的字段是 null,它会被插入到数据库中,但一般建议避免插入 null 字段。
6. logicDeleteById和logicDeleteByIdWithFill的区别
logicDeleteById 和 logicDeleteByIdWithFill 都是 MyBatis-Plus 提供的逻辑删除方法,但它们之间有一个关键的区别,主要体现在 是否自动填充字段,尤其是删除相关的字段。
- logicDeleteById
作用:根据 ID 执行逻辑删除操作,将 逻辑删除字段(如 deleted)更新为 1,标记记录为已删除。
不自动填充其他字段,如删除时间、删除人等。如果你需要填充额外的字段,需要手动设置。
- 示例
#需要确保 deleted 字段 被正确地标记为逻辑删除。
@TableLogic
private Integer deleted; // 逻辑删除字段,值为 1 表示已删除
boolean result = userService.logicDeleteById(1L); // 逻辑删除 id 为 1 的用户
#最终的sql语句
UPDATE user SET deleted = 1 WHERE id = 1;
- logicDeleteByIdWithFill
作用:除了进行逻辑删除外,还会根据配置的 MetaObjectHandler 自动填充一些字段(如删除时间、修改时间等)。例如,deletedTime 字段可以自动填充为当前时间。
自动填充字段:通过 MetaObjectHandler 配置的 updateFill 或 insertFill 方法来填充字段,这样无需手动赋值。
- 示例
#需要确保 deleted 字段 被正确地标记为逻辑删除。
@TableLogic
private Integer deleted; // 逻辑删除字段,值为 1 表示已删除
#MetaObjectHandler 配置自动填充字段
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// 在插入时填充字段
}
@Override
public void updateFill(MetaObject metaObject) {
// 在更新时填充删除时间字段
if (metaObject.hasSetter("deletedTime")) {
this.setFieldValByName("deletedTime", LocalDateTime.now(), metaObject);
}
}
}
boolean result = userService.logicDeleteByIdWithFill(1L); // 逻辑删除并自动填充删除时间
#最终的sql语句
UPDATE user SET deleted = 1, deleted_time = '2025-03-12 10:00:00' WHERE id = 1;
7. Wrappers介绍
MyBatis-Plus 提供了 Wrappers 类,它是一个静态工厂类,用于快速创建 QueryWrapper、UpdateWrapper、LambdaQueryWrapper 和 LambdaUpdateWrapper 的实例。使用 Wrappers 可以减少代码量,提高开发效率。
- 示例
// 创建 QueryWrapper
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.eq("name", "张三");
// 创建 LambdaQueryWrapper
LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();
lambdaQueryWrapper.eq(User::getName, "张三");
// 创建 UpdateWrapper
UpdateWrapper<User> updateWrapper = Wrappers.update();
updateWrapper.set("name", "李四");
// 创建 LambdaUpdateWrapper
LambdaUpdateWrapper<User> lambdaUpdateWrapper = Wrappers.lambdaUpdate();
lambdaUpdateWrapper.set(User::getName, "李四");
注意:
- 在使用QueryWrapper、UpdateWrapper查询、设置条件字段部分,一定要保证安全,避免SQL注入攻击。
- 任何前端传入的SQL片段都要严格过滤。
8. 自定义sql语句
MyBatis-Plus 提供了强大的 Wrapper 条件构造器,允许开发者自定义 SQL 语句,以满足更复杂的数据库查询需求。为了使用这一功能,请确保你的 mybatis-plus 版本不低于 3.0.7。
- Constants.WRAPPER
使用 ${ew.customSqlSegment}:在 SQL 语句中,使用 ${ew.customSqlSegment} 来引用 Wrapper 对象生成的 SQL 片段。不支持基于 entity 的 where 语句。
- 示例
#service方法
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "张三");
List<User> userList = userMapper.selectByCustomSql(queryWrapper);
#mapper方法
public interface UserMapper extends BaseMapper<User> {
@Select("SELECT * FROM user ${ew.customSqlSegment}")
List<User> selectByCustomSql(@Param(Constants.WRAPPER) Wrapper<User> wrapper);
}
- map动态参数
使用 Mapper.xml 方式,防止 SQL 注入。
- 示例
List<User> selectByParams(@Param("params") Map<String, Object> params);
<select id="selectByParams" resultType="User">
SELECT * FROM user
WHERE 1=1
<if test="params.userName != null">
AND user_name = #{params.userName}
</if>
<if test="params.email != null">
AND email = #{params.email}
</if>
</select>
9. 线程安全性
Wrapper 实例不是线程安全的,因此建议在每次使用时创建新的 Wrapper 实例。这样可以避免多线程环境下的数据竞争和潜在的错误。
- 示例
// 每次创建新的 QueryWrapper 实例,避免共享
QueryWrapper<User> wrapper1 = new QueryWrapper<>();
wrapper1.eq("name", "John");
QueryWrapper<User> wrapper2 = new QueryWrapper<>();
wrapper2.eq("age", 30);
注意
QueryWrapper.clear() 方法 不会使 QueryWrapper 变为线程安全,它仅仅是清除当前 QueryWrapper 对象的所有条件,以便于 重复使用同一个实例。但是,仍然存在潜在的风险,特别是在多线程环境中,因为你可能不确定其他线程是否正在使用这个同一个 QueryWrapper 实例,或者在清除后是否会有意外的修改。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)