本文主要介紹mybatis-plus這款插件,針對springboot用戶。包括引入,配置,使用,以及擴(kuò)展等常用的方面做一個匯總整理,盡量包含大家常用的場景內(nèi)容。
關(guān)于mybatis-plus是什么,不多做介紹了,看官方文檔:baomidou.com ,咱們直接代碼擼起來。
一、快速開始
本文基于springboot、maven、jdk1.8、mysql開發(fā),所以開始前我們需要準(zhǔn)備好這套環(huán)境。我的環(huán)境使用了nacos作為注冊中心,不了解或需要搭建的參考:https://juejin.cn/post/7053977860612030477
新建如下數(shù)據(jù)庫:
建議大家選擇utf8mb4這種字符集,做過微信的同學(xué)應(yīng)該會知道,微信用戶名稱的表情,是需要這種字符集才能存儲的。
我就默認(rèn)其他環(huán)境已經(jīng)準(zhǔn)備好了,咱們直接從mybatis-plus開始。
1.1 依賴準(zhǔn)備
想要什么依賴版本的去maven倉庫查看:https://mvnrepository.com/
引入mybatis-plus依賴:
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.5.0version>
dependency>
引入mysql依賴:
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.27version>
dependency>
目前,多數(shù)項目會有多數(shù)據(jù)源的要求,或者是主從部署的要求,所以我們還需要引入mybatis-plus關(guān)于多數(shù)據(jù)源的依賴:
<dependency>
<groupId>com.baomidougroupId>
<artifactId>dynamic-datasource-spring-boot-starterartifactId>
<version>3.5.0version>
dependency>
1.2 配置準(zhǔn)備
springboot啟動類。配置@MapperScan注解,用于掃描Mapper文件位置:
importorg.mybatis.spring.annotation.MapperScan;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importorg.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@MapperScan("com.wjbgn.user.mapper")
@SpringBootApplication
publicclassRobNecessitiesUserApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(RobNecessitiesUserApplication.class,args);
}
}
數(shù)據(jù)源配置,此處配置一主一從的環(huán)境,當(dāng)前我只有一臺,所以此處配置一樣的:
spring:
datasource:
dynamic:
primary:master#設(shè)置默認(rèn)的數(shù)據(jù)源或者數(shù)據(jù)源組,默認(rèn)值即為master
strict:false#嚴(yán)格匹配數(shù)據(jù)源,默認(rèn)false.true未匹配到指定數(shù)據(jù)源時拋異常,false使用默認(rèn)數(shù)據(jù)源
datasource:
master:
url:jdbc//127.0.0.1:3306/rob_necessities?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username:root
password:123456
slave_1:
url:jdbc//127.0.0.1:3306/rob_necessities?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
username:root
password:123456
補(bǔ)充:這里面因?yàn)槟J(rèn)使用的是HikariCP
數(shù)據(jù)源,目前也推薦使用這個,相比于druid
有更高的性能,但是不能忽略下面的配置,否則服務(wù)會不斷拋出異常,原因是數(shù)據(jù)庫的連接時常和連接池的配置沒有做好。
spring:
datasource:
dynamic:
hikari:
max-lifetime:1800000
connection-timeout:5000
idle-timeout:3600000
max-pool-size:12
min-idle:4
connection-test-query:/**ping*/
1.3 啟動服務(wù)
下面直接啟動服務(wù):
得到如上結(jié)果表示啟動成功了。
二、使用
前面我們成功的集成進(jìn)來了mybatis-plus,配合springboot使用不要太方便。下面我們看看如何使用它來操作我們的數(shù)據(jù)庫。介紹一下常規(guī)的用法。
2.1 實(shí)體類注解
mybatis-plus為使用者封裝了很多的注解,方便我們使用,我們首先看下實(shí)體類中有哪些注解。有如下的實(shí)體類:
@TableName(value="user")
publicclassUserDO{
/**
*主鍵
*/
@TableId(value="id",type=IdType.AUTO)
privateLongid;
/**
*昵稱
*/
@TableField("nickname")
privateStringnickname;
/**
*真實(shí)姓名
*/
privateStringrealName;
}
- @TableName 表名注解,用于標(biāo)識實(shí)體類對應(yīng)的表。其說明如下,關(guān)于這些書寫,常規(guī)情況基本很少用到,不做多余解釋了:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.ANNOTATION_TYPE})
public@interfaceTableName{
/**
*實(shí)體對應(yīng)的表名
*/
Stringvalue()default"";
/**
*schema
*
*@since3.1.1
*/
Stringschema()default"";
/**
*是否保持使用全局的tablePrefix的值
*只生效于既設(shè)置了全局的tablePrefix也設(shè)置了上面{@link#value()}的值
*如果是false,全局的tablePrefix不生效
*
*@since3.1.1
*/
booleankeepGlobalPrefix()defaultfalse;
/**
*實(shí)體映射結(jié)果集,
*只生效與mp自動注入的method
*/
StringresultMap()default"";
/**
*是否自動構(gòu)建resultMap并使用,
*只生效與mp自動注入的method,
*如果設(shè)置resultMap則不會進(jìn)行resultMap的自動構(gòu)建并注入,
*只適合個別字段設(shè)置了typeHandler或jdbcType的情況
*
*@since3.1.2
*/
booleanautoResultMap()defaultfalse;
/**
*需要排除的屬性名
*
*@since3.3.1
*/
String[]excludeProperty()default{};
}
- @TableId 主鍵注解,看看其源碼:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.ANNOTATION_TYPE})
public@interfaceTableId{
/**
*字段值(駝峰命名方式,該值可無)
*/
Stringvalue()default"";
/**
*主鍵ID
*{@linkIdType}
*/
IdTypetype()defaultIdType.NONE;
}
其中IdType很重要:
名稱 | 描述 |
---|---|
AUTO | 數(shù)據(jù)庫自增ID |
NONE | 該類型為未設(shè)置主鍵類型(注解里等于跟隨全局,全局里約等于 INPUT) |
INPUT | 用戶自己設(shè)置的ID |
ASSIGN_ID | 當(dāng)用戶傳入為空時,自動分配類型為Number或String的主鍵(雪花算法) |
ASSIGN_UUID | 當(dāng)用戶傳入為空時,自動分配類型為String的主鍵 |
-
@TableFiled 表字段標(biāo)識,下面看看其主要常用屬性:
名稱 描述 value 數(shù)據(jù)庫字段名 condition 字段 where
實(shí)體查詢比較條件,通過SqlCondition
設(shè)置 如果未設(shè)置條件,則按照正常相等來查詢 若設(shè)置則按照以下規(guī)則:等于:EQUAL = "%s=#{%s}"; 不等于:NOT_EQUAL = "%s<>#{%s}"; 左右模糊:LIKE = "%s LIKE CONCAT('%%',#{%s},'%%')"; oracle左右模糊ORACLE_LIKE = "%s LIKE CONCAT(CONCAT('%%',#{%s}),'%%')"; 左模糊:LIKE_LEFT = "%s LIKE CONCAT('%%',#{%s})"; 右模糊:LIKE_RIGHT = "%s LIKE CONCAT(#{%s},'%%')";fill 自動填充策略,通過 FieldFill
設(shè)置 不處理:FieldFill.DEFAULT 插入時填充字段:FieldFill.INSERT 更新時填充字段:FieldFill.UPDATE 插入或新增時填充字段:FieldFill.INSERT_UPDATE關(guān)于其他的屬性,我不太推薦使用,用得越多,越容易蒙圈。可以通過wapper查詢?nèi)ピO(shè)置。
2.2 CRUD
mybatis-plus封裝好了一條接口供我們直接調(diào)用。關(guān)于內(nèi)部的具體方法,在使用時候自己體會吧,此處不列舉了。
2.2.1 Service層CRUD
我們使用的時候,需要在自己定義的service接口當(dāng)中繼承IService
接口:
importcom.baomidou.mybatisplus.extension.service.IService;
importcom.wjbgn.user.entity.UserDO;
/**
*@description:用戶服務(wù)接口
*@author:weirx
*@date:2022/1/17 15:02
*@version:3.0
*/
publicinterfaceIUserServiceextendsIService<UserDO>{
}
同時要在我們的接口實(shí)現(xiàn)impl當(dāng)中繼承ServiceImpl
,實(shí)現(xiàn)自己的接口:
importcom.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
importcom.wjbgn.user.entity.UserDO;
importcom.wjbgn.user.mapper.UserMapper;
importcom.wjbgn.user.service.IUserService;
/**
*@description:用戶接口實(shí)現(xiàn)
*@author:weirx
*@date:2022/1/17 15:03
*@version:3.0
*/
publicclassUserServiceImplextendsServiceImpl<UserMapper,UserDO>implementsIUserService{
}
2.2.2 Mapper層CRUD
mybatis-plus將常用的CRUD接口封裝成了BaseMapper
接口,我們只需要在自己的Mapper中繼承它就可以了:
/**
*@description:用戶mapper
*@author:weirx
*@date:2022/1/17 14:55
*@version:3.0
*/
@Mapper
publicinterfaceUserMapperextendsBaseMapper<UserDO>{
}
2.3 分頁
使用分頁話需要增加分頁插件的配置:
importcom.baomidou.mybatisplus.annotation.DbType;
importcom.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
importcom.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
importorg.mybatis.spring.annotation.MapperScan;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.wjbgn.*.mapper*")
publicclassMybatisPlusConfig{
@Bean
publicMybatisPlusInterceptormybatisPlusInterceptor(){
MybatisPlusInterceptorinterceptor=newMybatisPlusInterceptor();
interceptor.addInnerInterceptor(newPaginationInnerInterceptor(DbType.MYSQL));
returninterceptor;
}
}
如上配置后,我們直接使用分頁方法就行。
2.4 邏輯刪除配置
很多情況下我們的系統(tǒng)都需要邏輯刪除,方便恢復(fù)查找誤刪除的數(shù)據(jù)。
通過mybatis-plus可以通過全局配置的方式,而不需要再去手動處理。針對更新和查詢操作有效,新增不做限制。
通常以我的習(xí)慣邏輯刪除字段通常定義為is_delete
,在實(shí)體類當(dāng)中就是isDelete
。那么在配置文件中就可以有如下的配置:
mybatis-plus:
global-config:
db-config:
logic-delete-field:isDelete#全局邏輯刪除的實(shí)體字段名(since3.3.0,配置后可以忽略不配置步驟2)
logic-delete-value:1#邏輯已刪除值(默認(rèn)為1)
logic-not-delete-value:0#邏輯未刪除值(默認(rèn)為0)
或者通過注解@TableLogic
@TableLogic
privateIntegerisDelete;
2.5 通用枚舉配置
相信后端的同學(xué)都經(jīng)歷過一個情況,比如性別
這個字段,分別值和名稱對應(yīng)1男
、2女
,這個字段在數(shù)據(jù)庫時是數(shù)值類型,而前端展示則是展示字符串的名稱。有幾種常見實(shí)現(xiàn)方案呢?
- 數(shù)據(jù)庫查詢sql通過case判斷,返回名稱,以前oracle經(jīng)常這么做
- 數(shù)據(jù)庫返回的值,重新遍歷賦值進(jìn)去,這時候還需要判斷這個值到底是男是女。
- 前端寫死,返回1就是男,返回2就是女。
相信無論哪種方法都有其缺點(diǎn),所以我們可以使用mybatis-plus提供的方式。我們在返回給前端時:
- 只需要在遍歷時get這個枚舉,直接賦值其名稱,不需要再次判斷。
- 直接返回給前端,讓前端去去枚舉的name
這樣大家都不需要寫死這個值。
下面看看如何實(shí)現(xiàn)這個功能:
- 性別枚舉,實(shí)現(xiàn)IEnum接口:
importcom.baomidou.mybatisplus.annotation.IEnum;
importcom.fasterxml.jackson.annotation.JsonFormat;
/**
*@description:性別枚舉
*@author:weirx
*@date:2022/1/17 16:26
*@version:3.0
*/
@JsonFormat(shape=JsonFormat.Shape.OBJECT)
publicenumSexEnumimplementsIEnum{
MAN(1,"男"),
WOMAN(2,"女");
privateIntegercode;
privateStringname;
SexEnum(Integercode,Stringname){
this.code=code;
this.name=name;
}
@Override
publicIntegergetValue(){
returncode;
}
publicStringgetName(){
returnname;
}
}
@JsonFormat注解為了解決枚舉類返回前端只展示構(gòu)造器名稱的問題。
- 實(shí)體類性別字段
@TableName(value="user")
publicclassUserDO{
/**
*主鍵
*/
@TableId(value="id",type=IdType.AUTO)
privateLongid;
/**
*昵稱
*/
@TableField(value="nickname",condition=SqlCondition.EQUAL)
privateStringnickname;
/**
*性別
*/
@TableField(value="sex")
privateSexEnumsex;
/**
*版本
*/
@TableField(value="version",update="%s+1")
privateIntegerversion;
/**
*時間字段,自動添加
*/
@TableField(value="create_time",fill=FieldFill.INSERT)
privateLocalDateTimecreateTime;
}
- 配置文件掃描枚舉
mybatis-plus:
#支持統(tǒng)配符*或者;分割
typeEnumsPackage:com.wjbgn.*.enums
- 定義配置文件
@Bean
publicMybatisPlusPropertiesCustomizermybatisPlusPropertiesCustomizer(){
returnproperties->{
GlobalConfigglobalConfig=properties.getGlobalConfig();
globalConfig.setBanner(false);
MybatisConfigurationconfiguration=newMybatisConfiguration();
configuration.setDefaultEnumTypeHandler(MybatisEnumTypeHandler.class);
properties.setConfiguration(configuration);
};
}
-
序列化枚舉值為數(shù)據(jù)庫值,以下我是使用的fastjson,全局(添加在前面的配置文件中):
Bean
publicMybatisPlusPropertiesCustomizermybatisPlusPropertiesCustomizer(){
//序列化枚舉值為數(shù)據(jù)庫存儲值
FastJsonConfigconfig=newFastJsonConfig();
config.setSerializerFeatures(SerializerFeature.WriteEnumUsingToString);
returnproperties->{
GlobalConfigglobalConfig=properties.getGlobalConfig();
globalConfig.setBanner(false);
MybatisConfigurationconfiguration=newMybatisConfiguration();
configuration.setDefaultEnumTypeHandler(MybatisEnumTypeHandler.class);
properties.setConfiguration(configuration);
};
}
- 局部
JSONField(serialzeFeatures=SerializerFeature.WriteEnumUsingToString)
privateSexEnumsex;
2.6 自動填充
還記得前面提到的實(shí)體類當(dāng)中的注解@TableFeild
嗎?當(dāng)中有個屬性叫做fill,通過FieldFill
設(shè)置屬性,這個就是做自動填充用的。
publicenumFieldFill{
/**
*默認(rèn)不處理
*/
DEFAULT,
/**
*插入填充字段
*/
INSERT,
/**
*更新填充字段
*/
UPDATE,
/**
*插入和更新填充字段
*/
INSERT_UPDATE
}
但是這個直接是不能使用的,需要通過實(shí)現(xiàn)mybatis-plus提供的接口,增加如下配置:
importcom.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
importorg.apache.ibatis.reflection.MetaObject;
importorg.springframework.stereotype.Component;
importjava.time.LocalDateTime;
/**
*description:啟動自動填充功能
*@return:
*@author:weirx
*@time:2022/1/1717:00
*/
@Component
publicclassMyMetaObjectHandlerimplementsMetaObjectHandler{
@Override
publicvoidinsertFill(MetaObjectmetaObject){
//起始版本3.3.0(推薦使用)
this.strictInsertFill(metaObject,"createTime",LocalDateTime.class,LocalDateTime.now());
}
@Override
publicvoidupdateFill(MetaObjectmetaObject){
//起始版本3.3.0(推薦)
this.strictUpdateFill(metaObject,"updateTime",LocalDateTime.class,LocalDateTime.now());
}
}
字段如下:
/**
*時間字段,自動添加
*/
@TableField(value="create_time",fill=FieldFill.INSERT)
privateLocalDateTimecreateTime;
2.7 多數(shù)據(jù)源
前面提到過,配置文件當(dāng)中配置了主從的方式,其實(shí)mybatis-plus還支持更多的方式:
- 多主多從
spring:
datasource:
dynamic:
primary:master#設(shè)置默認(rèn)的數(shù)據(jù)源或者數(shù)據(jù)源組,默認(rèn)值即為master
strict:false#嚴(yán)格匹配數(shù)據(jù)源,默認(rèn)false.true未匹配到指定數(shù)據(jù)源時拋異常,false使用默認(rèn)數(shù)據(jù)源
datasource:
master_1:
master_2:
slave_1:
slave_2:
slave_3:
- 多種數(shù)據(jù)庫
spring:
datasource:
dynamic:
primary:mysql#設(shè)置默認(rèn)的數(shù)據(jù)源或者數(shù)據(jù)源組,默認(rèn)值即為master
strict:false#嚴(yán)格匹配數(shù)據(jù)源,默認(rèn)false.true未匹配到指定數(shù)據(jù)源時拋異常,false使用默認(rèn)數(shù)據(jù)源
datasource:
mysql:
oracle:
postgresql:
h2:
sqlserver:
- 混合配置
spring:
datasource:
dynamic:
primary:master#設(shè)置默認(rèn)的數(shù)據(jù)源或者數(shù)據(jù)源組,默認(rèn)值即為master
strict:false#嚴(yán)格匹配數(shù)據(jù)源,默認(rèn)false.true未匹配到指定數(shù)據(jù)源時拋異常,false使用默認(rèn)數(shù)據(jù)源
datasource:
master_1:
slave_1:
slave_2:
oracle_1:
oracle_2:
上面的三種方式,除了混合配置,我覺得都有肯能出現(xiàn)的吧。
- @DS注解
可以注解在方法上或類上,同時存在就近原則 【方法上注解】 優(yōu)先于 【類上注解】:
@DS("slave_1")
publicclassUserServiceImplextendsServiceImpl<UserMapper,UserDO>implementsIUserService{
@DS("salve_1")
@Override
publicListgetList() {
returnthis.getList();
}
@DS("master")
@Override
publicintsaveUser(UserDOuserDO){
booleansave=this.save(userDO);
if(save){
return1;
}else{
return0;
}
}
}
三、測試
經(jīng)過上面的配置,下面開始進(jìn)入測試驗(yàn)證階段。
建立一張表:
CREATETABLE`user`(
`id`int(11)NOTNULLAUTO_INCREMENT,
`nickname`varchar(255)NOTNULLCOMMENT'昵稱',
`sex`tinyint(1)NOTNULLCOMMENT'性別,1男2女',
`create_time`datetimeNOTNULLCOMMENT'創(chuàng)建時間',
`is_delete`tinyint(1)NOTNULLDEFAULT'0'COMMENT'是否刪除1是,0否',
PRIMARYKEY(`id`)
)ENGINE=InnoDBAUTO_INCREMENT=50DEFAULTCHARSET=utf8mb4;
controller:
/**
*@description:用戶controller
*@author:weirx
*@date:2022/1/17 17:39
*@version:3.0
*/
@RestController
@RequestMapping("/user")
publicclassUserController{
@Autowired
privateIUserServiceuserService;
/**
*description:新增
*@return:boolean
*@author:weirx
*@time:2022/1/1719:11
*/
@RequestMapping("/save")
publicbooleansave(){
UserDOuserDO=newUserDO();
userDO.setNickname("大漂亮");
userDO.setSex(SexEnum.MAN);
returnuserService.save(userDO);
}
/**
*description:修改
*@paramnickname
*@paramid
*@return:boolean
*@author:weirx
*@time:2022/1/1719:11
*/
@RequestMapping("/update")
publicbooleanupdate(@RequestParamStringnickname,@RequestParamLongid){
UserDOuserDO=newUserDO();
userDO.setNickname(nickname);
userDO.setId(id);
returnuserService.updateById(userDO);
}
/**
*description:刪除
*@paramid
*@return:boolean
*@author:weirx
*@time:2022/1/1719:11
*/
@RequestMapping("/delete")
publicbooleandelete(@RequestParamLongid){
UserDOuserDO=newUserDO();
userDO.setId(id);
returnuserService.removeById(userDO);
}
/**
*description:列表
*@return:java.util.List
*@author:weirx
*@time:2022/1/1719:11
*/
@RequestMapping("/list")
publicListlist() {
returnuserService.list();
}
/**
*description:分頁列表
*@paramcurrent
*@paramsize
*@return:com.baomidou.mybatisplus.extension.plugins.pagination.Page
*@author:weirx
*@time:2022/1/1719:11
*/
@RequestMapping("/page")
publicPagepage(@RequestParamintcurrent,@RequestParamintsize){
returnuserService.page(newPage<>(current,size),newQueryWrapper(newUserDO()));
}
}
記過上面的接口驗(yàn)證,功能沒有問題,集成成功。
項目源碼地址
https://gitee.com/wei_rong_xin/rob-necessities
審核編輯:湯梓紅
-
spring
+關(guān)注
關(guān)注
0文章
340瀏覽量
14343 -
mybatis
+關(guān)注
關(guān)注
0文章
60瀏覽量
6713
原文標(biāo)題:看了我的MyBatis-Plus用法,同事也開始悄悄模仿了...
文章出處:【微信號:AndroidPush,微信公眾號:Android編程精選】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論