天天看点

MybatisPlus学习笔记开始使用CRUD扩展性能分析插件wapper条件构造器。条件查询

MybatisPlus一个自动完成基本CRUD对Mybatis的增强框架。主流同类有JPA、tk-mapper。

开始使用

步骤:

1.导入依赖

<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--Lombok插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
           

注意:不要同时导入mybatis和mybatisplus,或版本冲突。

2.编写配置

3.编码

(没有使用mybatisPlus:连接数据库、编写dao-service-controller)

(使用mybatisPlus:编写pojo、mapper接口、使用)

注意:需要在主启动类中扫描mapper下的所有接口。@MapperScan(“com.hx.mybatis_plus.dao”)

4.编写测试类

–问题:mybatisPlus帮我们写好了sql,和方–

配置日志

#mybatis-plus配置
mybatis-plus:
configuration:
log-impl:org.apache.ibatis.logging.stdout.StdOutImpl#使用默认的控制台输出
           

CRUD扩展

主键生成策略

UUID,自增id,雪花算法,redis生成,zookeeper生成

数据库主键的值,必须为唯一的id

雪花算法

分布式系统唯一id生成方案汇总

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生4096个ID),最后还有一个符号位,永远是0。

几乎可以保证全球唯一!

@TableId(type=?)IdType

默认ID_WORKER是全局唯一id

主键自增

1.我们需要配置自增主键(数据库字段一定是要自增的)

2.实体类字段上@TableId(type=IdType.AUTO)

publicenumIdType{
AUTO(0),//自增
NONE(1),//无
INPUT(2),//手动输入
ID_WORKER(3),//默认全局id
UUID(4),//全局iduuid
ID_WORKER_STR(5);//id_worker的字符串表示法
}
           

#更新操作

==>Preparing:UPDATEuserSETname=?,age=?,email=?WHEREid=?

==>Parameters:嘻嘻(String),19(Integer),[email protected](String),1(Long)

<==Updates:1b

这里mybatisPlus会自动的拼接动态sql

自动填充

一般的创建时间,修改时间希望数据库自动填充,而不是手动的填充。

阿里开发手册:所有的数据库表都需要具备gmt_create,gmt_modified。几乎所有的表都需要配置

1.数据库级别的

不建议在工作中使用这种方式。

1.在表中新增字段create_time,update_time

##2.代码级别的

1.为实体类加上属性,并添加注解

@TableField(fill=FieldFill.INSERT)
privateStringcreateTime;

@TableField(fill=FieldFill.INSERT_UPDATE)
privateStringupdateTime;
           

2.编写处理器来处理这个注解。

乐观锁&悲观锁

原子引用。

乐观锁:总是认为不会出现问题,不加锁。若出现问题则再次更新值测试。

悲观锁:悲观的认为总会出现问题,无论什么都加锁。

乐观锁实现机制:

1.取记录时,获取当前version

2.更新时带上version

3.执行更新时,setversion=newVersionwhereversion=oldVersion

4.ifversion不对,则更新失败

步骤

1.给数据库加上字段version(int)

2.实体加属性与注解

@Version
privateintversion;
           

3.扫描注册组件

@EnableTransactionManagement//默认也是开启的
@Configuration//配置类
//扫描mapper所在的文件夹
@MapperScan("com.hx.mybatis_plus.dao")
publicclassMybatisPlusConfig{
//注册一个乐观锁插件
@Bean
publicOptimisticLockerInterceptoroptimisticLockerInterceptor(){
returnnewOptimisticLockerInterceptor();
}
}
           

测试

//测试乐观锁成功
@Test//在单线程情况下是可以成功的
voidtestOptimisticLockerSuccess(){
Useruser=userMapper.selectById(1L);
user.setName("Huathy-"+newDate().getTime());
userMapper.updateById(user);
}
           

控制台输出结果

==>Preparing:UPDATEuserSETname=?,age=?,email=?,version=?,update_time=?WHEREid=?ANDversion=?

==>Parameters:Huathy1608825571198(String),19(Integer),[email protected](String),2(Integer),2020-12-2423:59:31.227(Timestamp),1(Long),1(Integer)

<==Updates:1

//测试乐观锁失败
@Test
voidtestOptimisticLockerFailed(){
//线程1操作
Useruser=userMapper.selectById(1L);
user.setName("Huathy-"+newDate().getTime());

//模拟线程2执行插队操作
Useruser2=userMapper.selectById(1L);
user2.setName("Huathy-"+newDate().getTime());
userMapper.updateById(user2);

//可以利用自旋锁来多次尝试提交
userMapper.updateById(user);
}
           

查询操作

@Test//多id查询
voidtestSelectByBatchIds(){
List<User>users=userMapper.selectBatchIds(Arrays.asList(1,2,3));
users.forEach(System.out::println);
}

@Test//多条件查询
voidtestSelectByMap(){
Map<String,Object>map=newHashMap<>();
map.put("name","嘻嘻");
map.put("age",18);
List<User>users=userMapper.selectByMap(map);
users.forEach(System.out::println);
}
           

分页插件

1.原始的limit分页

2.pageHelper分页

3.MP内置分页插件分页

使用步骤

1.导入拦截器组件

//分页插件
@Bean
publicPaginationInterceptorpaginationInterceptor(){
returnnewPaginationInterceptor();
}
           

2.测试分页查询

@Test
voidtestPageSelect(){
//当前页,页面大小
Page<User>page=newPage<>(1,5);
IPage<User>userIPage=userMapper.selectPage(page,null);
userIPage.getRecords().forEach(System.out::println);
}
           

删除操作

@Test
voidtestDeleteById(){
intres=userMapper.deleteById(3L);
System.out.println(res);
}

@Test
voidtestDeleteBatchIds(){
intres=userMapper.deleteBatchIds(Arrays.asList(4L,5L));
System.out.println(res);
}

@Test
voidtestDeleteByMap(){
Map<String,Object>map=newHashMap<>();
map.put("name","嘻嘻1");
intres=userMapper.deleteByMap(map);
System.out.println(res);
}
           

逻辑删除

物理删除:直接的从数据库中删除。

逻辑删除:通过标识字段标识此记录失效。

步骤:

1.创建数据库字段deleted,并在实体类中加上字段

@TableLogic//逻辑删除标识
privateIntegerdeleted;
           

2.配置逻辑删除组件

@Bean//逻辑删除组件
publicISqlInjectorsqlInjector(){
returnnewLogicSqlInjector();
}
           

3.配置逻辑删除值

global-config:
db-config:
logic-delete-value:1
logic-not-delete-value:0
           

4.测试删除

@Test
voidtestDeleteById(){
intres=userMapper.deleteById(3L);
System.out.println(res);
}
//输出日志:
==>Preparing:UPDATEuserSETdeleted=1WHEREid=?ANDdeleted=0
==>Parameters:3(Long)
<==Updates:1
           

5.再次测试查询,检查是否能够查到数据

@Test
voidtestSelectById(){
Useru=userMapper.selectById(3L);
System.out.println(u);
}
//输出日志
==>Preparing:SELECTid,name,age,email,version,create_time,update_time,deletedFROMuserWHEREid=?ANDdeleted=0
==>Parameters:3(Long)
<==Total:0
           

性能分析插件

开发中可能存在一些慢查询。可以通过测试(压力测试),druid分析。MP也提供了性能分析插件。

若超过一定的时间就停止运行。

##使用步骤

导入插件->测试使用

作用:性能分析拦截器,用于输出每条sql语句及其执行时间

1.配置yml为开发环境

#设置springboot当前为开发环境
spring:
profiles:
active:dev
           
@Bean
@Profile({"dev","test"})
publicPerformanceInterceptorperformanceInterceptor(){
PerformanceInterceptorperformanceInterceptor=newPerformanceInterceptor();
//设置sql执行的最大时间ms
performanceInterceptor.setMaxTime(100);
//开启格式化支持
performanceInterceptor.setFormat(true);
returnperformanceInterceptor;
}
           

wapper条件构造器。条件查询

wapper用法:

wapper.isNotNull("coloum")//非空
wapper.ge("coloum",valObj)//大于等于
           

示例:

@Test
voidselectTest(){
//查询name和email不为空的参数且年龄>18
QueryWrapper<User>queryWrapper=newQueryWrapper<>();
queryWrapper
.isNotNull("name")
.isNotNull("email")
.ge("age",18);
userMapper.selectList(queryWrapper).forEach(System.out::println);
}