MyBatis-Plus 條件查詢器的實現
本篇的主要代碼依賴於之前的通用Mapper和通用Service篇
一、常用註解
在我們平時的日常開發中,會經常遇到我們的數據小夥伴們在數據庫中所創建的 表名要與我們Java開發人員所建的domian層的類名有一個對應關系
,這往往在不同的公司都有著不同的要求。
打個比方:數據庫表名 t_user
——– 後臺domian的實體類名User
。這樣很明顯會操做報錯。
所以我們的MyBtais-Plus為我們提供瞭一系列的註解,下面我們來正式學習他們
1.1 @TableName
在實體類上加上註解@TableName("t_user")
,標識這個類所對應的表名是t_user,這樣才可以成功映射到對應的字段。
@TableName("t_user") public class User { private Long id; private String userName; private Integer age; private String email; }
以上是通過註解的方式完成,我們也可以通過配置文件來設置
mybatis-plus: configuration: # 配置MyBatis日志 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: # 配置MyBatis-Plus操作表的默認前綴 table-prefix: t_
通過table_prefix設置前綴隻適用於數據庫表有前綴的,如果表名與實體類名差別甚遠,則建議使用註解
1.2 @TableId
MyBatis-Plus在實現CRUD時,會默認將id作為主鍵列,並在插入數據時,默認是基於雪花算法的策略生成id
ASSIGN_ID
【產生的問題】
- 若實體類和表中表示主鍵的不是id,而是其他字段 如何匹配
- 怎樣實現數據庫中的自增策略
【對策】
在實體類中uid屬性上通過@TableId將其標識為主鍵
,即可成功執行SQL語句
@TableName("t_user") public class User { @TableId(value = "id", type = IdType.AUTO) private Long id; private String userName; private Integer age; private String email; }
這裡有必要說下,idType,這個IdType
是MyBatis-plus裡面所提供的一種主鍵生成策略的枚舉類
【源碼】
@Getter public enum IdType { /** * 數據庫ID自增 * <p>該類型請確保數據庫設置瞭 ID自增 否則無效</p> */ AUTO(0), /** * 該類型為未設置主鍵類型(註解裡等於跟隨全局,全局裡約等於 INPUT) */ NONE(1), /** * 用戶輸入ID * <p>該類型可以通過自己註冊自動填充插件進行填充</p> */ INPUT(2), /* 以下3種類型、隻有當插入對象ID 為空,才自動填充。 */ /** * 分配ID (主鍵類型為number或string), * 默認實現類 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(雪花算法) * * @since 3.3.0 */ ASSIGN_ID(3), /** * 分配UUID (主鍵類型為 string) * 默認實現類 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(UUID.replace("-","")) */ ASSIGN_UUID(4); private final int key; IdType(int key) { this.key = key; } }
也就是說MP提供瞭5種測類,下面簡要的介紹其中的某些:
AUTO:
數據庫自增策略,註意,該類型請確保數據庫設置瞭id自增, 否則無效
- NONE:MP set主鍵,雪花算法實現。就是如果傳瞭id用傳的,否則默認的雪花算法
- INPUT:需要時開發者手動賦值,沒寫一樣雪花算法自動生成
- ASSIGN_ID: 雪花算法,默認,與數據庫id是否設置瞭自增無關
1.3 @TableField
TableField與TableId的區別就是:
- TableField適用於解決非主鍵字段不匹配的情況,而且TableField還可以指定那個字段查詢的時候不顯示
- TableId主要解決主鍵不匹配的情況
@TableName("t_user") public class User { // 處理主鍵相關的字段名不一致 以及設置主鍵自增策略 @TableId(value = "id", type = IdType.AUTO) private Long id; // 在mp種默認的設置可以將數據庫中的字段名xxx_xxx轉化為相應的駝峰命名 @TableField(value = "user_name") private String userName; @TableField(value = "age") private Integer age; // exist=false 表示查詢時候不顯示 @TableField(exist = false) private String email; }
當我們使用瞭@TableField(exist = false)
則在查詢的時候就不會顯示查詢出來的值
1.4 @TableLogic
邏輯刪除
在我們的日常開發中,會經常遇到這種邏輯刪除的操做,因為這樣仍然會在數據庫中保存這條數據,防止後期如果還想用的話還可以找到。我們要時刻銘記,數據的CUD操做,一定要謹慎,謹慎,再謹慎!!!
如果我們的業務對數據的要求是可以恢復的,我們就要使用邏輯刪除操做,一般我們就在數據庫種加一個字段is_deleted
物理刪除
:真實刪除,將對應數據從數據庫中刪除,之後查詢不到此條被刪除的數據邏輯刪除
:假刪除,將對應數據中代表是否被刪除字段的狀態修改為“被刪除狀態”,之後在數據庫中仍舊能看到此條數據記錄- 使用場景:可以進行數據恢復
@TableName("t_user") public class User { // 處理主鍵相關的字段名不一致 以及設置主鍵自增策略 @TableId(value = "id", type = IdType.AUTO) private Long id; // 在mp種默認的設置可以將數據庫中的字段名xxx_xxx轉化為相應的駝峰命名 @TableField(value = "user_name") private String userName; @TableField(value = "age") private Integer age; @TableField(value = "email") private String email; // 邏輯刪除 0 標識未刪除 1表示刪除瞭 @TableLogic private Integer isDeleted; }
註意:
當我們使用瞭邏輯刪除則刪除操作就變成瞭修改操作
測試刪除功能,真正執行的是修改
UPDATE t_user SET is_deleted=1 WHERE id=? AND is_deleted=0
測試查詢功能,被邏輯刪除的數據默認不會被查詢
SELECT id,username AS name,age,email,is_deleted FROM t_user WHERE is_deleted=0
二、條件構造器Wrapper
Wrapper在MyBatis-plus裡面主要分為兩種:一種適用於查詢的 QueryWrapper;一種是用於修改的UpdateWrapper
【繼承關系】
Wrapper : 條件構造抽象類,最頂端父類
- AbstractWrapper : 用於查詢條件封裝,生成 sql 的 where 條件
- QueryWrapper : 查詢條件封裝
- UpdateWrapper : Update 條件封裝
- AbstractLambdaWrapper : 使用Lambda 語法
- LambdaQueryWrapper :用於Lambda語法使用的查詢Wrapper
- LambdaUpdateWrapper : Lambda 更新封裝Wrapper
這裡主要就是介紹QueryWrapper和UpdateWrapper
2.1 QueryWrapper
上圖是BaseMapper裡面的關於參數是Warpper的方法,下面我們一一介紹:
2.1.1 組裝查詢條件selectCount
/** * 測試wraper封裝查詢條件1 * * @throws Exception */ @Test public void testQuery5() { QueryWrapper<User> queryWrapper = new QueryWrapper<User>(); // sql: SELECT COUNT( * ) FROM t_user WHERE is_deleted=0 AND (age BETWEEN ? AND // ?) queryWrapper.between("age", 18, 23); Long list = userMapper.selectCount(queryWrapper); System.out.println(list); }
2.1.2 組裝查詢條件selectList
/** * 測試wraper封裝查詢條件2 * * @throws Exception */ @Test public void testQuery9() { QueryWrapper<User> queryWrapper = new QueryWrapper<User>(); // SELECT id,user_name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND // (email IS NOT NULL AND email LIKE ?) queryWrapper.isNotNull("email").like("email", "163.com"); List<User> list = userMapper.selectList(queryWrapper); list.forEach(System.out::println); }
2.1.3 組裝查詢參數selectMaps
/** * 測試wraper封裝查詢條件3 * * @throws Exception */ @Test public void testQuery10() { QueryWrapper<User> queryWrapper = new QueryWrapper<User>(); // SELECT age,email,user_name FROM t_user WHERE is_deleted=0 queryWrapper.select("age", "email", "user_name"); List<Map<String, Object>> list = userMapper.selectMaps(queryWrapper); list.forEach(System.out::println); }
2.1.4 組裝查詢selectOne
/** * 測試wraper封裝查詢條件4 * * @throws Exception */ @Test public void testQuery11() { QueryWrapper<User> queryWrapper = new QueryWrapper<User>(); // SELECT age,email,user_name FROM t_user WHERE is_deleted=0 AND (user_name = ?) queryWrapper.select("age", "email", "user_name"); queryWrapper.eq("user_name", "test"); User list = userMapper.selectOne(queryWrapper); System.out.println(list); }
根據上述的方法,我們可以很輕松地觀察到,querywrapper裡面封裝瞭許多的方法就是用於設置我們的查詢條件,而且比較通俗易懂,比如ge大於等於
,between介於
等等,這裡隻演示這些,剩下的自己在開發中用到繼續摸索。
2.1.5 調整條件優先級
註意:
這裡說明下如何調整參數的優先級
,我們都知道在sql中可以通過()完成查詢條件的優先級提升,那麼在MP中如何操做???
【代碼演示】
通過and方法,利用lambda表達式實現
@Test public void testQuery7() throws Exception { User user = new User(); // 將用戶名中包含有a並且(年齡大於20或郵箱為null)的用戶信息修改 user.setEmail("[email protected]"); QueryWrapper<User> queryWrapper = new QueryWrapper<User>(); // UPDATE t_user SET age=?, email=? WHERE (user_name LIKE ? AND (age > ? OR email IS NULL)) queryWrapper.like("user_name", "a") .and( i -> i.ge("age", 20) .or() .isNull("email")); List<User> list = userMapper.selectList(queryWrapper); list.forEach(System.out::println); }
2.1.6 實現子查詢inSql
@GetMapping("/queryZI") public List<User> queryZI() { // SELECT id,user_name,age,email,is_deleted FROM t_user WHERE is_deleted=0 AND (id IN ( SELECT id FROM t_user WHERE id <=100)) QueryWrapper<User> queryWrapper = new QueryWrapper<User>(); queryWrapper.inSql("id", " SELECT id FROM t_user WHERE id <=100"); List<User> maps = userMapper.selectList(queryWrapper); return maps; }
2.2 UpdateWrapper
2.2.1 組裝修改條件update
@Test public void testUpdate2() throws Exception { User user = new User(); user.setEmail("[email protected]"); UpdateWrapper<User> updateWrapper = new UpdateWrapper<User>(); updateWrapper.ge("age", 20).like("user_name", "a").or().isNull("email"); /** * 根據 whereEntity 條件,更新記錄 * * @param entity 實體對象 (set 條件值,可以為 null) 修改的參數 * @param updateWrapper 實體對象封裝操作類(可以為 null,裡面的 entity 用於生成 where 語句)條件參數 */ int row = userMapper.update(user, updateWrapper); log.info("刪除數據={}條", row); }
三、MyBatis-Plus分頁插件
MyBatis Plus自帶分頁插件,隻要簡單的配置即可實現分頁功能
3.1 實現步驟
1️⃣添加配置類
/** * MybatisPlus的分頁插件配置類 * @author wangruoxian * */ @Configuration @MapperScan("com.wei.mapper") public class MyBatisPlusPageConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }
2️⃣ 測試
@GetMapping("/page") public IPage<User> pageList(){ Page<User> page = new Page<User>(1,3); // QueryWrapper<User> queryWrapper = new QueryWrapper<User>(); // // 當前頁碼 // page.setCurrent(1); // // 每頁顯示的條數 // page.setSize(5); IPage<User> selectPage = userMapper.selectPage(page, null); log.info("當前頁數={}",selectPage.getCurrent()); log.info("總頁數={}",selectPage.getPages()); selectPage.getRecords().forEach(System.out::println); log.info("每頁大小={}",selectPage.getSize()); log.info("總數據條數={}",selectPage.getTotal()); return selectPage; }
四、通用枚舉
表中的有些字段值是固定的,例如性別(男或女),此時我們可以使用MyBatis-Plus的通用枚舉來實現
4.1 數據庫表添加字段sex
4.2 配置掃描通用枚舉
# 配置掃描通用枚舉 type-enums-package: com.wei.enums
4.3 新建枚舉類
@Getter public enum SexEnum { MALE(0,"男"), FEMALE(1,"女"); @EnumValue private Integer sexCode; private String sexValue; private SexEnum(Integer sexCode, String sexValue) { this.sexCode = sexCode; this.sexValue = sexValue; } }
4.3.1 @EnumValue註解
通用的枚舉類註解,將數據庫字段映射成實體類的枚舉類型成員變量
將枚舉改成成員變量和數據庫的字段映射起來,根據數據庫字段的值找到對應枚舉的對象
4.4 測試
五、多數據源
適用於多種場景:純粹多庫、 讀寫分離、 一主多從、 混合模式等
,目前我們就來模擬一個純粹多庫的一個場景,其他場景類似
場景說明:
我們創建兩個庫,分別為:mybatis_plus(以前的庫不動)與mybatis_plus_1(新建),將
mybatis_plus庫的product表移動到mybatis_plus_1庫,這樣每個庫一張表,通過一個測試用例
分別獲取用戶數據與商品數據,如果獲取到說明多庫模擬成功
5.1 創建數據庫及表
CREATE DATABASE `mybatis_plus_slave` use `mybatis_plus_slave`; CREATE TABLE t_product ( id BIGINT(20) NOT NULL COMMENT '主鍵ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名稱', price INT(11) DEFAULT 0 COMMENT '價格', version INT(11) DEFAULT 0 COMMENT '樂觀鎖版本號', PRIMARY KEY (id) ); INSERT INTO product (id, NAME, price) VALUES (1, '外星人筆記本', 100);
5.2 引入依賴
<!-- 引入依賴 多數據源 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>3.3.1</version> </dependency>
5.3 配置多數據源
註意
註釋掉之前的配置 ,也可以新建一個項目進行測試
spring: # 配置數據源信息 datasource: dynamic: # 設置默認的數據源或者數據源組,默認值即為master primary: master # 嚴格匹配數據源,默認false.true未匹配到指定數據源時拋異常,false使用默認數據源 strict: false datasource: master: url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false driver-class-name: com.mysql.cj.jdbc.Driver username: root password: 123456 slave_1: url: jdbc:mysql://localhost:3306/mybatis_plus_1?characterEncoding=utf-8&useSSL=false driver-class-name: com.mysql.cj.jdbc.Driver username: root password: 123456
5.4 創建新庫中Product對應的類
此處省略domain,mapper,service,serviceImpl的創建
【controller層】
@RestController @RequestMapping("/product") @Api(value = "測試 ProductController 的接口", tags = "產品管理相關的接口", description = "product產品測試接口") public class ProductController { @Autowired private IProductService IProductService; @GetMapping("/list") // @ApiOperation("查詢所有商品的接口") public List<Product> queryAllProduct(){ return IProductService.list(); } }
到此這篇關於MyBatis-Plus 條件查詢器的實現的文章就介紹到這瞭,更多相關MyBatis-Plus 條件查詢器內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Mybatis-Plus查詢中如何排除標識字段
- mybatis plus實現條件查詢
- Mybatis Plus select 實現隻查詢部分字段
- Mybatis-Plus 通用CRUD的詳細操作
- MyBatis-Plus實現邏輯刪除的示例代碼