Mybatis-Plus 實(shí)戰(zhàn)教程
1.什么是Mybatis-Plus
1.1 什么是mybatis-plus
官網(wǎng):www.mybatis-plus.com/guide/
MyBatis-Plus(簡(jiǎn)稱 MP)是一個(gè) MyBatis 的增強(qiáng)工具,在 MyBatis 的基礎(chǔ)上只做增強(qiáng)不做改變,為簡(jiǎn)化開(kāi)發(fā)、提高效率而生。
1.2 官方愿景
1.3 特性
- 無(wú)侵入:只做增強(qiáng)不做改變,引入它不會(huì)對(duì)現(xiàn)有工程產(chǎn)生影響,如絲般順滑
- 損耗?。?jiǎn)?dòng)即會(huì)自動(dòng)注入基本 CURD,性能基本無(wú)損耗,直接面向對(duì)象操作
- 強(qiáng)大的 CRUD 操作:內(nèi)置通用 Mapper、通用 Service,僅僅通過(guò)少量配置即可實(shí)現(xiàn)單表大部分 CRUD 操作,更有強(qiáng)大的條件構(gòu)造器,滿足各類使用需求
- 支持 Lambda 形式調(diào)用:通過(guò) Lambda 表達(dá)式,方便地編寫各類查詢條件,無(wú)需再擔(dān)心字段寫錯(cuò)
- 支持主鍵自動(dòng)生成:支持多達(dá) 4 種主鍵策略(內(nèi)含分布式唯一 ID 生成器 – Sequence),可自由配置,完美解決主鍵問(wèn)題
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式調(diào)用,實(shí)體類只需繼承 Model 類即可進(jìn)行強(qiáng)大的 CRUD 操作
- 支持自定義全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 內(nèi)置代碼生成器:采用代碼或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 層代碼,支持模板引擎,更有超多自定義配置等您來(lái)使用
- 內(nèi)置分頁(yè)插件:基于 MyBatis 物理分頁(yè),開(kāi)發(fā)者無(wú)需關(guān)心具體操作,配置好插件之后,寫分頁(yè)等同于普通 List 查詢
- 分頁(yè)插件支持多種數(shù)據(jù)庫(kù):支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多種數(shù)據(jù)庫(kù)
- 內(nèi)置性能分析插件:可輸出 Sql 語(yǔ)句以及其執(zhí)行時(shí)間,建議開(kāi)發(fā)測(cè)試時(shí)啟用該功能,能快速揪出慢查詢
- 內(nèi)置全局?jǐn)r截插件:提供全表 delete 、 update 操作智能分析阻斷,也可自定義攔截規(guī)則,預(yù)防誤操作
1.4 支持?jǐn)?shù)據(jù)庫(kù)
- mysql 、 mariadb 、 oracle 、 db2 、 h2 、 hsql 、 sqlite 、 postgresql 、 sqlserver
1.5 框架結(jié)構(gòu)
從圖中我們可以看出,使用mybatis-plus可以自動(dòng)起別名,完成java對(duì)象與數(shù)據(jù)庫(kù)中記錄的映射,以及自動(dòng)創(chuàng)建CRUD,無(wú)需再去創(chuàng)建mapper配置文件了。
2. 快速入門
2.1 創(chuàng)建springboot項(xiàng)目
1.引入依賴
com.baomidou mybatis-plus-boot-starter 3.2.0復(fù)制代碼
- 注意:不需要在引入mybatis的相關(guān)依賴,只引入這一個(gè)即可,當(dāng)然數(shù)據(jù)庫(kù)相關(guān)的驅(qū)動(dòng)還的顯式引入
因?yàn)橐B接數(shù)據(jù)庫(kù),所以我們需要引入mysql、druid等依賴,下面是項(xiàng)目中所有的依賴
org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-devtools runtime true mysql mysql-connector-java runtime org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test com.baomidou mybatis-plus-boot-starter 3.2.0 com.alibaba druid 1.1.19復(fù)制代碼
為了防止創(chuàng)建maven過(guò)慢,我們可以使用阿里巴巴的鏡像
aliyun-repos http://maven.aliyun.com/nexus/content/groups/public/ false aliyun-plugin http://maven.aliyun.com/nexus/content/groups/public/ false 復(fù)制代碼
2.在入口類加入注解
@SpringBootApplication@MapperScan(“com.baizhi.dao”) // 掃描dao接口所在的包public class SpringbootMybatisplusApplication { public static void main(String[] args) { SpringApplication.run(SpringbootMybatisplusApplication.class, args); }}復(fù)制代碼
3.編寫配置文件
spring.datasource.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/mybatisplus?characterEncoding=UTF-8spring.datasource.username=rootspring.datasource.password=rootlogging.level.root=infologging.level.com.baizhi.dao=debug復(fù)制代碼
2.2 創(chuàng)建數(shù)據(jù)庫(kù)以及表結(jié)構(gòu)
DROP TABLE IF EXISTS `user`;CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, `bir` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;SET FOREIGN_KEY_CHECKS = 1;復(fù)制代碼
2.3 開(kāi)發(fā)實(shí)體類
實(shí)體類是什么,mybatisplus就會(huì)去數(shù)據(jù)庫(kù)中找相同名字的表
@Data //lombok的注解用來(lái)生成get set 等相關(guān)方法@AllArgsConstructor //有參構(gòu)造@NoArgsConstructor //無(wú)參構(gòu)造@ToString //toString方法@Accessors(chain = true) // 不寫默認(rèn)為false,當(dāng)該值為 true 時(shí),對(duì)應(yīng)字段的 setter 方法調(diào)用后,會(huì)返回當(dāng)前對(duì)象。public class User { private String id; private String name; private Integer age; private Date bir;}復(fù)制代碼
2.4 開(kāi)發(fā)mapper通用實(shí)現(xiàn)
import com.baomidou.mybatisplus.core.mapper.BaseMapper; //提供了各種CRUD方法// 使用mybatisplus的接口增強(qiáng)功能public interface UserDAO extends BaseMapper { // 方法不夠的話在DAO接口中寫方法,然后寫相應(yīng)的mapper配置文件對(duì)其做實(shí)現(xiàn) // 如果官網(wǎng)提供的方法不夠用的話,可以在這里自己寫方法并寫相應(yīng)的mapper配置文件即可}復(fù)制代碼
2.5 測(cè)試
@Autowiredprivate UserDAO userDAO;@Testvoid contextLoads() { List users = userDAO.selectList(null); System.out.println(users);}
3.常用注解說(shuō)明
- @TableName
- @TableId
- @TableField
3.1 @TableName注解
- 描述:用來(lái)將實(shí)體對(duì)象與數(shù)據(jù)庫(kù)表名完成映射
- 修飾范圍: 用在類上
- 常見(jiàn)屬性: value: String類型,指定映射的表名 resultMap: String類型,用來(lái)指定XML配置中resultMap的id值
3.2 @TableId注解
- 描述:主鍵注解
- 當(dāng)前對(duì)象的哪個(gè)屬性對(duì)應(yīng)數(shù)據(jù)庫(kù)的主鍵
- 修飾范圍:用在屬性上
- 常見(jiàn)屬性:
- value: String類型,指定實(shí)體類中與表中對(duì)應(yīng)的主鍵列名
- type: 枚舉類型,指定主鍵生成類型 type屬性寫枚舉類 IdType.AUTO
3.3 @TableField
- 描述:字段注解(非主鍵)
- 修飾范圍:用在屬性上
- 常用屬性: value: String類型,用來(lái)指定對(duì)應(yīng)的數(shù)據(jù)庫(kù)表中的字段名 el: String類型,映射為原生 #{ … } 邏輯,相當(dāng)于寫在 xml 里的 #{ … } 部分 3.0不存在 exist 如果對(duì)象中某一個(gè)屬性不是數(shù)據(jù)庫(kù)表中的字段,我們可以加上這個(gè)屬性,以免將它作為數(shù)據(jù)庫(kù)的列而產(chǎn)生錯(cuò)誤 boolean是否為數(shù)據(jù)庫(kù)表字段 true代表是數(shù)據(jù)庫(kù)字段,false代表不是
@Data //lombok的注解用來(lái)生成get set 等相關(guān)方法@AllArgsConstructor //有參構(gòu)造@NoArgsConstructor //無(wú)參構(gòu)造@ToString //toString方法@Accessors(chain = true) // 不寫默認(rèn)為false,當(dāng)該值為 true 時(shí),對(duì)應(yīng)字段的 setter 方法調(diào)用后,會(huì)返回當(dāng)前對(duì)象。@TableName(“tuser”) // 指定數(shù)據(jù)庫(kù)中與該對(duì)象對(duì)應(yīng)的表的名稱public class User { @TableId(value = “id”, type = IdType.AUTO) // 指定該屬性與表中的主鍵字段對(duì)應(yīng),value不寫表中字段為屬性名 private String id; @TableField // 指定該屬性與表中哪個(gè)字段對(duì)應(yīng),value屬性寫字段名,不寫表示字段名與屬性名一致 private String name; @TableField // 指定該屬性與表中哪個(gè)字段對(duì)應(yīng),value屬性寫字段名,不寫表示字段名與屬性名一致 private Integer age; @TableField // 指定該屬性與表中哪個(gè)字段對(duì)應(yīng) private Date bir; @TableField(exist = false) // 指定該屬性不與表中字段對(duì)應(yīng) private String aaa;}復(fù)制代碼
4.常用方法
4.1 查詢方法
selectList方法中的參數(shù)是用來(lái)幫我們做條件查詢的,如果為參數(shù)為null代表查詢所有數(shù)據(jù)
- 查詢所有
- @Test public void testFindAll(){ List users = userDAO.selectList(null); users.forEach(user-> System.out.println(“user = ” + user)); } 復(fù)制代碼
- 根據(jù)主鍵查詢一個(gè)
- @Test public void testFindOne(){ User user = userDAO.selectById(“1”); System.out.println(“user = ” + user); } 復(fù)制代碼
- 條件查詢
- //條件查詢 //泛型里面寫實(shí)體對(duì)象 @Test public void testFind(){ QueryWrapper queryWrapper = new QueryWrapper(); // 第一個(gè)字段應(yīng)該寫數(shù)據(jù)庫(kù)中表的字段名 queryWrapper.eq(“age”,23);//設(shè)置等值查詢,查詢age等于23的 //queryWrapper.lt(“age”,23);//設(shè)置小于查詢 //queryWrapper.ge(“age”,23);//小于等于查詢 gt 大于 ge 大于等于 List users = userDAO.selectList(queryWrapper); users.forEach(user-> System.out.println(user)); } 復(fù)制代碼
- 模糊查詢
- @Test public void testFindAll(){ QueryWrapper queryWrapper = new QueryWrapper(); // like %?% 內(nèi)容中包含對(duì)應(yīng)的值就可以了 // likeLeft %? 以···結(jié)尾的查詢 // likeRight ?% 以···開(kāi)頭的查詢 // queryWrapper.like(“username”,”小”); queryWrapper.likeRight(“username”,”小”); List users = userDAO.selectList(queryWrapper); users.forEach(user-> System.out.println(“user = ” + user)); } 復(fù)制代碼
- like 相當(dāng)于 %?%
- likeLeft 相當(dāng)于 %?
- likeRight 相當(dāng)于 ?%
4.2 添加方法
- 添加方法
- @Test public void testSave(){ User entity = new User(); entity.setAge(23).setName(“小明明”).setBir(new Date()); userDAO.insert(entity); } 復(fù)制代碼
4.3 修改方法
- 基于id修改
- @Test public void testUpdateById(){ User user = userDAO.selectById(“1”); user.setAge(24); userDAO.updateById(user); } 復(fù)制代碼
- 基于條件修改
- @Test public void testUpdate(){ User user = new User(); user.setName(“小陳陳”); QueryWrapper updateWrapper = new QueryWrapper(); updateWrapper.eq(true,”age”,23); // 修改age為23的記錄 userDAO.update(user, updateWrapper); // 修改age為23的記錄的name修改為百知教育 } 復(fù)制代碼
4.4 刪除方法
- 基于id刪除
- @Test public void testDeleteById(){ userDAO.deleteById(“3”); } 復(fù)制代碼
- 基于條件刪除
- @Test public void testDelete(){ QueryWrapper wrapper = new QueryWrapper(); wrapper.lambda().gt(“age”,23); // 刪除年齡大于 wrapper.lambda().eq(true,User::getAge,23); userDAO.delete(wrapper); } 復(fù)制代碼
5.Mybatis-Plus分頁(yè)查詢
分頁(yè)查詢的原理就是在查詢之后加上分頁(yè)的攔截,所以我們要實(shí)現(xiàn)在工廠中注冊(cè)攔截器類,所以我們實(shí)現(xiàn)需要?jiǎng)?chuàng)建一個(gè) MybatisPlusConfig 類。
0.預(yù)先配置
- 注意:使用分頁(yè)查詢必須設(shè)置mybatis-plus提供的分頁(yè)插件(配置),才能實(shí)現(xiàn)分頁(yè)效果
- @EnableTransactionManagement // 支持事務(wù)管理 @Configuration // 代表這是一個(gè)配置類 @MapperScan(“com.baizhi.dao”) // 掃描dao接口所在的包 public class MybatisPlusConfig { // 分頁(yè)的攔截器對(duì)象 @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); return paginationInterceptor; } } 復(fù)制代碼
- 注意事項(xiàng):目前分頁(yè)查詢僅僅支持單表查詢,不能在表連接時(shí)使用分頁(yè)插件
1.分頁(yè)查詢
- 非條件分頁(yè)查詢
- // 分頁(yè)查詢 @Test public void testFindPage(){ // 參數(shù)1:當(dāng)前頁(yè)從第幾頁(yè)開(kāi)始 參數(shù)2:當(dāng)前頁(yè)顯示幾條記錄 // 不傳參的話當(dāng)前頁(yè)從第1頁(yè)開(kāi)始,當(dāng)前頁(yè)顯示10條記錄 IPage page = new Page(1, 2); IPage userIPage = userDAO.selectPage(page, null); // 獲取總記錄數(shù) System.out.println(“總記錄數(shù):” + userIPage.getTotal()); // 獲取指定條件的記錄 userIPage.getRecords().forEach(user -> System.out.println(“user = ” + user)); } 復(fù)制代碼
- 帶條件分頁(yè)查詢
- @Test public void testFindAll(){ QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.eq(“age”,23); IPage page = new Page(1,2); page = userDAO.selectPage(page, queryWrapper); page.getRecords().forEach(user-> System.out.println(“user = ” + user)); } 復(fù)制代碼
6. Mybatis-Plus多數(shù)據(jù)源配置
引言
為了確保數(shù)據(jù)庫(kù)產(chǎn)品的穩(wěn)定性,很多數(shù)據(jù)庫(kù)擁有雙機(jī)熱備功能。也就是,第一臺(tái)數(shù)據(jù)庫(kù)服務(wù)器,是對(duì)外提供增刪改業(yè)務(wù)的生產(chǎn)服務(wù)器;第二臺(tái)數(shù)據(jù)庫(kù)服務(wù)器,主要進(jìn)行讀的操作?!?/p>
注意:這里我并沒(méi)有講解關(guān)于主從同步的配置,只是講了關(guān)于多數(shù)據(jù)源切換的配置,讀寫分離配置
6.1 引入dynamic-datasource-spring-boot-starter依賴
com.baomidou dynamic-datasource-spring-boot-starter 3.0.0復(fù)制代碼
6.2 配置數(shù)據(jù)源
使用多數(shù)據(jù)源的話就不需要原來(lái)application.properties中的dataSource配置了,使用下面的配置即可
spring.datasource.primary=master #指定默認(rèn)數(shù)據(jù)源spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.jdbc.Driverspring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/mybatis-plus?characterEncoding=UTF-8spring.datasource.dynamic.datasource.master.username=rootspring.datasource.dynamic.datasource.master.password=rootspring.datasource.dynamic.datasource.slave_1.driver-class-name=com.mysql.jdbc.Driverspring.datasource.dynamic.datasource.slave_1.url=jdbc:mysql://localhost:3306/mybatisplus-1?characterEncoding=UTF-8spring.datasource.dynamic.datasource.slave_1.username=rootspring.datasource.dynamic.datasource.slave_1.password=root
6.3 創(chuàng)建多個(gè)數(shù)據(jù)庫(kù)模擬不同mysql服務(wù)
一個(gè)mybatisplus數(shù)據(jù)庫(kù),一個(gè)是mybatisplus-1數(shù)據(jù)庫(kù)
6.4 @DS注解
- 作用: 用來(lái)切換數(shù)據(jù)源的注解
- 修飾范圍: 方法上和類上,同時(shí)存在則方法注解優(yōu)先于類上注解。
- Value屬性: 切換數(shù)據(jù)源名稱(不是數(shù)據(jù)庫(kù)名稱,是application.propertis配置文件中的,比如:master、slave_1等)
- 不使用這個(gè)注解的話默認(rèn)就是master
6.5 開(kāi)發(fā)業(yè)務(wù)層
- 業(yè)務(wù)接口
- public interface UserService{ List findAll(); void save(User user); } 復(fù)制代碼
- 業(yè)務(wù)實(shí)現(xiàn)類
- @Service @Transactional public class UserServiceImpl implements UserService { @Autowired private UserDAO userDAO; @Override @DS(“slave_1”) public List findAll() { return userDAO.selectList(null); } @Override public void save(User user) { userDAO.insert(user); } } 復(fù)制代碼
6.6 測(cè)試結(jié)果
package com.baizhi;import com.baizhi.entity.User;import com.baizhi.service.UserService;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import java.util.Date;@SpringBootTestpublic class TestUserService { @Autowired private UserService userService; @Test public void testFindAll(){ userService.findAll().forEach(user-> System.out.println(“user = ” + user)); } @Test public void testSave(){ User user = new User(); user.setName(“aaa”).setAge(23).setBir(new Date()); userService.save(user); }}
作者:嘿_魚骨頭鏈接:https://juejin.cn/post/7109612457923985444