一,乐观锁
可参考官方文档:https://baomidou.com/pages/0d93c0/
场景:当两个工作人员同时去处理一条投诉工单的时候
当两个人一起点开了投诉工单详情 并一起编辑处理 随后同时反馈给用户时 此时就会出现矛盾 当系统正常 没有bug的时候 是会出现两条不同的反馈信息都发送给用户的情况 此时用户的反应:???倒地哪一条是对的?
此时就可以用到乐观锁了
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
取出记录时,获取当前 version
更新时,带上这个 version
执行更新时, set version = newVersion where version = oldVersion
如果 version 不对,就更新失败
配置示例:
1.在数据库表种加入version字段 表示数据版本号
2.在实体类的字段上加上注解@Version
3.配置文件
// Spring Boot 方式
@Configuration
@MapperScan("按需修改")
public class MybatisPlusConfig {
/**
* 新版
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mybatisPlusInterceptor;
}
}
4.测试乐观锁
//测试乐观锁
@Test
public void testLock01(){
User user01 = userMapper.selectById(66L);
User user02 = userMapper.selectById(66L);
user01.setName("leguansuo01");
userMapper.updateById(user01);
user02.setName("leguansuo02");
userMapper.updateById(user02);
}
原数据:66L
若没有加乐观锁的情况代码理应对他进行两次操作 也就是最终这条数据的name值为 ”leguansuo02“
但是我们此时已经添加了乐观锁 so 看演示结果
第二遍的修改失败原因:先查看数据库
在第一个修改完成的时候 数据库种的version已经变为2 第二遍修改时指定的还是为1 所以找不带,执行行数就会为0 这样就是使用乐观锁成功阻止了上述场景的发生
注意:乐观锁与悲观锁的区别
参考地址:
http://zhuanlan.zhihu.com/p/63714157
从字面上理解:都是一种锁机制 都是为了保护数据
区别:
乐观锁的角度:认为它锁保护的数据只在极少数的情况下是不安全的, 不容易出现并发问题
悲观锁的角度:认为它所保护的数据在绝大多数的情况下是不安全的,很容易出现并发问题
二,查询构造器
参考地址:
https://baomidou.com/pages/10c804/
1.举例
//部分举例
// QueryWrapper qu = new QueryWrapper();
// qu.eq("id",66L);
// 等价于
// Select * from user where id =66L
// qu.ne("name","javaxl");
// 等价于(不为,不=)
// select * from user where name <> 'javaxl'
// String sql ="email =12@qq.com and version =2";
// "等价于 拼接"
// qu.apply(sql);
2.查证测试代码:
@Test
public void testWrapperLike() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.likeRight("name", "T")
.eq("age", 28);
List<User> users = userMapper.selectList(wrapper);
users.forEach(t-> System.out.println(t));
}
三,分页插件
参考地址:
https://baomidou.com/pages/97710a/
1.添加分页拦截器
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
完整:
package com.ljj.mp0111.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// Spring Boot 方式
@Configuration
public class MybatisPlusConfig {
/**
* 新版
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
// 乐观锁
mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
// 分页拦截器
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
- 测试:
@Test
public void testSelectPage() {
PageDTO<User> page = new PageDTO<>();
page.setCurrent(3);
page.setSize(3);
// select * from user limit (3-1)*3,3
PageDTO<User> pageDTO = userMapper.selectPage(page, null);
System.out.println(pageDTO.getTotal());
List<User> records = pageDTO.getRecords();
records.forEach(t-> System.out.println(t));
}
3.查询结果:
思考:如何在不同的表中使用共同的分页(提取出重复的代码供不同的表使用)
方法:将共同代码放入查询的前置通知当中 在后置通知中处理结果
四,逻辑删除
在开发过程当中 我们使用的删除操作应该要尽量的去使用逻辑删除(不显示) 而不是物理删除(彻底删除)因为以往的数据可能在日后都会需要到
实现步骤:
- 添加逻辑删除标识
软件使用过程中所有的查询都带上where deleteid = 0
2.修改实体类
//标记该字段为逻辑删除字段
@TableLogic
private int deleteid;
3. 在application.properties (或application.yml)中加入如下配置
#逻辑删除字段名
mybatis-plus.global-config.db-config.logic-delete-field=deleteid
# 1表示逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
# 0 表示未删除
mybatis-plus.global-config.db-config.log
- 测试
@Test
public void testDeleteLogic() {
int i = userMapper.deleteById(1L);
System.out.println(i);
}
五,在Mybatis-plus中使用xml配置
mybatis-plus是mybatis的升级版,所以在mybatis-plus中使用xml的配置比较简单
1. 在application.properties配置文件中加入如下配置
mybatis-plus.mapper-locations=classpath:/mapper/**/*.xml
2. 定义mapper接口,继承BaseMapper接口,以便于使用mybatis-plus提供的方法
@Repository
public interface UserMapperXml extends BaseMapper<User> {
List<User> list();
}
3. 根据接口生成xml配置文件,IDE一般有辅助的插件,例如IDEA中的Free Mybatis plugin
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.zking.mpdemo.mapper.UserMapperXml">
<select id="list" resultType="com.zking.mpdemo.model.User">
select * from user;
</select>
</mapper>
也可以不使用xml配置文件,使用注解来定义sql语句 但是当sql链表等复杂化的时候不方便维护 不推荐
public interface UserMapperXml extends BaseMapper<User> {
@Select("select * from user")
List<User> list();
}
4.测试
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MpdemoApplication.class)
public class UserMapperXmlTest {
@Autowired
private UserMapperXml userMapperXml;
//使用xml配置的方法
@Test
public void list() {
List<User> list = userMapperXml.list();
list.forEach(t-> System.out.println(t));
}
//mybatis-plus提供的方法
@Test
public void testSelectByID() {
User user = userMapperXml.selectById(2L);
System.out.println(user);
}
}
可以在mybatis-plus中使用mybatis中的功能 但是关于前者的自动维护的功能就会全部失效