注意点:我们在主启动类上需要扫描我们持久层文件下的所以接口
@MapperScan("com.kuang.mapper")
配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
CRUD扩展
1.插入测试
//测试插入
@Test
public void testInsert(){
User user= new User();
user.setName("直接起飞");
user.setAge(78);
user.setEmail("23672367@qq.com");
int result=userMapper.insert(user);
System.out.println(result);
}
数据库插入的id:全局唯一id
主键生成策略
默认ID_WORKER全局唯一id
分布式系统唯一id生成:https://blog.csdn.net/qq_37469055/article/details/118061067
雪花算法:
雪花算法就是使用64位long类型的数据存储id,最高位一位存储0或者1,0代表整数,1代表负数,一般都是0,所以最高位不变,41位存储毫秒级时间戳,10位存储机器码(包括5位datacenterId和5位workerId),12存储序列号。这样最大2的10次方的机器,也就是1024台机器,最多每毫秒每台机器产生2的12次方也就是4096个id。
主键自增
我们需要配置主键自增:
1.实体类字段上 @TableId(type = IdType.AUTO)
2.数据库字段一定要是自增的!
3.再测试
其余源码解释
public enum IdType { AUTO(0), //数据库id自增 NONE(1), //未设置主键 INPUT(2), //手动输入 ID_WORKER(3), //默认全局唯一id UUID(4), //全局唯一id uuid ID_WORKER_STR(5); //ID_WORKER 字符串表示法 }
2.更新操作
//更新操作
@Test
public void testUpdata() {
User user = new User();
//通过条件自动拼接动态sql
user.setId(6L);
user.setName("高原起飞");
//注意:updateById 但是参数是一个对象!
int result = userMapper.updateById(user);
System.out.println(result);
}
//更新操作
@Test
public void testUpdata() {
User user = new User();
//通过条件自动拼接动态sql
user.setId(6L);
user.setAge(18);
user.setName("高原起飞");
//注意:updateById 但是参数是一个对象!
int result = userMapper.updateById(user);
System.out.println(result);
}
所有的sql都是自动帮你动态配置!
3.自动填充
创建时间,修改时间!这些操作都是自动化完成的,我们不希望手动更新!
阿里巴巴开发手册:所有的表都应该配置有gmt_create,gmt_modified几乎所有的表都要配置上,且需要自动化。
方式一:数据库级别
1.在表中设置字段,create_time,update_time
2.更新实体类
private Date createTime;
private Date updateTime;
3.重新测试插入实体类信息
方式二:代码级别
1.数据库设置
2.实体类属性设置
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
3.继承提供的类实现其方法
@Slf4j
@Component //一定不要忘记把处理器加到IOC容器中
public class MyMetaObjectHandler implements MetaObjectHandler {
//插入时的填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill......");
//setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
// 填充的字段名 填充的值 meatObject
this.setFieldValByName("creatTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
//更改时的填充策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill......");
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
4.进行测试
插入数据测试
修改数据测试
5.结果查看:注意时间
4.乐观锁
乐观锁:顾名思义,它总是认为不会出现问题,无论干什么都不去上锁!如果出现了问题,再次更新值测试!
悲观锁:顾名思义,它总是认为总是出现问题,无论干什么都上锁!再去操作!
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
1.给数据库添加version字段,默认为1
2.需要实体类加上对应的字段
//乐观锁字段
@Version
private Integer version;
3.注册组件
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement //自动事务管理
//使用配置类后,扫描持久层工作可以放到这里来,不在启动类上进行扫描
@MapperScan("com.kuang.mapper")
@Configuration //配置类
public class MybatisPlusConfig {
//注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
4.测试一下
// 测试乐观锁成功
@Test
public void testVersionSuccess(){
// 1. 查询用户信息
User user = userMapper.selectById(1L);
// 2. 修改用户信息
user.setName("嘎嘎");
user.setAge(24);
// 3. 执行更新操作
userMapper.updateById(user);
}
// 测试乐观锁失败!多线程下
@Test
public void testVersionFall(){
// 线程1
User user1 = userMapper.selectById(1L);
user1.setName("嘎嘎111");
user1.setAge(14);
// 线程2
User user2 = userMapper.selectById(1L);
user2.setName("嘎嘎222");
user2.setAge(24);
userMapper.updateById(user2);
//因为user2的抢先执行使得user1中保存的version与user2执行后的不同,user1无法修改
//自旋锁来多次尝试提交!
userMapper.updateById(user1); //如果没有乐观锁就会覆盖插队线程的值
}
5.测试结果
成功的结果
失败的结果
查询操作
// 测试查询
@Test
public void testSelectById(){
User user = userMapper.selectById(1);
System.out.println(user);
}
// 批量查询
@Test
public void testSelectByBatchIds(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
}
// 按照条件查询之一使用 map
@Test
public void testSelectByMap(){
HashMap<String, Object> map = new HashMap<>();
// 自定义要查询
map.put("name","Tom");
map.put("age","28");
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
分页查询
分页网站频繁使用
- 原始使用limit进行分页
- pageHelper第三方插件
- MybatisPlus内置了分页插件
分页查询操作方法
1.配置拦截器
// 分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
2.直接使用Page对象即可
// 测试分页查询
@Test
public void testPage(){
// 参数一: 当前页
// 参数二: 页面大小
// 使用了分页插件之后,所有的分页操作变得简单了
Page<User> page = new Page<>(1,5);
userMapper.selectPage(page, null);
page.getRecords().forEach(System.out::println);
//内置许多方法,如下是得到总记录的条数
System.out.println(page.getTotal());
}
删除操作
// 测试删除
@Test
public void testdelete(){
userMapper.deleteById(6L);
}
// 测试批量删除
@Test
public void testdeleteBatchId(){
userMapper.deleteBatchIds(Arrays.asList(1287326823914405893L,1287326823914405894L));
}
//通过map删除
@Test
public void testDeleteByMap(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","KUANG");
userMapper.deleteByMap(map);
}
逻辑删除
物理删除:从数据库中直接移除
逻辑删除:在数据库中没有被移除,而是通过一个变量让他生效!deleted=0 --> deleted=1
测试:
-
在数据库表中增加一个deleted字段
-
实体类中增加属性
@TableLogic // 逻辑删除
private Integer deleted;
3.配置
// 逻辑删除组件
public ISqlInjector sqlInjector(){
return new LogicSqlInjector();
}
# 配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
4.测试删除
5.测试查询
以上所有的CRUD操作及其扩展操作,我们必须精通掌握!会大大提高工作效率!
四、性能分析插件
我们在平时的开发中,会遇到一些慢sql。解决方案:测试,druid监控…
作用:性能分析拦截器,用于输出每条SQL语句及其执行时间
MyBatisPlus也提供性能分析插件,如果超过这个时间就停止运行!
1.导入插件
// SQL执行效率插件
@Bean
@Profile({"dev","test"})
public PerformanceInterceptor performanceInterceptor(){
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(100); //ms 设置sql执行的最大时间,如果超过了则不执行
performanceInterceptor.setFormat(true); // 是否格式化
return performanceInterceptor;
}
记住,要在SpringBoot中配置环境为dev或者test环境!
2.测试使用
// 测试查询
@Test
public void testSelectById(){
User user = userMapper.selectById(3);
System.out.println(user);
}
只要超出时间就会抛出异常
使用性能分析插件可以提高效率,新版本MP已经移除该拆件了,可以使用druid