DoytoQuery中的查詢映射方案詳解

引言
DoytoQuery作為一個(gè)ORM框架,在研發(fā)過(guò)程中積累了很多全新的思路和解決方案,其中一個(gè)核心方案就是將查詢對(duì)象的字段映射為SQL語(yǔ)句中的WHERE條件進(jìn)行動(dòng)態(tài)查詢,目前支持四種字段映射方式。
讓我們看看如何為以下UserEntity編寫(xiě)查詢對(duì)象:
@Getter
@Setter
@Entity
public class UserEntity extends AbstractPersistable<Integer> {
private String username;
private String email;
private String mobile;
private String password;
private String nickname;
private Boolean valid;
}
四種字段映射方式詳解
1. 后綴映射
先定義一個(gè)類(lèi)UserQuery, 對(duì)于一些常見(jiàn)的查詢條件,比如id = ?, username = ? and valid = ?等,我們只需要在UserQuery類(lèi)中定義如下字段即可。
@Getter
@Setter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class UserQuery extends PageQuery {
private Integer id;
private String username;
private Boolean valid;
}
像其他一些常用的比較符號(hào). [NOT] LIKE, >, <, !=, >=, <=, IS [NOT] NULL, [NOT] IN, 我們需要在列名后加一些特定的后綴作為字段名稱(chēng)來(lái)標(biāo)識(shí)對(duì)應(yīng)的條件符號(hào)。比如,將idIn映射為id IN (?,?,?), 將idGt映射為id > ?, 將usernameLike映射為username LIKE ?, 還需要定義好對(duì)應(yīng)的類(lèi)型。
public class UserQuery extends PageQuery {
private Integer id;
private String username;
private Boolean valid;
private List<Integer> idIn;
private Integer idGt;
private String usernameLike;
}
只有值不為NULL的字段才會(huì)被映射,并且多個(gè)條件由AND連接。
UserQuery userQuery = UserQuery.builder().usernameLike("test").valid(true).build();
這個(gè)userQuery會(huì)被映射為如下查詢語(yǔ)句以及對(duì)應(yīng)的參數(shù)。
SELECT id, username, email, mobile, password, nickname, valid FROM user WHERE username LIKE ? and valid = ? -- With parameters: ["%test%", true]
所有支持的后綴詳見(jiàn)附錄I。
2. OR映射
OR語(yǔ)句也是SQL里一種常用的查詢方式,DoytoQuery支持的方式有兩種。
2.1 將含Or的字段映射為OR語(yǔ)句
像usernameOrEmailOrMobile這樣多個(gè)字段由Or連接的字段會(huì)被映射為username = ? OR email = ? OR mobile = ?。
2.2 將實(shí)現(xiàn)了Or的對(duì)象映射為OR語(yǔ)句
public interface Or {
}
public class AccountOr implements Or {
private String username;
private String email;
private String mobile;
}
public class UserQuery {
private AccountOr account;
}
遍歷AccountOr中的字段可以得到[username, email, mobile],然后使用關(guān)鍵字OR相連而得username = ? OR email = ? OR mobile = ?.
3. 嵌套查詢映射
嵌套查詢是SQL的另一個(gè)常用特性。在管理菜單樹(shù)的menu表的常見(jiàn)定義中,我們通常定義一個(gè)外鍵parentId來(lái)引向父菜單實(shí)體的id。
要查詢擁有子菜單的父菜單,我們可以執(zhí)行以下SQL:
SELECT * FROM menu WHERE id IN (SELECT parentId FROM menu WHERE ...)
要查詢某些菜單的子菜單,我們可以執(zhí)行以下SQL:
SELECT * FROM menu WHERE parentId IN (SELECT id FROM menu WHERE ...)
這條語(yǔ)句用于查詢指定用戶擁有的菜單:
SELECT * FROM menu WHERE id IN (
SELECT menu_id FROM a_perm_and_menu WHERE perm_id IN (
SELECT perm_id FROM a_role_and_perm WHERE role_id IN (
SELECT role_id FROM a_user_and_role WHERE user_id IN (
SELECT id FROM t_user WHERE id = ?
))))
這些都是ERM模型里常見(jiàn)的一對(duì)多/多對(duì)一/多對(duì)多關(guān)系. DoytoQuery定義了一個(gè)新的@DomainPath注解來(lái)映射這種嵌套查詢。
@Target(FIELD)
@Retention(RUNTIME)
public @interface DomainPath {
// To describe how to route from the host domain to the target domain.
String[] value();
String localField() default "id";
String foreignField() default "id";
}
這里有一個(gè)@DomainPath注解用法介紹。
public class MenuQuery extends PageQuery {
// 多對(duì)一: 根據(jù)父菜單的條件查詢他們的子菜單
@DomainPath(localField = "parentId", foreignField = "id", value = "menu")
MenuQuery parent; // parentId IN (SELECT id FROM menu WHERE ... )
// 一對(duì)多: 根據(jù)子菜單的條件查詢父菜單
@DomainPath(localField = "id", foreignField = "parentId", value = "menu")
MenuQuery children; // id IN (SELECT parentId FROM menu WHERE ... )
// 多對(duì)多: 查詢滿足條件的用戶被授予的菜單
@DomainPath({"menu", "~", "perm", "~", "role", "~", "user"})
UserQuery user;
}
4. 直接映射
當(dāng)上述方法都不使用時(shí),還有最后一種將字段映射到條件的方法,就是使用注解@QueryField定義查詢條件后直接映射。這是DoytoQuery創(chuàng)建時(shí)的第一種映射方式,但是是最后一種推薦的方式,用法如下:
public class MenuQuery extends PageQuery {
@QueryField(and = "id = (SELECT parent_id FROM menu WHERE id = ?)")
private Integer childId;
}
嵌套查詢的這種映射方式在@DomainPath發(fā)明后就已棄用。
總結(jié)
在本文中,我們介紹了DoytoQuery中的四種字段映射方式。前三種方式不需要編寫(xiě)任何SQL語(yǔ)句,并且可以涵蓋到關(guān)系數(shù)據(jù)庫(kù)開(kāi)發(fā)中大部分涉及單表查詢的場(chǎng)景。
附錄I: 后綴支持列表
| 后綴名稱(chēng) | 比較符號(hào) | 占位符 | 類(lèi)型 | 值處理 |
|---|---|---|---|---|
| (No matching suffix) | = | ? | ||
| Not | != | ? | ||
| NotLike | NOT LIKE | ? | String | %value% |
| Like | LIKE | ? | String | %value% |
| Start | LIKE | ? | String | %value |
| End | LIKE | ? | String | value% |
| NotIn | NOT IN | 非空集合: (?[, ?]); | Collection | |
| In | IN | 非空集合(?[, ?]); | Collection | |
| NotNull | IS NOT NULL | - | boolean | |
| Null | IS NULL | - | boolean | |
| Gt | > | ? | ||
| Ge | >= | ? | ||
| Lt | < | ? | ||
| Le | <= | ? | ||
| Eq | = | ? |
以上就是DoytoQuery中的查詢映射方案詳解的詳細(xì)內(nèi)容,更多關(guān)于DoytoQuery查詢映射的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java多線程的調(diào)度_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
有多個(gè)線程,如何控制它們執(zhí)行的先后次序呢?下文給大家分享四種方法及java多線程調(diào)度的實(shí)例代碼,需要的朋友參考下吧2017-05-05
Postman實(shí)現(xiàn)傳List<String>集合
這篇文章主要介紹了Postman實(shí)現(xiàn)傳List<String>集合方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
關(guān)于Spring自定義XML schema 擴(kuò)展的問(wèn)題(Spring面試高頻題)
今天給大家分享一道spring高頻率面試題關(guān)于Spring自定義XML schema 擴(kuò)展的問(wèn)題,今天以spring整合dubbo的實(shí)例給大家詳細(xì)講解下,感興趣的朋友跟隨小編一起看看吧2021-05-05
springboot項(xiàng)目編譯提示無(wú)效的源發(fā)行版17解決辦法
這篇文章主要給大家介紹了關(guān)于springboot項(xiàng)目編譯提示無(wú)效的源發(fā)行版17解決辦法,這個(gè)錯(cuò)誤意味著你的Spring Boot項(xiàng)目正在使用Java 17這個(gè)版本,但是你的項(xiàng)目中未配置正確的Java版本,需要的朋友可以參考下2023-06-06
Java中將一個(gè)列表拆分為多個(gè)較小列表的三種不同方法
有時(shí)候我們需要將大集合按指定的數(shù)量分割成若干個(gè)小集合,這篇文章主要給大家介紹了關(guān)于Java中將一個(gè)列表拆分為多個(gè)較小列表的三種不同方法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-09-09
Java實(shí)現(xiàn)冒泡排序簡(jiǎn)單示例
冒泡排序(Bubble Sort)是一種簡(jiǎn)單的排序算法,它重復(fù)地走訪過(guò)要排序的數(shù)列,一次比較兩個(gè)元素,如果他們的順序錯(cuò)誤就把他們交換過(guò)來(lái),下面這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)冒泡排序的相關(guān)資料,需要的朋友可以參考下2023-06-06

