<strike id="rtjff"><noframes id="rtjff"><strike id="rtjff"></strike>
<progress id="rtjff"><address id="rtjff"></address></progress>
<th id="rtjff"></th>
<span id="rtjff"><video id="rtjff"></video></span><th id="rtjff"><video id="rtjff"><span id="rtjff"></span></video></th><progress id="rtjff"><noframes id="rtjff"><strike id="rtjff"><video id="rtjff"><strike id="rtjff"></strike></video></strike>
<th id="rtjff"></th><strike id="rtjff"><noframes id="rtjff"><strike id="rtjff"></strike>
<span id="rtjff"><video id="rtjff"></video></span>
<span id="rtjff"></span><span id="rtjff"><noframes id="rtjff">
<span id="rtjff"></span>
<th id="rtjff"><noframes id="rtjff"><th id="rtjff"></th>
<th id="rtjff"><noframes id="rtjff">
<span id="rtjff"><noframes id="rtjff">
  1. 首頁 > 汽車知識網 > 汽車知識

gtsearcher,winesearcher

對一個 Java 后端程序員來說,mybatis、hibernate、data-jdbc 等都是我們常用的 ORM 框架。它們有時候很好用,比如簡單的 CRUD,事務的支持都非常棒。但有時候用起來也非常繁瑣,比如接下來我們要聊到的一個常見的開發需求,而對這類需求,本文會給出一個比直接使用這些 ORM 開發效率至少會提高 100 倍的方法(絕無夸張)。

首先數據庫有兩張表

用戶表(user):(簡單起見,假設只有 4 個字段)

字段名

類型

含義

id

bitint

用戶 ID

name

varchar(45)

用戶名

age

int

年齡

role_id

int

角色 ID

角色表(role):(簡單起見,假設只有 2 個字段)

字段名

類型

含義

id

int

掃描 Scan;Scanning;Sweep 掃描器 Scanner;Searcher;scanistor 自動掃描 Auto Scan;SCAN;automatic scan

角色 ID

name

varchar(45)

角色名

接下來我們要實現一個用戶查詢的功能

這個查詢有點復雜,它的要求如下:

可按用戶名字段查詢,要求: 可精確匹配(等于某個值) 可全模糊匹配(包含給定的值) 可后模糊查詢(以...開頭) 可前模糊查詢(以.. 結尾) 可指定以上四種匹配是否可以忽略大小寫

可按年齡字段查詢,要求: 可精確匹配(等于某個年齡) 可大于匹配(大于某個值) 可小于匹配(小于某個值) 可區間匹配(某個區間范圍)

可按角色ID查詢,要求:精確匹配

可按用戶ID查詢,要求:同年齡字段

可指定只輸出哪些列(例如,只查詢 ID 與 用戶名 列)

支持分頁(每次查詢后,頁面都要顯示滿足條件的用戶總數)

極影或者直接用QVOD的下得了

查詢時可選擇按 ID、用戶名、年齡 等任意字段排序

后端接口該怎么寫呢?

試想一下,對于這種要求的查詢,后端接口里的代碼如果用 mybatis、hibernate、data-jdbc 直接來寫的話,100 行代碼 能實現嗎?

反正我是沒這個信心,算了,我還是直接坦白,面對這種需求后端如何 只用一行代碼搞定 吧(有興趣的同學可以 mybatis 等寫個試試,最后可以對比一下)

手把手:只一行代碼實現以上需求

首先,重點人物出場啦:Bean Searcher,它就是專門來對付這種列表檢索的,無論簡單的還是復雜的,統統一行代碼搞定!而且它還非常輕量,Jar 包體積僅不到 100KB,無第三方依賴。

假設我們項目使用的框架是 Spring Boot(當然 Bean Searcher 對框架沒有要求,winesearcher官方,但在 Spring Boot 中使用更加方便),

添加依賴

Maven :

com.ejlchinabean-searcher-boot-starter3.0.1

Gradle :

implementation &39;

然后寫個實體類來承載查詢的結果

@SearchBean(tables=&34;,joinCond=&34;,autoMapTo=&34;) public class User {private Long id; // 用戶ID(u.id)private String name; // 用戶名(u.name)private int age; // 年齡(u.age)private int roleId; // 角色ID(u.role_id)@DbField(&34;) // 指明這個屬性來自 role 表的 name 字段private int role; // 角色名(r.name)// Getter and Setter ...}

接著就可以寫用戶查詢接口了

接口路徑就叫 /user/index 吧:

@RestController@RequestMapping(&34;)public class UserController {@Autowiredprivate MapSearcher mapSearcher;// 注入檢索器(由 bean-searcher-boot-starter 提供)@GetMapping(&34;)public SearchResult> index(HttpServletRequest request) { // 這里咱們只寫一行代碼return mapSearcher.search(User.class,MapUtils.flat(request.getParameterMap()));}}

上述代碼中的 MapUtils 是 Bean Searcher 提供的一個工具類,MapUtils.flat(request.getParameterMap()) 只是為了把前端傳來的請求參數統一收集起來,然后剩下的,就全部交給 MapSearcher 檢索器了。

gtsearcher

這樣就完了?那我們來測一下這個接口,看看效果吧

(1)無參請求

GET /user/index

返回結果:

{&34;: [ // 用戶列表,默認返回第 0 頁,默認分頁大小為 15 (可配置){ &34;: 1,&34;: &34;,&34;: 25,&34;: 1,&34;: &34; }, { &34;: 2,&34;: &34;,&34;: 26,&34;: 1,&34;: &34; }, ...], &34;: 100 // 用戶總數}

GET /user/index? page=2 & size=10

返回結果:結構同 (1)(只是每頁 10 條,返回第 2 頁)

參數名 size 和 page 可自定義, page 默認從 0 開始,同樣可自定義,并且可與其它參數組合使用

GET /user/index? sort=age & order=desc

返回結果:結構同 (1)(只是 dataList 數據列表以 age 字段降序輸出)

gamesearcher下載 http://www.tjstart.com/down/software/2007-05-24/20.html 你是不是因為在不同的樓層之間不能一起玩而去上HF或者VS,那么用這個吧 解壓后運行GameSearcher.exe,點連接,輸入主機IP,點連接,搜索后。

參數名 sort 和 order 可自定義,可與其它參數組合使用

GET /user/index? onlySelect=id,name,role

GET /user/index? selectExclude=age,roleId

返回結果:( 列表只含 id,name 與 role 三個字段)

{&34;: [ // 用戶列表,默認返回第 0 頁(只包含 id,name,role 字段){ &34;: 1,&34;: &34;,&34;: &34; }, { &34;: 2,&34;: &34;,&34;: &34; }, ...], &34;: 100 // 用戶總數}

參數名 onlySelect 和 selectExclude 可自定義,可與其它參數組合使用

GET /user/index? age=20

GET /user/index? age=20 & age-op=eq

返回結果:結構同 (1)(但只返回 age = 20 的數據)

參數 age-op = eq 表示 age 的 字段運算符 是 eq(Equal 的縮寫),表示參數 age 與參數值 20 之間的關系是 Equal,由于 Equal 是一個默認的關系,所以 age-op = eq 也可以省略

參數名 age-op 的后綴 -op 可自定義,且可與其它字段參數 和 上文所列的參數(分頁、排序、指定字段)組合使用,下文所列的字段參數也是一樣,不再復述。

GET /user/index? age=20 & age-op=ne

返回結果:結構同 (1)(但只返回 age != 20 的數據,ne 是 NotEqual 的縮寫)

GET /user/index? age=20 & age-op=ge

返回結果:結構同 (1)(但只返回 age >= 20 的數據,ge 是 GreateEqual 的縮寫)

GET /user/index? age=20 & age-op=le

返回結果:結構同 (1)(但只返回 age <= 20 的數據,le 是 LessEqual 的縮寫)

GET /user/index? age=20 & age-op=gt

返回結果:結構同 (1)(但只返回 age > 20 的數據,gt 是 GreateThan 的縮寫)

GET /user/index? age=20 & age-op=lt

返回結果:結構同 (1)(但只返回 age < 20 的數據,lt 是 LessThan 的縮寫)

gtsearcher

GET /user/index? age-0=20 & age-1=30 & age-op=bt

返回結果:結構同 (1)(但只返回 20 <= age <= 30 的數據,bt 是 Between 的縮寫)

參數 age-0 = 20 表示 age 的第 0 個參數值是 20。上述提到的 age = 20 實際上是 age-0 = 20 的簡寫形式。另:參數名 age-0 與 age-1 中的連字符 - 可自定義。

GET /user/index? age-0=20 & age-1=30 & age-2=40 & age-op=mv

返回結果:結構同 (1)(但只返回 age in (20,30,40) 的數據,mv 是 MultiValue 的縮寫,表示有多個值的意思)

GET /user/index? name=Jack & name-op=in

gtsearcher

GET /user/index? name=Jack & name-op=sw

返回結果:結構同 (1)(但只返回 name 以 Jack 開頭的數據,sw 是 StartWith 的縮寫)

GET /user/index? name=Jack & name-op=ew

返回結果:結構同 (1)(但只返回 name 以 Jack 結尾的數據,sw 是 EndWith 的縮寫)

GET /user/index? name-op=ey

返回結果:結構同 (1)(但只返回 name 為空 或為 null 的數據,ey 是 Empty 的縮寫)

GET /user/index? name-op=ny

返回結果:結構同 (1)(但只返回 name 非空 的數據,ny 是 NotEmpty 的縮寫)

GET /user/index? name=Jack & name-ic=true

返回結果:結構同 (1)(但只返回 name 等于 Jack (忽略大小寫) 的數據,ic 是 IgnoreCase 的縮寫)

當然,以上各種條件都可以組合,例如

查詢 name 以 Jack (忽略大小寫) 開頭,且 roleId = 1,結果以 id 字段排序,每頁加載 10 條,查詢第 2 頁:

GET /user/index? name=Jack & name-op=sw & name-ic=true & roleId=1 & sort=id & size=10 & page=2

返回結果:結構同 (1)

OK,效果看完了,/user/index 接口里我們確實只寫了一行代碼,它便可以支持這么多種的檢索方式,有沒有覺得現在 你寫的一行代碼 就可以 干過別人的一百行 呢?

Bean Searcher

本例中,我們只使用了 Bean Searcher 提供的 MapSearcher 檢索器的一個 search 方法,其實,它有很多 search 方法。

檢索方法

searchCount(Class beanClass,Map params) 查詢指定條件下的數據 總條數

searchSum(Class beanClass,Map params,String field) 查詢指定條件下的 某字段 的 統計值

searchSum(Class beanClass,Map params,String[] fields) 查詢指定條件下的 多字段 的 統計值

search(Class beanClass,Map params) 分頁 查詢指定條件下數據 列表 與 總條數

search(Class beanClass,Map params,String[] summaryFields) 同上 + 多字段 統計

searchFirst(Class beanClass,Map params) 查詢指定條件下的 第一條 數據

searchList(Class beanClass,Map params) 分頁 查詢指定條件下數據 列表

searchAll(Class beanClass,Map params) 查詢指定條件下 所有 數據 列表

MapSearcher 與 BeanSearcher

另外,Bean Searcher 除了提供了 MapSearcher 檢索器外,還提供了 BeanSearcher 檢索器,它同樣擁有 MapSearcher 擁有的方法,只是它返回的單條數據不是 Map,而是一個 泛型 對象。

參數構建工具

另外,如果你是在 Service 里使用 Bean Searcher,那么直接使用 Map 類型的參數可能不太優雅,為此, Bean Searcher 特意提供了一個參數構建工具。

例如,同樣查詢 name 以 Jack (忽略大小寫) 開頭,且 roleId = 1,結果以 id 字段排序,每頁加載 10 條,加載第 2 頁,使用參數構建器,代碼可以這么寫:

Map params = MapUtils.builder().field(User::getName,&34;).op(Operator.StartWith).ic().field(User::getRoleId,1).orderBy(User::getId,&34;).page(2,10).build()List users = beanSearcher.searchList(User.class,params);

UltraEdit: 搜索---在文件中查找---查找 輸入關鍵字, 文件 *.txt,目錄,高級---搜索子目錄 ---查找 搜索中文不行的 FileLocator Pro Portable total commander 文件名 +文件內容 也可以 Search And Replace是。

這里使用的是 BeanSearcher 檢索器,以及它的 searchList(Class beanClass,Map params) 方法。

運算符約束

上文我們看到,Bean Searcher 對實體類中的每一個字段,都直接支持了很多的檢索方式。

但某同學:哎呀!檢索方式太多了,我根本不需要這么多,我的數據量幾十億,用戶名字段的前模糊查詢方式利用不到索引,萬一把我的數據庫查崩了怎么辦呀?

好辦,Bean Searcher 支持運算符的約束,實體類的用戶名 name 字段只需要注解一下即可:

@SearchBean(tables=&34;,joinCond=&34;,autoMapTo=&34;) public class User {@DbField(onlyOn = {Operator.Equal,Operator.StartWith})private String name;// 為減少篇幅,省略其它字段...}

如上,通過 @DbField 注解的 onlyOn 屬性,指定這個用戶名 name 只能適用與 精確匹配 和 后模糊查詢,其它檢索方式它將直接忽略。

上面的代碼是限制了 name 只能有兩種檢索方式,如果再嚴格一點,只允許 精確匹配,那其實有兩種寫法。

(1)還是使用運算符約束:

@SearchBean(tables=&34;,joinCond=&34;,autoMapTo=&34;) public class User {@DbField(onlyOn = Operator.Equal)private String name;// 為減少篇幅,省略其它字段...}

(2)在 Controller 的接口方法里把運算符參數覆蓋:

@GetMapping(&34;)public SearchResult> index(HttpServletRequest request) {Map params = MapUtils.flatBuilder(request.getParameterMap()).field(User::getName).op(Operator.Equal) // 把 name 字段的運算符直接覆蓋為 Equal.build()return mapSearcher.search(User.class,params);}

條件約束

該同學又:哎呀!我的數據量還是很大,age 字段沒有索引,我不想讓它參與 where 條件,不然很可能就出現慢 SQL 啊!

不急,Bean Searcher 還支持條件的約束,讓這個字段直接不能作為條件:

@SearchBean(tables=&34;,joinCond=&34;,autoMapTo=&34;) public class User {@DbField(conditional = false)private int age;// 為減少篇幅,省略其它字段...}

如上,通過 @DbField 注解的 conditional 屬性, 就直接不允許 age 字段參與條件了,無論前端怎么傳參,Bean Searcher 都不搭理。

參數過濾器

該同學仍:哎呀!哎呀 ...

別怕! Bean Searcher 還支持配置全局參數過濾器,可自定義任何參數過濾規則,在 Spring Boot 項目中,只需要配置一個 Bean:

@Beanpublic ParamFilter myParamFilter() {return new ParamFilter() {@Overridepublic Map doFilter(BeanMeta beanMeta,Map paraMap) {// beanMeta 是正在檢索的實體類的元信息,paraMap 是當前的檢索參數// TODO: 這里可以寫一些自定義的參數過濾規則return paraMap;// 返回過濾后的檢索參數}};}

某同學問

searcher.ejlchina.com/guide/lates…

參數個數的多少,其實是和需求的復雜程度相關的。如果需求很簡單,那么很多參數沒必要讓前端傳,后端直接塞進去就好。比如:name 只要求后模糊匹配,age 只要求區間匹配,則可以:

@GetMapping(&34;)public SearchResult> index(HttpServletRequest request) {Map params = MapUtils.flatBuilder(request.getParameterMap()).field(User::getName).op(Operator.StartWith).field(User::getAge).op(Operator.Between).build()return mapSearcher.search(User.class,params);}

這樣前端就不用傳 name-op 與 age-op 這兩個參數了。

其實還有一種更簡單的方法,那就是 運算符約束(當約束存在時,運算符默認就是 onlyOn 屬性中指定的第一個值,前端可以省略不傳):

@SearchBean(tables=&34;,joinCond=&34;,autoMapTo=&34;) public class User {@DbField(onlyOn = Operator.StartWith)private String name;@DbField(onlyOn = Operator.Between)private String age;// 為減少篇幅,省略其它字段...}

入參是 request,我 swagger 文檔不好渲染了呀

其實,Bean Searcher 的檢索器只是需要一個 Map 類型的參數,至于這個參數是怎么來的,和 Bean Searcher 并沒有直接關系。前文之所以從 request 里取,只是因為這樣代碼看起來簡潔,如果你喜歡

@GetMapping(&34;)public SearchResult> index(Integer page,Integer size,String sort,String order,String name,Integer roleId, @RequestParam(value = &34;,required = false) String name_op, @RequestParam(value = &34;,required = false) Boolean name_ic, @RequestParam(value = &34;,required = false) Integer age_0, @RequestParam(value = &34;,required = false) Integer age_1, @RequestParam(value = &34;,required = false) String age_op) {Map params = MapUtils.builder().field(Employee::getName,name).op(name_op).ic(name_ic).field(Employee::getAge,age_0,age_1).op(age_op).field(Employee::getRoleId,roleId).orderBy(sort,order).page(page,size).build();return mapSearcher.search(User.class,params);}

結語

本文介紹了 Bean Searcher 在復雜列表檢索領域的超強能力。它之所以可以極大提高這類需求的研發效率,根本上歸功于它 獨創 的 動態字段運算符 與 多表映射機制,這是傳統 ORM 框架所沒有的。但由于篇幅所限,它的特性本文不能盡述,比如它還:

支持 聚合查詢

支持 Select|Where|From子查詢

支持 實體類嵌入參數

支持 字段轉換器

支持 Sql 攔截器

支持 多數據源

支持 自定義注解

等等

要了解更多,先來點個 Star 吧 : Github 、Gitee。

Bean Searcher 是我在工作中總結封裝出來的一個小工具,公司內部使用了 4 年,經歷大小項目三四十個,只是最近才著手完善文檔分享給大家,如果你喜歡,一定去點個 Star 哦 ^_^。

再奉上 Bean Searcher 的詳細文檔:searcher.ejlchina.com

最后,再來個 Demo 地址:

Spring Boot 框架中使用 demo

github.com/ejlchina/be…

gitee.com/ejlchina-zh…

Grails 框架中使用 demo

github.com/ejlchina/be…

gitee.com/ejlchina-zh…

代碼,也喜歡純手工的,因為這樣才能造出真正的藝術品。

版權聲明:本站文章均來源于網絡,如有侵權請聯系刪除!

聯系我們

在線咨詢:點擊這里給我發消息

QQ:

工作日:9:30-18:30,節假日休息

<strike id="rtjff"><noframes id="rtjff"><strike id="rtjff"></strike>
<progress id="rtjff"><address id="rtjff"></address></progress>
<th id="rtjff"></th>
<span id="rtjff"><video id="rtjff"></video></span><th id="rtjff"><video id="rtjff"><span id="rtjff"></span></video></th><progress id="rtjff"><noframes id="rtjff"><strike id="rtjff"><video id="rtjff"><strike id="rtjff"></strike></video></strike>
<th id="rtjff"></th><strike id="rtjff"><noframes id="rtjff"><strike id="rtjff"></strike>
<span id="rtjff"><video id="rtjff"></video></span>
<span id="rtjff"></span><span id="rtjff"><noframes id="rtjff">
<span id="rtjff"></span>
<th id="rtjff"><noframes id="rtjff"><th id="rtjff"></th>
<th id="rtjff"><noframes id="rtjff">
<span id="rtjff"><noframes id="rtjff">
一二三四视频社区在线7