最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatis-Flex實現(xiàn)多表聯(lián)查(自動映射)

 更新時間:2024年06月24日 09:58:44   作者:kunkun2580  
我們可以輕松的使用 Mybaits-Flex 鏈接任何數(shù)據(jù)庫,本文主要介紹了MyBatis-Flex實現(xiàn)多表聯(lián)查(自動映射),具有一定的參考價值,感興趣的可以了解一下

 簡介:

MyBatis-Flex 是一個優(yōu)雅的 MyBatis 增強框架,它非常輕量、同時擁有極高的性能與靈活性。我們可以輕松的使用 Mybaits-Flex 鏈接任何數(shù)據(jù)庫,其內(nèi)置的 "QueryWrapper " → 亮點,幫助我們極大的減少了 SQL 編寫的工作的同時,減少出錯的可能性。

官網(wǎng):

MyBatis-Flex - MyBatis-Flex 官方網(wǎng)站

多表聯(lián)查

初始對比:

為了方便熟悉,我們和mybatis-plus的查詢做一個對比,更加容易理解:

MyBatis-Flex:

QueryWrapper query = new QueryWrapper()
    .select(
        ACCOUNT.ID,
        ACCOUNT.USER_NAME,
        max(ACCOUNT.BIRTHDAY),
        avg(ACCOUNT.SEX).as("sex_avg")
    );
List<Employee> employees = employeeMapper.selectListByQuery(query);

MyBatis-Plus:

QueryWrapper<Employee> queryWrapper = new QueryWrapper<>();
queryWrapper
    .select(
        "id"
        ,"user_name"
        ,"max(birthday)"
        ,"avg(birthday) as sex_avg"
    );
List<Employee> employees = employeeMapper.selectList(queryWrapper);

在多表聯(lián)查前面我們先嘗試一個基礎(chǔ)查詢(基礎(chǔ)映射):

@Table(value = "tb_account")
public class Account {

    @Id(keyType = KeyType.Auto)
    private Long id;
    private String userName;
    private int age;

    //getter setter
}

Account.java 與表 tb_account 是字段和屬性是一一對應(yīng)關(guān)系的。此時,我們在查詢數(shù)據(jù)的時候,可以通過 AccountMapper 方法直接查詢,例如:

QueryWrapper qw = new QueryWrapper();
qw.select(ACCOUNT.ALL_COLUMNS)
    .where(ACCOUNT.ID.ge(100));

List<Account> accounts = accountMapper.selectListByQuery(qw);

或者使用如下的鏈?zhǔn)讲樵?,都可以直接得?nbsp;List<Account> 結(jié)果:accounts

QueryChain.of(accountMapper)
    .select(ACCOUNT.ALL_COLUMNS)
    .where(ACCOUNT.ID.ge(100))
    .list();

AS 映射

假設(shè)我們在 Account.java 中多定義了一些其他屬性,如下所示:

@Table(value = "tb_account")
public class Account {

    @Id(keyType = KeyType.Auto)
    private Long id;
    private String userName;
    private int age;

    //最大年齡
    private int maxAge;

    //平均年齡
    private int avgAge;

    //getter setter
}

那么,我們在查詢的時候,就可以通過 as 進(jìn)行映射關(guān)聯(lián),查詢代碼如下:

QueryChain.of(accountMapper)
    .select(
        ACCOUNT.ALL_COLUMNS,
        max(ACCOUNT.AGE).as("maxAge"),
        avg(ACCOUNT.AGE).as("avgAge")
    ).where(ACCOUNT.ID.ge(100))
    .groupBy(ACCOUNT.AGE)
    .list();

或者:

QueryChain.of(accountMapper)
    .select(
        ACCOUNT.ALL_COLUMNS,
        max(ACCOUNT.AGE).as("max_age"),
        avg(ACCOUNT.AGE).as("avg_age")
    ).where(ACCOUNT.ID.ge(100))
    .groupBy(ACCOUNT.AGE)
    .list();

或者使用 lambda:

QueryChain.of(accountMapper)
    .select(
        ACCOUNT.ALL_COLUMNS,
        max(ACCOUNT.AGE).as(Account::getMaxAge),
        avg(ACCOUNT.AGE).as(Account::getAvgAge)
    ).where(ACCOUNT.ID.ge(100))
    .groupBy(Account::getAge)
    .list();

以上代碼執(zhí)行的 SQL 如下:

select tb_account.*
     , max(tb_account.age) as maxAge
     , avg(tb_account.age) as avgAge
where tb_account.id >= 100
group by tb_account.age

多表映射

假設(shè)我們定義了一個 BootVo.java,其中包含了圖書的基本信息,也包含了圖書歸屬的用戶信息,例如:

public class BookVo {

    //圖書的基本字段
    private Long id;
    private Long accountId;
    private String title;
    private String content;

    //用戶表的字段
    private String userName;
    private int userAge;
}

此時,我們再進(jìn)行 left join 多表查詢時,代碼如下:

List<BookVo> bookVos = QueryChain.of(bookMapper)
    .select(
        BOOK.ALL_COLUMNS, //圖書的所有字段
        ACCOUNT.USER_NAME, //用戶表的 user_name 字段
        ACCOUNT.AGE.as("userAge") //用戶表的 age 字段, as "userAge"
    ).from(BOOK)
    .leftJoin(ACCOUNT).on(BOOK.ACCOUNT_ID.eq(ACCOUNT.ID))
    .where(ACCOUNT.ID.ge(100))
    .listAs(BookVo.class);

或者,我們也可以直接在 BookVo 中,定義 Account 對象,例如:

public class BookVo {

    //圖書的基本字段
    private Long id;
    private Long accountId;
    private String title;
    private String content;

    //用戶
    private Account account;
}

查詢代碼如下:

List<BookVo> bookVos = QueryChain.of(bookMapper)
    .select(
        BOOK.DEFAULT_COLUMNS,
        ACCOUNT.DEFAULT_COLUMNS,
     )
    .from(BOOK)
    .leftJoin(ACCOUNT).on(BOOK.ACCOUNT_ID.eq(ACCOUNT.ID))
    .where(ACCOUNT.ID.ge(100))
    .listAs(BookVo.class);

高級映射?

在以上的表結(jié)構(gòu)中,一個賬戶可以有多本圖書,那么我們假設(shè)定義的 AccountVo.java 的結(jié)構(gòu)如下:

public class AccountVO {

    private Long id;
    private String userName;
    private int age;

    //賬戶擁有的 圖書列表
    private List<Book> books;
}
List<AccountVO> bookVos = QueryChain.of(accountMapper)
    .select() // 不傳入?yún)?shù)等同于 SQL 的 select *
    .from(ACCOUNT)
    .leftJoin(BOOK).on(ACCOUNT.ID.eq(BOOK.ACCOUNT_ID))
    .where(ACCOUNT.ID.ge(100))
    .listAs(AccountVO.class);

亦或者指定查詢參數(shù):

List<AccountVO> bookVos = QueryChain.of(accountMapper)
    .select(
        ACCOUNT.ID,
        ACCOUNT.USER_NAME,
        ACCOUNT.AGE,
        BOOK.TITLE,
        BOOK.CONTENT,
     )
    .from(ACCOUNT)
    .leftJoin(BOOK).on(ACCOUNT.ID.eq(BOOK.ACCOUNT_ID))
    .where(ACCOUNT.ID.ge(100))
    .listAs(AccountVO.class);

高級映射的場景中,我們還可以通過注解 @RelationManyToOne 進(jìn)行查詢, 詳情請點擊 這里。

重名映射?

在很多類型嵌套的場景下,可能會出現(xiàn)字段名定義重復(fù)的情況,例如:

@TableRef(Account.class)
public class AccountVO {

    private Long id;
    private String name;
    private int age;

    //賬戶擁有的 圖書列表
    private List<Book> book;
}
public class Book {
    private Long id;
    private Long accountId;
    private String name;
}

在以上的嵌套定義中, AccountVO 以及 Book 都包含了 id 和 name 的定義,假設(shè)我們查詢的方法如下:

List<AccountVO> bookVos = QueryChain.of(accountMapper)
    .select(
        ACCOUNT.ID,
        ACCOUNT.NAME,
        ACCOUNT.AGE,
        BOOK.ID,
        BOOK.NAME,
     )
    .from(ACCOUNT)
    .leftJoin(BOOK).on(ACCOUNT.ID.eq(BOOK.ACCOUNT_ID))
    .where(ACCOUNT.ID.ge(100))
    .listAs(AccountVO.class);

其執(zhí)行的 SQL 如下:

select tb_account.id   as tb_account$id,
       tb_account.name as tb_account$name,
       tb_account.age,
       tb_book.id      as tb_book$id,  -- Flex 發(fā)現(xiàn)有重名時,會自動添加上 as 別名
       tb_book.name    as tb_book$name -- Flex 發(fā)現(xiàn)有重名時,會自動添加上 as 別名
from tb_account
         left join tb_book on tb_account.id = tb_book.account_id
where tb_account.id >= 100

此時,查詢的數(shù)據(jù)可以正常映射到 AccountVO 類。

注意事項

  • 在查詢 VO 類當(dāng)中有重名字段時,需要給 VO 類標(biāo)記 @TableRef 注解,指定其對應(yīng)的實體類,以正確添加別名。
  • 在 QueryWrapper 的 select(...) 中,MyBatis-Flex 在 多表查詢 的情況下,且有相同的字段名時,MyBatis-Flex 內(nèi)部會主動幫助用戶添加上 as 別名,默認(rèn)為:表名$字段名

錯誤的情況:

若我們修改查詢代碼如下:

List<AccountVO> bookVos = QueryChain.of(accountMapper)
    .select()
    .from(ACCOUNT)
    .leftJoin(BOOK).on(ACCOUNT.ID.eq(BOOK.ACCOUNT_ID))
    .where(ACCOUNT.ID.ge(100))
    .listAs(AccountVO.class);

那么,其執(zhí)行的 SQL 如下:

select * from tb_account
left join tb_book on tb_account.id = tb_book.account_id
where tb_account.id >= 100

此時,查詢的結(jié)果集中,會有多個 id 和 name 列,程序無法知道 id 和 name 對應(yīng)的應(yīng)該是 AccountVO 的還是 Book 的,因此,可能會出現(xiàn)數(shù)據(jù)錯誤賦值的情況。

所以,若程序中出現(xiàn)包裹對象有重名屬性的情況時,QueryWrapper 的 select(...) 方法必須傳入具體的字段才能保證數(shù)據(jù)正常賦值。

如下的代碼也是沒問題的:

List<AccountVO> bookVos = QueryChain.of(accountMapper)
    .select(
        ACCOUNT.DEFAULT_COLUMNS,
        BOOK.DEFAULT_COLUMNS
     )
    .from(ACCOUNT)
    .leftJoin(BOOK).on(ACCOUNT.ID.eq(BOOK.ACCOUNT_ID))
    .where(ACCOUNT.ID.ge(100))
    .listAs(AccountVO.class);

@ColumnAlias 注解:

@ColumnAlias 注解的作用是用于定義在 entity 查詢時,默認(rèn)的 SQL 別名名稱,可以取代自動生成的別名,例如:

public class Book {

    @ColumnAlias("bookId")
    private Long id;

    private Long accountId;

    @ColumnAlias("bookName")
    private String name;
}

那么,假設(shè)我們的查詢代碼如下:

List<AccountVO> bookVos = QueryChain.of(accountMapper)
    .select(
        ACCOUNT.ID,
        ACCOUNT.NAME,
        ACCOUNT.AGE,
        BOOK.ID,
        BOOK.NAME,
     )
    .from(ACCOUNT)
    .leftJoin(BOOK).on(ACCOUNT.ID.eq(BOOK.ACCOUNT_ID))
    .where(ACCOUNT.ID.ge(100))
    .listAs(AccountVO.class);

其執(zhí)行的 SQL 為:

select tb_account.id, tb_account.name, tb_account.age,
    tb_book.id as bookId, -- @ColumnAlias("bookId")
    tb_book.name as bookName  -- @ColumnAlias("bookName")
from tb_account
left join tb_book on tb_account.id = tb_book.account_id
where tb_account.id >= 100

此時,數(shù)據(jù)也是可以正常映射。

到此這篇關(guān)于MyBatis-Flex實現(xiàn)多表聯(lián)查(自動映射)的文章就介紹到這了,更多相關(guān)MyBatis-Flex多表聯(lián)查內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Maven里面沒有plugins dependence問題解決

    Maven里面沒有plugins dependence問題解決

    在整合Nacos和Dubbo時,出現(xiàn)Maven錯誤可以通過檢查父模塊的依賴解決,問題源于MySQL驅(qū)動版本不兼容,移除特定依賴并刷新pom文件可恢復(fù)項目,執(zhí)行clean命令,查看報錯,感興趣的可以了解一下
    2024-10-10
  • SpringBoot使用@Cacheable注解實現(xiàn)緩存功能流程詳解

    SpringBoot使用@Cacheable注解實現(xiàn)緩存功能流程詳解

    最近一直再學(xué)Spring Boot,在學(xué)習(xí)的過程中也有過很多疑問。為了解答自己的疑惑,也在網(wǎng)上查了一些資料,以下是對@Cacheable注解的一些理解
    2023-01-01
  • SpringBoot從0到1整合銀聯(lián)無跳轉(zhuǎn)支付功能附源碼

    SpringBoot從0到1整合銀聯(lián)無跳轉(zhuǎn)支付功能附源碼

    這篇文章主要介紹了SpringBoot從0到1整合銀聯(lián)無跳轉(zhuǎn)功能支付附源碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • JAVASE系統(tǒng)實現(xiàn)抽卡功能

    JAVASE系統(tǒng)實現(xiàn)抽卡功能

    這篇文章主要為大家詳細(xì)介紹了JAVASE系統(tǒng)實現(xiàn)抽卡功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • Java中動態(tài)規(guī)則的實現(xiàn)方式示例詳解

    Java中動態(tài)規(guī)則的實現(xiàn)方式示例詳解

    這篇文章主要介紹了Java中動態(tài)規(guī)則的實現(xiàn)方式,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • Springboot?過濾器、攔截器、全局異常處理的方案處理小結(jié)

    Springboot?過濾器、攔截器、全局異常處理的方案處理小結(jié)

    攔截器是一種動態(tài)攔截方法調(diào)用的機制,與過濾器類似,是Spring框架中提供的,用來動態(tài)攔截控制器方法的執(zhí)行,這篇文章主要介紹了Springboot?過濾器、攔截器、全局異常處理,需要的朋友可以參考下
    2024-03-03
  • Spring?MVC和springboot靜態(tài)資源處理問題

    Spring?MVC和springboot靜態(tài)資源處理問題

    這篇文章主要介紹了Spring?MVC和springboot靜態(tài)資源處理問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Spring Boot 在啟動時進(jìn)行配置文件加解密的方法詳解

    Spring Boot 在啟動時進(jìn)行配置文件加解密的方法詳解

    這篇文章主要介紹了Spring Boot 在啟動時進(jìn)行配置文件加解密的方法,本文通過實例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • 一文讓你徹底學(xué)會Java左移、右移操作

    一文讓你徹底學(xué)會Java左移、右移操作

    這篇文章主要介紹了了Java中的位運算符,包括左移(<<)、右移(>>)和無符號右移(>>>),左移將數(shù)字的二進(jìn)制位向左移動,相當(dāng)于乘以2的n次方;右移將數(shù)字的二進(jìn)制位向右移動,保留符號位,相當(dāng)于除以2的n次方,文中介紹的非常詳細(xì),需要的朋友可以參考下
    2025-02-02
  • Java中的volatile關(guān)鍵字解析

    Java中的volatile關(guān)鍵字解析

    這篇文章主要介紹了Java中的volatile關(guān)鍵字解析,Java內(nèi)存模型規(guī)定了所有的變量都存儲在主內(nèi)存中,每個線程都有自己的工作內(nèi)存,線程的工作內(nèi)存保存了該線程使用到的變量的是主內(nèi)存副本的拷貝,需要的朋友可以參考下
    2023-11-11

最新評論

襄汾县| 荃湾区| 剑河县| 大埔区| 饶阳县| 台安县| 额济纳旗| 香格里拉县| 紫金县| 大邑县| 波密县| 旬阳县| 麻城市| 定陶县| 兴山县| 诸暨市| 广河县| 徐州市| 新野县| 汉阴县| 藁城市| 涟水县| 山东省| 尖扎县| 龙南县| 双牌县| 西华县| 洛南县| 石狮市| 肥西县| 上蔡县| 灵寿县| 沙田区| 青川县| 汶上县| 和龙市| 嵩明县| 哈密市| 郧西县| 台前县| 甘孜|