close
(給ImportNew加星標,提高Java技能)
本文主要介紹mybatis-plus這款插件,針對springboot用戶。包括引入,配置,使用,以及擴展等常用的方面做一個匯總整理,儘量包含大家常用的場景內容。

關於mybatis-plus是什麼,不多做介紹了,看官方文檔:baomidou.com ,咱們直接代碼擼起來。

一、快速開始

本文基於springboot、maven、jdk1.8、mysql開發,所以開始前我們需要準備好這套環境。我的環境使用了nacos作為註冊中心,不了解或需要搭建的參考:https://juejin.cn/post/7053977860612030477

新建如下數據庫:

建議大家選擇utf8mb4這種字符集,做過微信的同學應該會知道,微信用戶名稱的表情,是需要這種字符集才能存儲的。

我就默認其他環境已經準備好了,咱們直接從mybatis-plus開始。

1.1 依賴準備

想要什麼依賴版本的去maven倉庫查看:https://mvnrepository.com/

引入mybatis-plus依賴:

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.0</version></dependency>

引入mysql依賴:

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version></dependency>

目前,多數項目會有多數據源的要求,或者是主從部署的要求,所以我們還需要引入mybatis-plus關於多數據源的依賴:

<!--mybatis-plus多數據源--><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.5.0</version></dependency>1.2 配置準備

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")@SpringBootApplicationpublicclassRobNecessitiesUserApplication{publicstaticvoidmain(String[]args){SpringApplication.run(RobNecessitiesUserApplication.class,args);}}

數據源配置,此處配置一主一從的環境,當前我只有一台,所以此處配置一樣的:

spring:datasource:dynamic:primary:master#設置默認的數據源或者數據源組,默認值即為masterstrict:false#嚴格匹配數據源,默認false.true未匹配到指定數據源時拋異常,false使用默認數據源datasource:master:url:jdbc:mysql://127.0.0.1:3306/rob_necessities?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghaiusername:rootpassword:123456slave_1:url:jdbc:mysql://127.0.0.1:3306/rob_necessities?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghaiusername:rootpassword:123456

補充:這裡面因為默認使用的是HikariCP數據源,目前也推薦使用這個,相比於druid有更高的性能,但是不能忽略下面的配置,否則服務會不斷拋出異常,原因是數據庫的連接時常和連接池的配置沒有做好。

spring:datasource:dynamic:hikari:max-lifetime:1800000connection-timeout:5000idle-timeout:3600000max-pool-size:12min-idle:4connection-test-query:/**ping*/1.3 啟動服務

下面直接啟動服務:

得到如上結果表示啟動成功了。

二、使用

前面我們成功的集成進來了mybatis-plus,配合springboot使用不要太方便。下面我們看看如何使用它來操作我們的數據庫。介紹一下常規的用法。

2.1 實體類註解

mybatis-plus為使用者封裝了很多的註解,方便我們使用,我們首先看下實體類中有哪些註解。有如下的實體類:

@TableName(value="user")publicclassUserDO{/***主鍵*/@TableId(value="id",type=IdType.AUTO)privateLongid;/***暱稱*/@TableField("nickname")privateStringnickname;/***真實姓名*/privateStringrealName;}
@TableName 表名註解,用於標識實體類對應的表。其說明如下,關於這些書寫,常規情況基本很少用到,不做多餘解釋了:
@Documented@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.TYPE,ElementType.ANNOTATION_TYPE})public@interfaceTableName{/***實體對應的表名*/Stringvalue()default"";/***schema**@since3.1.1*/Stringschema()default"";/***是否保持使用全局的tablePrefix的值*<p>只生效於既設置了全局的tablePrefix也設置了上面{@link#value()}的值</p>*<li>如果是false,全局的tablePrefix不生效</li>**@since3.1.1*/booleankeepGlobalPrefix()defaultfalse;/***實體映射結果集,*只生效與mp自動注入的method*/StringresultMap()default"";/***是否自動構建resultMap並使用,*只生效與mp自動注入的method,*如果設置resultMap則不會進行resultMap的自動構建並注入,*只適合個別字段設置了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數據庫自增IDNONE該類型為未設置主鍵類型(註解里等於跟隨全局,全局裡約等於 INPUT)INPUT用戶自己設置的IDASSIGN_ID當用戶傳入為空時,自動分配類型為Number或String的主鍵(雪花算法)ASSIGN_UUID當用戶傳入為空時,自動分配類型為String的主鍵

@TableFiled 表字段標識,下面看看其主要常用屬性:

名稱描述value數據庫字段名condition字段 where 實體查詢比較條件,通過SqlCondition設置 如果未設置條件,則按照正常相等來查詢 若設置則按照以下規則:等於: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設置 不處理:FieldFill.DEFAULT 插入時填充字段:FieldFill.INSERT 更新時填充字段:FieldFill.UPDATE 插入或新增時填充字段:FieldFill.INSERT_UPDATE

關於其他的屬性,我不太推薦使用,用得越多,越容易蒙圈。可以通過wapper查詢去設置。

2.2 CRUD

mybatis-plus封裝好了一條接口供我們直接調用。關於內部的具體方法,在使用時候自己體會吧,此處不列舉了。

2.2.1 Service層CRUD

我們使用的時候,需要在自己定義的service接口當中繼承IService接口:

importcom.baomidou.mybatisplus.extension.service.IService;importcom.wjbgn.user.entity.UserDO;/***@description:用戶服務接口*@author:weirx*@date:2022/1/17 15:02*@version:3.0*/publicinterfaceIUserServiceextendsIService<UserDO>{}

同時要在我們的接口實現impl當中繼承ServiceImpl,實現自己的接口:

importcom.baomidou.mybatisplus.extension.service.impl.ServiceImpl;importcom.wjbgn.user.entity.UserDO;importcom.wjbgn.user.mapper.UserMapper;importcom.wjbgn.user.service.IUserService;/***@description:用戶接口實現*@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*/@MapperpublicinterfaceUserMapperextendsBaseMapper<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{@BeanpublicMybatisPlusInterceptormybatisPlusInterceptor(){MybatisPlusInterceptorinterceptor=newMybatisPlusInterceptor();interceptor.addInnerInterceptor(newPaginationInnerInterceptor(DbType.MYSQL));returninterceptor;}}

如上配置後,我們直接使用分頁方法就行。

2.4 邏輯刪除配置

很多情況下我們的系統都需要邏輯刪除,方便恢復查找誤刪除的數據。

通過mybatis-plus可以通過全局配置的方式,而不需要再去手動處理。針對更新和查詢操作有效,新增不做限制。

通常以我的習慣邏輯刪除字段通常定義為is_delete,在實體類當中就是isDelete。那麼在配置文件中就可以有如下的配置:

mybatis-plus:global-config:db-config:logic-delete-field:isDelete#全局邏輯刪除的實體字段名(since3.3.0,配置後可以忽略不配置步驟2)logic-delete-value:1#邏輯已刪除值(默認為1)logic-not-delete-value:0#邏輯未刪除值(默認為0)

或者通過註解@TableLogic

@TableLogicprivateIntegerisDelete;2.5 通用枚舉配置

相信後端的同學都經歷過一個情況,比如性別這個字段,分別值和名稱對應1男、2女,這個字段在數據庫時是數值類型,而前端展示則是展示字符串的名稱。有幾種常見實現方案呢?

數據庫查詢sql通過case判斷,返回名稱,以前oracle經常這麼做
數據庫返回的值,重新遍歷賦值進去,這時候還需要判斷這個值到底是男是女。
前端寫死,返回1就是男,返回2就是女。

相信無論哪種方法都有其缺點,所以我們可以使用mybatis-plus提供的方式。我們在返回給前端時:

只需要在遍歷時get這個枚舉,直接賦值其名稱,不需要再次判斷。
直接返回給前端,讓前端去去枚舉的name

這樣大家都不需要寫死這個值。

下面看看如何實現這個功能:

性別枚舉,實現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<Integer>{MAN(1,"男"),WOMAN(2,"女");privateIntegercode;privateStringname;SexEnum(Integercode,Stringname){this.code=code;this.name=name;}@OverridepublicIntegergetValue(){returncode;}publicStringgetName(){returnname;}}

@JsonFormat註解為了解決枚舉類返回前端只展示構造器名稱的問題。

實體類性別字段
@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:#支持統配符*或者;分割typeEnumsPackage:com.wjbgn.*.enums
定義配置文件
@BeanpublicMybatisPlusPropertiesCustomizermybatisPlusPropertiesCustomizer(){returnproperties->{GlobalConfigglobalConfig=properties.getGlobalConfig();globalConfig.setBanner(false);MybatisConfigurationconfiguration=newMybatisConfiguration();configuration.setDefaultEnumTypeHandler(MybatisEnumTypeHandler.class);properties.setConfiguration(configuration);};}

序列化枚舉值為數據庫值,以下我是使用的fastjson,全局(添加在前面的配置文件中):

BeanpublicMybatisPlusPropertiesCustomizermybatisPlusPropertiesCustomizer(){//序列化枚舉值為數據庫存儲值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 自動填充

還記得前面提到的實體類當中的註解@TableFeild嗎?當中有個屬性叫做fill,通過FieldFill設置屬性,這個就是做自動填充用的。

publicenumFieldFill{/***默認不處理*/DEFAULT,/***插入填充字段*/INSERT,/***更新填充字段*/UPDATE,/***插入和更新填充字段*/INSERT_UPDATE}

但是這個直接是不能使用的,需要通過實現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*/@ComponentpublicclassMyMetaObjectHandlerimplementsMetaObjectHandler{@OverridepublicvoidinsertFill(MetaObjectmetaObject){//起始版本3.3.0(推薦使用)this.strictInsertFill(metaObject,"createTime",LocalDateTime.class,LocalDateTime.now());}@OverridepublicvoidupdateFill(MetaObjectmetaObject){//起始版本3.3.0(推薦)this.strictUpdateFill(metaObject,"updateTime",LocalDateTime.class,LocalDateTime.now());}}

字段如下:

/***時間字段,自動添加*/@TableField(value="create_time",fill=FieldFill.INSERT)privateLocalDateTimecreateTime;2.7 多數據源

前面提到過,配置文件當中配置了主從的方式,其實mybatis-plus還支持更多的方式:

多主多從
spring:datasource:dynamic:primary:master#設置默認的數據源或者數據源組,默認值即為masterstrict:false#嚴格匹配數據源,默認false.true未匹配到指定數據源時拋異常,false使用默認數據源datasource:master_1:master_2:slave_1:slave_2:slave_3:
多種數據庫
spring:datasource:dynamic:primary:mysql#設置默認的數據源或者數據源組,默認值即為masterstrict:false#嚴格匹配數據源,默認false.true未匹配到指定數據源時拋異常,false使用默認數據源datasource:mysql:oracle:postgresql:h2:sqlserver:
混合配置
spring:datasource:dynamic:primary:master#設置默認的數據源或者數據源組,默認值即為masterstrict:false#嚴格匹配數據源,默認false.true未匹配到指定數據源時拋異常,false使用默認數據源datasource:master_1:slave_1:slave_2:oracle_1:oracle_2:

上面的三種方式,除了混合配置,我覺得都有肯能出現的吧。

@DS註解

可以註解在方法上或類上,同時存在就近原則 【方法上註解】 優先於 【類上註解】:

@DS("slave_1")publicclassUserServiceImplextendsServiceImpl<UserMapper,UserDO>implementsIUserService{@DS("salve_1")@OverridepublicList<UserDO>getList(){returnthis.getList();}@DS("master")@OverridepublicintsaveUser(UserDOuserDO){booleansave=this.save(userDO);if(save){return1;}else{return0;}}}三、測試

經過上面的配置,下面開始進入測試驗證階段。

建立一張表:

CREATETABLE`user`(`id`int(11)NOTNULLAUTO_INCREMENT,`nickname`varchar(255)NOTNULLCOMMENT'暱稱',`sex`tinyint(1)NOTNULLCOMMENT'性別,1男2女',`create_time`datetimeNOTNULLCOMMENT'創建時間',`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{@AutowiredprivateIUserServiceuserService;/***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<com.wjbgn.user.entity.UserDO>*@author:weirx*@time:2022/1/1719:11*/@RequestMapping("/list")publicList<UserDO>list(){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()));}}

記過上面的接口驗證,功能沒有問題,集成成功。

項目源碼地址

https://gitee.com/wei_rong_xin/rob-necessities

作者:我犟不過你 來源:juejin.cn/post/7054726274362638350

- EOF -

推薦閱讀點擊標題可跳轉

秒殺系統的藝術

高並發,你真的理解透徹了嗎?

高並發下如何防重?

看完本文有收穫?請轉發分享給更多人

關注「ImportNew」,提升Java技能

點讚和在看就是最大的支持❤️

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()