一個多功能(聚合)查詢接口,實現(xiàn)模糊、分頁、主鍵、排序以及多條件查詢
前言
寫的啰嗦了點,看效果請直接忽略中間,直接看后半部分。
引個流,公眾號:小簡聊開發(fā)
概念
瞎編的名字,哈哈哈,我就勉強稱之為聚合查詢吧,不知道概念符不符合。
大家好,我是小簡,很久沒寫文章了,確實是太忙了,今天我異想天開(其實也有很多類似的實現(xiàn),只不過沒去封裝)的想去實現(xiàn)一個查詢接口,不同條件不同查詢的功能,簡單的玩玩,如果大家有更好的思路或者見解,可以評論區(qū)互動一下,我很菜,還請理解,大佬勿噴。
在日常開發(fā)中,我們基本上是使用RESTful接口,也就是一個接口對應一個功能,這很方便前端開發(fā)的對接,具體優(yōu)勢我想我就不必說了,大家都在使用。
但是RESTful如果功能過多,對應的接口也會隨之增多,比如后臺的查詢接口和前臺可能數(shù)據(jù)有區(qū)別需要額外寫一個,可能前臺查詢數(shù)據(jù)某一個要模糊查詢,某一個又要走主鍵查詢,有的又是多條件查詢。
那我就在想,要不試試一個查詢接口,聚合N個實現(xiàn)?不同數(shù)據(jù)去不同實現(xiàn)然后不同拼合。
那其實這時候,GraphQL這個玩意,其實就很符合我的預想,這玩意的接口查詢就是一個接口實現(xiàn)的,大概意思和大致想法都是一樣的。
但是GraphQL的開發(fā)和使用復雜度要高一些,而且我還是喜歡RESTful一些,這里不做過多介紹與對比,有興趣可以前往瀏覽器搜索一些,了解了解。
預想
那該怎么去實現(xiàn)呢?我的項目使用的是MyBatisPlus作為ORM框架,每一個實體都是去映射數(shù)據(jù)庫表的,我要想這一個功能方便通用,那我肯定要去進行部分封裝的。
首先考慮一下目前項目理想狀態(tài):
實體映射數(shù)據(jù)庫 數(shù)據(jù)庫字段規(guī)范的采用蛇形命名,無一例外 實體類采用駝峰命名映射,無一例外
這種情況下,我只需要通過反射,將一個傳過來的實體類的字段從駝峰轉(zhuǎn)換為蛇形命名,作為查詢條件的Key,也就是數(shù)據(jù)庫字段名。
然后獲取對應的值,作為條件拼接,然后將查詢條件對象丟到MyBatisPlus的service里面就可以了。
那么...開干!
查詢條件拼接
我們MP是使用QueryWrApper來構(gòu)建條件查詢對象的,總共有四種情況:
基本查詢條件:queryWrapper.eq() 模糊查詢條件:queryWrapper.like() 排序查詢條件:queryWrapper.orderByXXX()
至于主鍵查詢,我預想是創(chuàng)建一個注解作為標識,如果在邏輯處理時候發(fā)現(xiàn)主鍵標識注解的字段值不為空,我就直接拋棄所有其他條件,直接走主鍵查詢,ById。
但是因為時間原因,我就沒去具體實現(xiàn)了。
獲取對象字段與值
- 先通過反射獲取對象所有屬性并遍歷。
- 如果屬性值不為null就拼接。
- 使用Hutool中的StrUtil.toUnderlineCase將屬性名稱轉(zhuǎn)換蛇形。
拼接條件
代碼如下:
JAVA復制代碼 /**
* 聚合查詢對象拼接
*
* @param queries 查詢對象
* @param obj 聚合查詢屬性對象
* @return 查詢對象
*/
public static <Q> QueryWrapper<Q> splicingQueries(QueryWrapper<Q> queries, Object obj) {
Field[] declaredFields = obj.getClass().getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
String underlineCase = StrUtil.toUnderlineCase(field.getName());
try {
if (field.get(obj) != null) {
queries.eq(underlineCase, field.get(obj));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return queries;
}
大概代碼就是這樣的,然后我給了個泛型,為了約束查詢對象的類型。
那有人就說了:“那這樣,模糊查詢怎么辦?排序怎么辦?分頁怎么辦?”
哎哎哎,別急嘛,且聽我娓娓道來。
拼接模糊
同理,去實現(xiàn)這個模糊查詢的拼接方法封裝。
java復制代碼 /**
* 模糊查詢對象拼接
*
* @param queries 查詢對象
* @param obj 模糊查詢屬性對象
* @return 查詢對象
*/
public static <Q> QueryWrapper<Q> splicingFuzzyQueries(QueryWrapper<Q> queries, Object obj) {
Field[] declaredFields = obj.getClass().getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
String underlineCase = StrUtil.toUnderlineCase(field.getName());
try {
if (field.get(obj) != null) {
queries.like(underlineCase, field.get(obj));
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return queries;
}
拼接排序
java復制代碼 /**
* 排序
*
* @param wrapper 查詢對象
* @param sortField 排序字段
* @param sortType 排序類型
*/
private static <Q> void applySort(QueryWrapper<Q> wrapper, String sortField, int sortType) {
String field = StrUtil.toUnderlineCase(sortField);
if (sortType == 1) {
wrapper.orderByDesc(field);
} else {
wrapper.orderByAsc(field);
}
}
這里其實可以優(yōu)化sortType為枚舉,不過...嘿嘿,我比較懶,算了算了吧。
分頁實現(xiàn)
分頁先留在后面了,客官先往下看。
邏輯處理
到目前,功能的方法封裝好了,整理一下業(yè)務的邏輯。
在排除主鍵(沒時間寫啦)查詢的情況下,邏輯總結(jié)如下:
如果存在絕對查詢條件情況,如:ID查詢、手機號查詢、郵箱查詢,直接性查詢,就不拼接模糊查詢了。
然后,基本查詢條件,可以與絕對條件查詢互補,也可以與模糊查詢條件互補。
對于模糊查詢,如果沒有絕對查詢條件的情況下,才會去拼接,模糊可與基本條件互補。
對于排序條件,只要數(shù)據(jù)存在就需要拼接,并且如果排序方式為null,默認升序。
對于分頁條件,我設(shè)置的是必傳項,并且沒去設(shè)置默認值(懶...)。
那將這個邏輯串聯(lián)起來,就可以實現(xiàn)一個通用方法。
但是!!!
在實現(xiàn)這個方法之前,我如何區(qū)分數(shù)據(jù)是要模糊還是基本條件或者又是絕對查詢條件?
所以,我們需要先封裝一個實體類,這個實體我們可能每一個對象都有自己不一樣的屬性,所以我們不能寫死,直接泛化即可。
實體封裝
先看我的注釋,截個圖:
再貼所有的代碼:
java復制代碼/*
* Copyright (c) 2023. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
* © JanYork 2023年6月2日 23點37分
*/
/**
* <p>
* 泛型說明:
* <ul>
* <li>T:直接性查詢條件對象</li>
* <li>C:基本查詢條件對象</li>
* <li>R:模糊查詢條件對象</li>
* <li>泛型對象可以為空,為空時不進行查詢</li>
* <li>泛型對象必須是一個Bean</li>
* <li>泛型對象的屬性<b>必須是基本數(shù)據(jù)類型</b></li>
* </ul>
* </p>
*
* @author JanYork
* @version 1.0.0
* @date 2023/06/02
* @description 聚合查詢對象
* @since 1.0.0
*/
@Data
@ApiModel(value = "聚合查詢對象")
public class AggregateQueries<T, C, R> {
/**
* 直接性查詢條件對象(T是一個Bean)
* <p>
* 直接性查詢對象如果存在,<b>模塊查詢條件直接失效</b>,場景如:<br/> <b>ID直接查詢</b>、<b>手機號直接查詢</b>
* </p>
*/
@ApiModelProperty(value = "直接性查詢條件對象")
private T queries;
/**
* 分頁信息對象
* <p>
* 分頁對象包含分頁信息,<b>分頁信息必須存在</b>,場景如:<br/> <b>分頁查詢</b>
* </p>
*/
@ApiModelProperty(value = "分頁信息對象")
private PaginationDTO pagination;
/**
* 基本查詢條件對象(C是一個Bean)
* <p>
* 基本查詢對象與直接性查詢可以同時存在,<b>基本查詢條件對象的查詢條件會與直接性查詢條件對象的查詢條件進行組合</b>,場景如:<br/>
* <b>直接性查詢ID為10001的用戶</b>,<b>基本性查詢狀態(tài)為true的用戶</b>,結(jié)合后的查詢條件為:<br/>
* <b>查詢ID為10001且狀態(tài)為true的用戶</b>
* </p>
*/
@ApiModelProperty(value = "基本查詢條件對象")
private C condition;
/**
* 模糊查詢條件對象(R是一個Bean)
* <p>
* 模糊查詢與直接性條件查詢互斥,與基本查詢條件對象互補,<b>模糊查詢條件對象的查詢條件會與基本查詢條件對象的查詢條件進行組合</b>,場景如:<br/>
* <b>基本性查詢狀態(tài)為true的用戶</b>,<b>模糊性查詢用戶名為張三的用戶</b>,結(jié)合后的查詢條件為:<br/>
* <b>查詢狀態(tài)為true且用戶名包含張三的用戶</b>
* </p>
*/
@ApiModelProperty(value = "模糊查詢條件對象")
private R fuzzyQueries;
/**
* 排序字段
* <p>
* 排序字段可以為空,為空時不進行排序
* </p>
*/
@ApiModelProperty(value = "排序字段")
private String sortField;
/**
* 排序方式
* <p>
* 排序方式可以為空,為空時默認為升序,0:升序,1:降序
* </p>
*/
@ApiModelProperty(value = "排序方式")
private Integer sortType;
/**
* 是否存在直接性查詢條件對象
*
* @return boolean true:存在,false:不存在
*/
public boolean hasQueries() {
return queries != null;
}
/**
* 是否存在分頁信息對象
*
* @return boolean true:存在,false:不存在
*/
public boolean hasPagination() {
return pagination != null;
}
/**
* 是否存在基本查詢條件對象
*
* @return boolean true:存在,false:不存在
*/
public boolean hasCondition() {
return condition != null;
}
/**
* 是否存在模糊查詢條件對象
*
* @return boolean true:存在,false:不存在
*/
public boolean hasFuzzyQueries() {
return fuzzyQueries != null;
}
/**
* 是否存在排序字段
*
* @return boolean true:存在,false:不存在
*/
public boolean hasSortField() {
return sortField != null;
}
/**
* 是否存在排序方式
*
* @return boolean true:存在,false:不存在
*/
public boolean hasSortType() {
return sortType != null;
}
}
這里面有一個PaginationDTO,是一個分頁信息對象,我也貼出來:
java復制代碼/**
* @author JanYork
* @version 1.0.0
* @date 2023/06/02
* @description 分頁DTO
* @since 1.0.0
*/
@Data
@ApiModel(value = "分頁數(shù)據(jù)對象")
public class PaginationDTO {
/**
* 頁碼
*/
@ApiModelProperty(value = "頁碼")
private Integer page;
/**
* 每頁大小
*/
@ApiModelProperty(value = "每頁大小")
private Integer size;
}
那這樣我們就封裝成實體類了。
三個泛型?
三個泛型對象其實我在注釋中已經(jīng)說了:
泛型說明:
T:直接性查詢條件對象 C:基本查詢條件對象 R:模糊查詢條件對象 泛型對象可以為空,為空時不進行查詢(不拼接) 泛型對象必須是一個Bean(實體),并且實體必須映射數(shù)據(jù)表,字段必須規(guī)范命名 泛型對象的屬性必須是基本數(shù)據(jù)類型
然后對于這三個泛型,我們要創(chuàng)建不同的實體(麻煩歸麻煩,規(guī)范還是要),所以,接下來看看我怎么用的。
我這里一個地址聚合查詢和一個商品聚合查詢。
構(gòu)建實體?
Condition結(jié)尾的是基本查詢條件對象,如:
java復制代碼/**
* @author JanYork
* @version 1.0.0
* @date 2023/06/02
* @description 地址基本條件查詢對象
* @since 1.0.0
*/
@Data
@ApiModel("(地址)基本條件查詢對象")
public class AddressCondition {
/**
* 省
*/
@ApiModelProperty(value = "省")
private String province;
/**
* 城市
*/
@ApiModelProperty(value = "城市")
private String city;
/**
* 縣/區(qū)
*/
@ApiModelProperty(value = "縣/區(qū)")
private String district;
}
這里面的條件,如果存在,那就必定會拼接,與絕對查詢條件或者模糊查詢條件互補。
FuzzyQueries結(jié)尾的是模糊查詢條件,如:
java復制代碼/**
* @author JanYork
* @version 1.0.0
* @date 2023/06/02
* @description 地址模糊查詢對象
* @since 1.0.0
*/
@Data
@ApiModel("(地址)模糊查詢對象")
public class AddressFuzzyQueries {
/**
* 用戶手機號
*/
@ApiModelProperty(value = "用戶手機號(可模糊)")
private String phone;
/**
* 用戶姓名
*/
@ApiModelProperty(value = "用戶姓名(可模糊)")
private String name;
/**
* 詳細地址
*/
@ApiModelProperty(value = "詳細地址(可模糊)")
private String address;
}
這個實體里面的條件與絕對查詢條件互斥,且優(yōu)先級低于絕對查詢條件!
Queries結(jié)尾的是絕對查詢條件,如:
java復制代碼/**
* @author JanYork
* @version 1.0.0
* @date 2023/06/02
* @description 地址直接性查詢對象
* @since 1.0.0
*/
@Data
@ApiModel("(地址)直接性查詢對象")
public class AddressQueries {
/**
* 用戶ID
*/
@ApiModelProperty(value = "用戶ID")
private Long userId;
/**
* 用戶手機號
*/
@ApiModelProperty(value = "用戶手機號")
private String phone;
}
這個實體條件優(yōu)先級最高,如果存在必定拼接。
然后三個實體都有了,我們還需要將上面邏輯處理段落總結(jié)的邏輯串聯(lián)起來,實現(xiàn)一個通用方法。
通用方法實現(xiàn)
我們開始已經(jīng)封裝了模糊、條件、排序的拼接方法,所以我們可以直接調(diào)用封裝好的方法去實現(xiàn)拼接的邏輯處理。
直接丟代碼了:
java復制代碼 /**
* 聚合查詢對象拼接
*
* @param queries 查詢對象
* @param aggregate 聚合查詢對象
* @return {@link QueryWrapper}<{@link Q}>
*/
public static <Q, T, C, R> QueryWrapper<Q> splicingAggregateQueries(QueryWrapper<Q> queries, AggregateQueries<T, C, R> aggregate) {
if (aggregate.hasQueries()) {
splicingQueries(queries, aggregate.getQueries());
}
if (aggregate.hasCondition()) {
splicingQueries(queries, aggregate.getCondition());
}
if (aggregate.hasFuzzyQueries() && !aggregate.hasQueries()) {
splicingFuzzyQueries(queries, aggregate.getFuzzyQueries());
}
if (aggregate.hasSortField()) {
aggregate.setSortType(aggregate.hasSortType() ? aggregate.getSortType() : 0);
applySort(queries, aggregate.getSortField(), aggregate.getSortType());
}
return queries;
}
這個通用方法,主要就是實現(xiàn)通用性和邏輯貫穿處理,這里沒寫過多注釋,aggregate.hasXXXX方法是判斷是否存在條件實體對象或者字段值,邏輯還需要請各位親自捋一下了,畢竟也就幾個if。
使用聚合方法與分頁操作
先看代碼后講解:
java復制代碼 /**
* 聚合查詢
*
* @param aggregate 聚合查詢對象
* @return {@link ApiResponse}<{@link List}<{@link Address}>>
*/
@PostMapping("/get")
public ApiResponse<List<Address>> get(@RequestBody AggregateQueries<AddressQueries, AddressCondition, AddressFuzzyQueries> aggregate) {
if (!aggregate.hasPagination()) {
return ApiResponse.fAIl(null);
}
PaginationDTO pagination = aggregate.getPagination();
QueryWrapper<Address> wrapper = AggregateQueriesUtil.splicingAggregateQueries(new QueryWrapper<>(), aggregate);
Page<Address> page = new Page<>(pagination.getPage(), pagination.getSize());
return ApiResponse.ok(
addressService.page(page, wrapper).getRecords()
);
}
這里,接口接收的參數(shù)就是映射我們封裝的聚合條件對象:AggregateQueries<AddressQueries, AddressCondition, AddressFuzzyQueries> aggregate了。
這三個泛型就是我們對于不同數(shù)據(jù)庫實體的不同條件字段封裝的不同POJO。
分頁
先前說了,分頁是必須的,所以我們判斷一下,分頁對象不存在直接返回失敗。
java復制代碼if (!aggregate.hasPagination()) {
return ApiResponse.fail(null);
}
如果存在我們獲取分頁信息,利用MP的分頁插件,直接進行分頁查詢操作,這個插件就不多說了。
處理
這里我們直接利用我們封裝好的通用方法去獲取拼接條件后的QueryWrapper對象:
java復制代碼QueryWrapper<Address> wrapper = AggregateQueriesUtil.splicingAggregateQueries(new QueryWrapper<>(), aggregate);
因為是后臺管理端的數(shù)據(jù),我就懶得去Bean拷貝到VO對象了,直接就是實體返回。
效果演示
調(diào)試工具用什么好呢?上postman吧。
數(shù)據(jù)庫數(shù)據(jù)展示
1000 1658741489930473472 江西省 南昌市 南昌縣 江西省南昌市南昌縣萬壽宮 16688880818 小簡 28.68333 115.88333 0
1001 1658741489930473472 江西省 南市 南昌縣 江西省南昌市南昌縣東湖區(qū)ABCD6棟 16670080818 小簡 28.68333 115.88333 0
1002 1658741489930473472 江西省 昌市 南昌縣 江西省南昌市南昌縣CCC寫字樓 16676080818 小簡 28.68333 115.88333 1
測試JSON數(shù)據(jù):
json復制代碼{
"queries": {
"phone":"16688880818"
},
"pagination": {
"page": 1,
"size": 3
},
"condition":{
"city":"南市"
},
"fuzzyQueries": {
"phone": "166",
"address": "CCC寫字樓"
},
"sortField": "id",
"sortType": 1
}
絕對條件查詢
數(shù)據(jù):
json復制代碼{
"queries": {
"phone":"16688880818"
},
"pagination": {
"page": 1,
"size": 3
}
}
SQL日志:
SQL復制代碼SELECT id,user_id,province,city,district,address,phone,name,latitude,longitude,is_default FROM address WHERE (phone = ?) LIMIT ?
MP完整日志:
SQL復制代碼Creating a new SqlSession
SqlSession [org.Apache.ibatis.session.defaults.DefaultSqlSession@164276c] was not registered for synchronization because synchronization is not active
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@71237c20] will not be managed by Spring
==> Preparing: SELECT COUNT(*) AS total FROM address WHERE (phone = ?)
==> Parameters: 16688880818(String)
<== Columns: total
<== Row: 1
<== Total: 1
==> Preparing: SELECT id,user_id,province,city,district,address,phone,name,latitude,longitude,is_default FROM address WHERE (phone = ?) LIMIT ?
==> Parameters: 16688880818(String), 3(Long)
<== Columns: id, user_id, province, city, district, address, phone, name, latitude, longitude, is_default
<== Row: 1000, 1658741489930473472, 江西省, 南昌市, 南昌縣, 江西省南昌市南昌縣萬壽宮, 16688880818, 小簡, 28.68333, 115.88333, 0
<== Total: 1
回調(diào)數(shù)據(jù):
json復制代碼{
"code": 200,
"message": "success",
"data": [
{
"id": 1000,
"userId": 1658741489930473472,
"province": "江西省",
"city": "南昌市",
"district": "南昌縣",
"address": "江西省南昌市南昌縣萬壽宮",
"phone": "16688880818",
"name": "小簡",
"latitude": "28.68333",
"longitude": "115.88333",
"isDefault": false
}
]
}
絕對+基本
數(shù)據(jù):
json復制代碼{
"queries": {
"phone":"16688880818"
},
"pagination": {
"page": 1,
"size": 3
},
"condition":{
"city":"南昌市"
}
}
SQL日志:
SQL復制代碼SELECT id,user_id,province,city,district,address,phone,name,latitude,longitude,is_default FROM address WHERE (phone = ? AND city = ?) LIMIT ?
MP日志:
SQL復制代碼Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e00c6c9] was not registered for synchronization because synchronization is not active
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5e68f14e] will not be managed by Spring
==> Preparing: SELECT COUNT(*) AS total FROM address WHERE (phone = ? AND city = ?)
==> Parameters: 16688880818(String), 南昌市(String)
<== Columns: total
<== Row: 1
<== Total: 1
==> Preparing: SELECT id,user_id,province,city,district,address,phone,name,latitude,longitude,is_default FROM address WHERE (phone = ? AND city = ?) LIMIT ?
==> Parameters: 16688880818(String), 南昌市(String), 3(Long)
<== Columns: id, user_id, province, city, district, address, phone, name, latitude, longitude, is_default
<== Row: 1000, 1658741489930473472, 江西省, 南昌市, 南昌縣, 江西省南昌市南昌縣萬壽宮, 16688880818, 小簡, 28.68333, 115.88333, 0
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e00c6c9]
回調(diào)數(shù)據(jù):
json復制代碼{
"code": 200,
"message": "success",
"data": [
{
"id": 1000,
"userId": 1658741489930473472,
"province": "江西省",
"city": "南昌市",
"district": "南昌縣",
"address": "江西省南昌市南昌縣萬壽宮",
"phone": "16688880818",
"name": "小簡",
"latitude": "28.68333",
"longitude": "115.88333",
"isDefault": false
}
]
}
模糊
數(shù)據(jù):
json復制代碼{
"pagination": {
"page": 1,
"size": 3
},
"fuzzyQueries": {
"phone": "166"
// "address": "CCC寫字樓"
}
}
SQL日志:
sql復制代碼SELECT id,user_id,province,city,district,address,phone,name,latitude,longitude,is_default FROM address WHERE (phone LIKE ?) LIMIT ?
MP日志:
sql復制代碼Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3646a7c1] was not registered for synchronization because synchronization is not active
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3e66a291] will not be managed by Spring
==> Preparing: SELECT COUNT(*) AS total FROM address WHERE (phone LIKE ?)
==> Parameters: %166%(String)
<== Columns: total
<== Row: 3
<== Total: 1
==> Preparing: SELECT id,user_id,province,city,district,address,phone,name,latitude,longitude,is_default FROM address WHERE (phone LIKE ?) LIMIT ?
==> Parameters: %166%(String), 3(Long)
<== Columns: id, user_id, province, city, district, address, phone, name, latitude, longitude, is_default
<== Row: 1000, 1658741489930473472, 江西省, 南昌市, 南昌縣, 江西省南昌市南昌縣萬壽宮, 16688880818, 小簡, 28.68333, 115.88333, 0
<== Row: 1001, 1658741489930473472, 江西省, 南市, 南昌縣, 江西省南昌市南昌縣東湖區(qū)ABCD6棟, 16670080818, 小簡, 28.68333, 115.88333, 0
<== Row: 1002, 1658741489930473472, 江西省, 昌市, 南昌縣, 江西省南昌市南昌縣CCC寫字樓, 16676080818, 小簡, 28.68333, 115.88333, 1
<== Total: 3
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3646a7c1]
回調(diào)數(shù)據(jù):
json復制代碼{
"code": 200,
"message": "success",
"data": [
{
"id": 1000,
"userId": 1658741489930473472,
"province": "江西省",
"city": "南昌市",
"district": "南昌縣",
"address": "江西省南昌市南昌縣萬壽宮",
"phone": "16688880818",
"name": "小簡",
"latitude": "28.68333",
"longitude": "115.88333",
"isDefault": false
},
{
"id": 1001,
"userId": 1658741489930473472,
"province": "江西省",
"city": "南市",
"district": "南昌縣",
"address": "江西省南昌市南昌縣東湖區(qū)ABCD6棟",
"phone": "16670080818",
"name": "小簡",
"latitude": "28.68333",
"longitude": "115.88333",
"isDefault": false
},
{
"id": 1002,
"userId": 1658741489930473472,
"province": "江西省",
"city": "昌市",
"district": "南昌縣",
"address": "江西省南昌市南昌縣CCC寫字樓",
"phone": "16676080818",
"name": "小簡",
"latitude": "28.68333",
"longitude": "115.88333",
"isDefault": true
}
]
}
排序+模糊
數(shù)據(jù):
json復制代碼{
"pagination": {
"page": 1,
"size": 3
},
"fuzzyQueries": {
"phone": "166"
},
"sortField": "id",
"sortType": 1
}
SQL日志:
SQL復制代碼SELECT id,user_id,province,city,district,address,phone,name,latitude,longitude,is_default FROM address WHERE (phone LIKE ?) ORDER BY id DESC LIMIT ?
MP日志:
SQL復制代碼Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@26a0b246] was not registered for synchronization because synchronization is not active
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3deaaebe] will not be managed by Spring
==> Preparing: SELECT COUNT(*) AS total FROM address WHERE (phone LIKE ?)
==> Parameters: %166%(String)
<== Columns: total
<== Row: 3
<== Total: 1
==> Preparing: SELECT id,user_id,province,city,district,address,phone,name,latitude,longitude,is_default FROM address WHERE (phone LIKE ?) ORDER BY id DESC LIMIT ?
==> Parameters: %166%(String), 3(Long)
<== Columns: id, user_id, province, city, district, address, phone, name, latitude, longitude, is_default
<== Row: 1002, 1658741489930473472, 江西省, 昌市, 南昌縣, 江西省南昌市南昌縣CCC寫字樓, 16676080818, 小簡, 28.68333, 115.88333, 1
<== Row: 1001, 1658741489930473472, 江西省, 南市, 南昌縣, 江西省南昌市南昌縣東湖區(qū)ABCD6棟, 16670080818, 小簡, 28.68333, 115.88333, 0
<== Row: 1000, 1658741489930473472, 江西省, 南昌市, 南昌縣, 江西省南昌市南昌縣萬壽宮, 16688880818, 小簡, 28.68333, 115.88333, 0
<== Total: 3
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@26a0b246]
回調(diào)數(shù)據(jù):
json復制代碼{
"code": 200,
"message": "success",
"data": [
{
"id": 1002,
"userId": 1658741489930473472,
"province": "江西省",
"city": "昌市",
"district": "南昌縣",
"address": "江西省南昌市南昌縣CCC寫字樓",
"phone": "16676080818",
"name": "小簡",
"latitude": "28.68333",
"longitude": "115.88333",
"isDefault": true
},
{
"id": 1001,
"userId": 1658741489930473472,
"province": "江西省",
"city": "南市",
"district": "南昌縣",
"address": "江西省南昌市南昌縣東湖區(qū)ABCD6棟",
"phone": "16670080818",
"name": "小簡",
"latitude": "28.68333",
"longitude": "115.88333",
"isDefault": false
},
{
"id": 1000,
"userId": 1658741489930473472,
"province": "江西省",
"city": "南昌市",
"district": "南昌縣",
"address": "江西省南昌市南昌縣萬壽宮",
"phone": "16688880818",
"name": "小簡",
"latitude": "28.68333",
"longitude": "115.88333",
"isDefault": false
}
]
}
其他效果
都可以自由組合,單排序、單分頁、單模糊、排序+分頁+模糊、排序+基本......
都是可以自由組合的,方法太多就不都去嘗試了,大家也可以去試試,痛苦的封裝也會帶來一定的好處。
也可以在此基礎(chǔ)上,去創(chuàng)造一些新鮮的玩法和業(yè)務實現(xiàn),感謝大家閱讀,下期再見啦!
我是小簡,下期再會(不知道下期是多久了唉)。
尾述
為什么要去寫一些七里八里的東東呢?
因為,創(chuàng)造性才是本質(zhì),我不希望被CRUD的工作丟失我的興趣與活躍的思維。
我認為,賺錢的永遠是思維和大腦,而非單純的、一味的技術(shù)。