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);
}