建设一个房产网站赚钱吗,苏州网站制作聚尚网络,网站每年都要备案吗,上海网站公司目录 一、前言二、update1、关于修改的4个条件构造器2、UpdateWrapper【用法示例】3、LambdaUpdateWrapper【用法示例】4、UpdateChainWrapper【 用法示例】5、LambdaUpdateChainWrapper【 用法示例】6、updateById 和 updateBatchById7、Mybatis-plus设置某个字段值为null的方… 目录 一、前言二、update1、关于修改的4个条件构造器2、UpdateWrapper【用法示例】3、LambdaUpdateWrapper【用法示例】4、UpdateChainWrapper【 用法示例】5、LambdaUpdateChainWrapper【 用法示例】6、updateById 和 updateBatchById7、Mybatis-plus设置某个字段值为null的方法总结 三、saveOrUpdate1、saveOrUpdate 【用法示例】2、saveOrUpdateBatch【用法示例】3、批量插入优化 四、防全表更新与删除插件 一、前言 在Mybatis-Plus官网当中并没有对于update进行针对性的详细讲解以及其使用很多初级小白都用不明白包括我有时候都迷迷糊糊的基于这个问题我也是下定决心好好整理一篇。本篇文章重点是通过多个案例来进行讲解每一个案例执行出来的sql我都会放到文章当中方便大家快速掌握并使用 在实际开发当中我们一般都是将service的接口继承IServiceT然后serviceImpl继承ServiceImplM extends BaseMapperT, Tmapper接口继承BaseMapperT
BaseMapper相对来说方法比较少一般都是通过service接口或者serviceImpl来使用其update的相关方法有如下 二、update
update方法主要有以下
// 返回UpdateChainWrapper主要用来链式调用
UpdateChainWrapper update();
// 返回LambdaUpdateChainWrapper 同样是主要用来链式调用只不过是基于Lambda的
LambdaUpdateChainWrapper lambdaUpdate();
// 根据 UpdateWrapper 条件更新记录 需要设置sqlset
boolean update(WrapperT updateWrapper);
// 根据 whereWrapper 条件更新记录
boolean update(T updateEntity, WrapperT whereWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(CollectionT entityList);
// 根据ID 批量更新
boolean updateBatchById(CollectionT entityList, int batchSize);参数说明 1、关于修改的4个条件构造器
Mybatis-Plus给我们提供了4个关于Java修改的条件构造器这四个构造器的顶级父类都是Wrapper
UpdateWrapper
UpdateWrapperUser objectUpdateWrapper new UpdateWrapper();
UpdateWrapperUser update1 Wrappers.update();LambdaUpdateWrapper
LambdaUpdateWrapperUser updateWrapper new LambdaUpdateWrapper();
LambdaUpdateWrapperUser updateWrapper new UpdateWrapper().lambda();
LambdaUpdateWrapperUser objectLambdaUpdateWrapper Wrappers.lambdaUpdate();UpdateChainWrapper可以new但是必须传入BaseMapper参数或者是传入实体类的字节码可以通过service来声明。
Resource
private UserService userService;Resource
private UserMapper userMapper;Test
void contextLoads() {UpdateChainWrapperUser update userService.update();UpdateChainWrapperUser userUpdateChainWrapper new UpdateChainWrapper(User.class);UpdateChainWrapperUser userUpdateChainWrapper1 new UpdateChainWrapper(userMapper);
}LambdaUpdateChainWrapper同UpdateChainWrapper一样可以new但是必须传入BaseMapper参数或者是传入实体类的字节码可以通过service来声明LambdaUpdateChainWrapperUser userLambdaUpdateChainWrapper userService.lambdaUpdate();
UpdateChainWrapper和LambdaUpdateChainWrapper都继承了AbstractChainWrapper而UpdateWrapper和LambdaUpdateWrapper都继承了AbstractWrapper。AbstractChainWrapper和AbstractWrapper都继承了Wrapper。 在上面我们也了解到了Mybatis-Plus给我们提供了好几个update方法并且传参都离不开Wrapper下面我们将通过不同的Wrapper和不同的方法进行结合起来彻底了解清楚什么时候该用什么方法 2、UpdateWrapper【用法示例】
UpdateWrapper当中主要这四个方法用的比较多一点
set(String column, Object val)
set(boolean condition, String column, Object val)
setSql(String sql)
setSql(boolean condition, String sql)参数解释
类型参数名描述Stringcolumn数据库当中的字段名称Objectval需要修改的数据booleancondition判断条件控制该sql是否用到条件当中假如为true代表生效Stringsql拼接sql
1使用场景一
UpdateWrapperUser updateWrapper Wrappers.update();
// 修改表中name字段为指定的数据
updateWrapper.set(name, 123);
// 假如age不等于空那么我就将age修改为我指定的参数
Integer age 66;
updateWrapper.set(age ! null, age, age);
updateWrapper.set(email, 99999qq.com);
// 修改条件为id5的数据
updateWrapper.eq(id, 5);
// 假如修改失败返回值为false
boolean update userService.update(updateWrapper);日志打印出来的sql
UPDATE user SET name123,age66,email99999qq.com WHERE (id 5)使用 boolean update(WrapperT updateWrapper); 修改他本质上就是调用的update(T updateEntity, WrapperT whereWrapper);只不过Entity传的为null 2使用场景二把所有set值全去掉只使用UpdateWrapper作为修改的条件然后通过Entity赋值
UpdateWrapperUser updateWrapper Wrappers.update();
// 修改条件为id5的数据
updateWrapper.eq(id, 5);
User user new User();
user.setName(wdawdwa);
user.setAge(888);
user.setEmail(dwadwadqq.com);
// 假如修改失败返回值为false
boolean update userService.update(user, updateWrapper);日志打印出来的sql
UPDATE user SET namewdawdwa, age888, emaildwadwadqq.com WHERE (id 5)3Entity之和UpdateWrapper两种赋值方式同时使用
接下来我们进行测试看看boolean update(T updateEntity, WrapperT whereWrapper); 假如同时使用两种赋值方式会是什么样的。
UpdateWrapperUser updateWrapper Wrappers.update();// 修改表中name字段为指定的数据
updateWrapper.set(name, 123);
// 假如age不等于空那么我就将age修改为我指定的参数
Integer age 66;
updateWrapper.set(age ! null, age, age);
updateWrapper.set(email, 99999qq.com);
// 修改条件为id5的数据
updateWrapper.eq(id, 5);User user new User();
user.setName(wdawdwa);
user.setEmail(99999qq.com);// 假如修改失败返回值为false
boolean update userService.update(user, updateWrapper);日志打印出来的sql
UPDATE user SET namewdawdwa, age0, email99999qq.com, name123222,age66 WHERE (id 5)得出结论
updateWrapper和Entity同时对name进行赋值很显然Entity根本没起到作用的哈updateWrapper优先级要高于Entity。最终查询出来的sql是updateWrapper和Entity两种赋值方式的并集。并不会因为使用了updateWrapper.set赋值就导致整个Entity失效
4现在有一个疑问需要验证一下new出来的user并没有对email字段赋值那么他会不会将数据库当中的email赋值为null。 下面我们进行验证我user表有好几个字段我只修改了两个
UpdateWrapperUser updateWrapper Wrappers.update();
updateWrapper.eq(id, 5);
User user new User();
user.setName(wdawdwa);
user.setAge(888);
boolean update userService.update(user, updateWrapper);日志打印出来的sql
UPDATE user SET namewdawdwa, age888 WHERE (id 5)得出结论
Mybatis-Plus会根据字段是否为null来判断条件是否生效假如实体类当中使用的是基本类型new出来的对象会赋初始值的比如int默认就是0这样就会导致我们并不想对他进行修改但是最后却修改了。
5本质上假如我们不使用UpdateWrapper的set相关方法的话其实也可以直接使用QueryWrapper的如下
QueryWrapperUser objectQueryWrapper new QueryWrapper();
updateWrapper.eq(id, 5);
User user new User();
user.setName(wdawdwa);
user.setAge(888);
user.setEmail(dwadwadqq.com);
boolean update userService.update(user, objectQueryWrapper);日志打印出来的sql同时用UpdateWrapper是一样的
UPDATE user SET namewdawdwa, age0 WHERE (id 5)UpdateWrapper和QueryWrapper都继承了AbstractWrapperAbstractWrapper主要用于生成 sql 的 where 条件AbstractWrapper又继承了Wrapper。他两个唯一的区别是
UpdateWrapper实现了Update接口这个接口提供了一些set方法QueryWrapper实现了Query接口这个接口提供了一些select方法 6假如我们不使用Entity也不使用UpdateWrapper的set那sql打印出来是什么呢
UpdateWrapperUser updateWrapper Wrappers.update();
// 修改条件为id5的数据
updateWrapper.eq(id, 5);
// 假如修改失败返回值为false
boolean update userService.update(null, updateWrapper);运行结果 得出结论
直接就语法异常了语法异常userService.update并不会返回false而是线程直接就终止了
3、LambdaUpdateWrapper【用法示例】
UpdateWrapper和LambdaUpdateWrapper其实是一样的都能够实现彼此的功能只是语法不同LambdaUpdateWrapper所有的指定column参数不再是字符串而是SFunction函数。 1使用场景
LambdaUpdateWrapperUser objectLambdaUpdateWrapper new LambdaUpdateWrapper();
// 修改条件为id5的数据
objectLambdaUpdateWrapper.eq(User::getId, 5);
objectLambdaUpdateWrapper.set(User::getAge, 22);
objectLambdaUpdateWrapper.set(User::getName, zhangsan);
objectLambdaUpdateWrapper.setSql(emailceceqq.com);User user new User();
user.setAge(666);
boolean update userService.update(user, objectLambdaUpdateWrapper);日志打印出来的sql
UPDATE user SET age666, age22,namezhangsan,emailceceqq.com WHERE (id 5)2原理讲解 SFunction其实就是继承了Function函数。而Function是一个函数式(Functional)接口 Function三种使用方法
public static void main(String[] args) {// 匿名内部类Function function new FunctionUser, Object() {Overridepublic Object apply(User user) {return user.getAge();}};// lambdaFunctionUser, Object function1 (a) - a.getAge();// 方法引用FunctionUser, Object function2 User::getAge;
}核心源码 感兴趣的可以断点观察一下源码 3假如我们的get方法和表中的字段不对应是否会出问题 LambdaUpdateWrapperUser objectLambdaUpdateWrapper new LambdaUpdateWrapper();
// 修改条件为id5的数据
objectLambdaUpdateWrapper.eq(User::getId, 5);
objectLambdaUpdateWrapper.set(User::getSexaa, 男);
boolean update userService.update(objectLambdaUpdateWrapper);日志打印出来的sql
UPDATE user SET sex男 WHERE (id 5)得出结论
实体字段名和数据库当中的列名称不一致并不会影响赋值使用他实际上是通过反射拿到的是TableField当中指定的值而并非只是简单的通过get方法名字来获取的。
4、UpdateChainWrapper【 用法示例】
1使用场景一
// UpdateChainWrapper有三种创建方式
// UpdateChainWrapperUser userUpdateChainWrapper new UpdateChainWrapper(User.class);
// UpdateChainWrapperUser update new UpdateChainWrapper(userMapper);
User user new User();
user.setAge(222);
UpdateChainWrapperUser updateChainWrapper userService.update();
updateChainWrapper.eq(id, 5).set(name, 张三).setSql(emailceceqq.com).setEntity(user).update();日志打印出来的sql
UPDATE user SET name张三,emailceceqq.com WHERE age222 AND (id 5)2使用场景二
User user new User();
user.setAge(222);
UpdateChainWrapperUser updateChainWrapper userService.update();
updateChainWrapper.eq(id, 5).update(user);日志打印出来的sql
UPDATE user SET age222 WHERE (id 5)5、LambdaUpdateChainWrapper【 用法示例】
LambdaUpdateChainWrapper同UpdateChainWrapper一模一样只不过参数是函数式表达式这里就不再过多叙述了。
// LambdaUpdateChainWrapper有三种创建方式// LambdaUpdateChainWrapperUser userUpdateChainWrapper new LambdaUpdateChainWrapper(User.class);// LambdaUpdateChainWrapperUser update new LambdaUpdateChainWrapper(userMapper);User user new User();user.setAge(222);LambdaUpdateChainWrapperUser userLambdaUpdateChainWrapper userService.lambdaUpdate();userLambdaUpdateChainWrapper.eq(User::getId,5).update(user);日志打印出来的sql
UPDATE user SET age222 WHERE (id 5)6、updateById 和 updateBatchById
1updateById 使用场景 在调用updateById方法前需要在T entity对应的实体类中的主键属性上加上TableId注解。 User user new User();
user.setId(new Long(5));
user.setAge(555);
user.setEmail(null);
userService.updateById(user);日志打印出来的sql
UPDATE user SET age555 WHERE id52updateBatchById 使用场景
User user new User();
user.setId(new Long(5));
user.setAge(555);
user.setEmail(null);User user1 new User();
user1.setId(new Long(4));
user1.setAge(666);
user1.setEmail(null);ListUser objects new ArrayList();
objects.add(user);
objects.add(user1);
boolean b userService.updateBatchById(objects);日志打印出来的sql
UPDATE user SET age555 WHERE id5
UPDATE user SET age666 WHERE id47、Mybatis-plus设置某个字段值为null的方法总结
Mybatis-Plus给我们提供的update根本没有全量修改的都是只对不为空的进行修改例如updateById和update使用Entity赋值的方法都是只对不为null的进行赋值修改。假如遇到需要将某个值赋为null这时候该怎么办
方式一在mapper.xml中写对应的sql语句
方式二实体类对应字段添加注解
TableField注解介绍
TableField(insertStrategy FieldStrategy.IGNORED) 添加该注解值的字段在Mybatis-plus生成insert sql时会忽略该字段值的判断TableField(updateStrategy FieldStrategy.IGNORED) 添加该注解值的字段在Mybatis-plus生成update sql时会忽略该字段值的判断TableField(whereStrategy FieldStrategy.IGNORED) 添加该注解值的字段在Mybatis-plus生成sql时的where条件中会忽略该字段值的判断
可以聚合三种进行同时使用
TableField(insertStrategy FieldStrategy.IGNORED,updateStrategy FieldStrategy.IGNORED,whereStrategy FieldStrategy.IGNORED) 说明 FieldStrategy 的可选值
FieldStrategy.NOT_NULL不为null则更新也就是字段值为null则不生成到sql中不更新该字段如果字段值为(空字符串)也是会更新的FieldStrategy.NOT_EMPTY不为空则更新也就是该字段值为null或为(空字符串)都不会更新FieldStrategy.DEFAULT默认值和全局配置保持一致FieldStrategy.IGNORED忽略判断该字段值不论是什么都进行更新FieldStrategy.NEVER不做更新操作该字段值不论是什么都不进行更新
在email字段中设置注解加上该注解之后Mybatis-plus会在对应的情况下生成sql时忽略掉该字段值的判断即该字段值不论是什么都会生成在sql中就可以设置字段值为null了
TableField(value email, updateStrategy FieldStrategy.IGNORED)测试添加注解后的效果
User user new User();
user.setId(new Long(5));
user.setAge(555);
user.setEmail(null);
userService.updateById(user);日志打印出来的sql
UPDATE user SET age555, emailnull WHERE id5方式三通过条件构造器的set进行赋值
UpdateWrapperUser updateWrapper Wrappers.update();
updateWrapper.set(name, null);
updateWrapper.eq(id, 5);
boolean update userService.update(updateWrapper);方式四Mybatis-plus 全局参数配置(yaml方式配置如下)
全局配置的值可选项和第二种方式 FieldStrategy 的可选项一致全局配置默认值为 not_null
mybatis-plus:global-config:db-config:insert-strategy: ignoredupdate-strategy: ignoredselect-strategy: ignored这种方式和第二种一样可能会使用不当导致字段值为null数据丢失并且该方式是全局配置对所有表的实体类所有字段都生效危害会更严重如果同时配置了第二种那么优先第二种生效。
三、saveOrUpdate
saveOrUpdate方法主要有以下
// TableId 注解存在更新记录否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, WrapperT updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(CollectionT entityList);
// 批量修改插入
boolean saveOrUpdateBatch(CollectionT entityList, int batchSize);参数说明 下面进行一个一个讲解
1、saveOrUpdate 【用法示例】
方法一
boolean saveOrUpdate(T entity); 这个方法我就不演示了哈通过源码已经可以看的一清二楚了如下 方法二
default boolean saveOrUpdate(T entity, WrapperT updateWrapper) {return this.update(entity, updateWrapper) || this.saveOrUpdate(entity);
}User user new User();
user.setId(new Long(5));
user.setAge(555);
user.setEmail(null);UpdateWrapperUser updateWrapper Wrappers.update();
updateWrapper.set(name, 123);
boolean b userService.saveOrUpdate(user, updateWrapper);日志打印出来的sql 我把user.setId(new Long(5));这一行去掉之后也是打印出来的下面的sql UPDATE user SET age555, name123通过上面示例好像说明不了其作用我们再来看一个示例
User user new User();
user.setAge(555);
user.setEmail(null);UpdateWrapperUser updateWrapper Wrappers.update();
// 修改表中name字段为指定的数据
updateWrapper.set(name, 123);
// 假如不存在id为5的数据这时候会进行新增
updateWrapper.eq(id,5);
boolean b userService.saveOrUpdate(user, updateWrapper);日志打印出来的sql
UPDATE user SET age555, name123 WHERE (id 5)假如不存在id为5的数据这时候打印出来的sql
UPDATE user SET age555, name123 WHERE (id 6)
INSERT INTO user ( id, age ) VALUES ( 1668194662817099777, 555 )得出结论
像我们平常使用的updateByid不就是根据id来判断是新增还是修改。而这个方法说白了他就是要以updateWrapper当中所组成的where条件来判断是新增还是修改。
2、saveOrUpdateBatch【用法示例】
方法三
default boolean saveOrUpdateBatch(CollectionT entityList) {return this.saveOrUpdateBatch(entityList, 1000);
}测试代码数据库当中只有id为5的数据没有id为6的数据
User user new User();
user.setId(new Long(5));
user.setAge(555);
user.setEmail(null);User user1 new User();
user1.setId(new Long(6));
user1.setAge(666);
user1.setEmail(null);ListUser objects new ArrayList();
objects.add(user);
objects.add(user1);boolean b userService.saveOrUpdateBatch(objects);System.out.println(11111111111111111111);
System.out.println(b);日志打印出来的sql
SELECT id,name,age,email FROM user WHERE id5
UPDATE user SET age555 WHERE id5
SELECT id,name,age,email FROM user WHERE id6
INSERT INTO user ( id, age ) VALUES ( 6, 666 )得出结论
假如是批量的能查到就修改查不到就新增每条数据都是相互隔离的谁也不影响谁
方法四
其实方法三就是掉用的方法四设置了batchSize 为1000。 batchSize代表的是插入批次数量。
boolean saveOrUpdateBatch(CollectionT entityList, int batchSize);3、批量插入优化
如果大数据量例如五千、一万插入建议修改MySQL的JDBC连接的url为如下开启rewriteBatchedStatements可以优化插入速度。
url: jdbc:mysql://127.0.0.1:3306/text1?characterEncodingUTF-8useSSLfalserewriteBatchedStatementstrue四、防全表更新与删除插件
在使用Mybatis-Plus的时候如果对API不是特别了解很容易导致重大事故就拿下面的代码来说
User user new User();
user.setId(new Long(5));
user.setAge(555);
user.setEmail(null);UpdateWrapperUser updateWrapper Wrappers.update();
updateWrapper.set(name, 123);
boolean b userService.saveOrUpdate(user, updateWrapper);日志打印出来的sql
UPDATE user SET age555, name123本来想着只修改id为5的数据却不料最终执行的sql连where条件都没有导致把整张表全给修改了。针对于这个问题我们可以添加如下配置进行防范 这是官网给我们提供的https://baomidou.com/pages/c571bc/#blockattackinnerinterceptor Configuration
public class MybatisPlusConfig {Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());return interceptor;}
}然后这时候再执行sql会发现直接就异常了原因是没有where条件