MyBatis一對(duì)多關(guān)系使用@Many注解的實(shí)現(xiàn)
一對(duì)多關(guān)系
在討論使用 MyBatis 實(shí)現(xiàn)一對(duì)多查找之前,有必要在數(shù)據(jù)表和數(shù)據(jù)類設(shè)計(jì)層次上明確一對(duì)多關(guān)系。
假設(shè)一個(gè)用戶有多個(gè)賬戶。在最簡(jiǎn)單的情況下,用戶表僅包含 user_id 和 user_name 列,而賬戶表則包含 account_id、account_name 和 user_id 外鍵,其中 *_id 列為各個(gè)表的主鍵。
現(xiàn)在來(lái)看數(shù)據(jù)類的設(shè)計(jì)。一個(gè)用戶擁有多個(gè)賬號(hào),自然想到 User 類中包含一個(gè) Account 列表。但是,Account 類中能包含 User 對(duì)象嗎?
如果 Account 中包含 User 對(duì)象,這意味著用戶的信息有泄露的可能(如果用戶表還包含其他隱私信息)。比如,當(dāng)我們只需要知道用戶的某個(gè)賬號(hào)時(shí),卻附贈(zèng)了用戶的一系列其他信息。另外這種互相包含的關(guān)系也容易導(dǎo)致寫出無(wú)限遞歸的查詢語(yǔ)句。Account 要為 User 賦值,而 User 中包含 Account 列表,Account 列表中的元素要為 User 賦值……
這里給出感覺(jué)合理的數(shù)據(jù)表和數(shù)據(jù)類模型。
# users table CREATE TABLE `users` ( `user_id` int NOT NULL, `user_name` varchar(45) NOT NULL, PRIMARY KEY (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
// user 類,忽略 setter 和 getter
public class User {
private Integer userId;
private String userName;
private List<Account> accounts;
}
# accounts table CREATE TABLE `accounts` ( `account_id` int NOT NULL, `account_name` varchar(45) NOT NULL, `user_id` int NOT NULL, PRIMARY KEY (`account_id`), KEY `user_id_idx` (`user_id`), CONSTRAINT `user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
// account 類,忽略 setter 和 getter
public class Account {
private Integer accountId;
private String accountName;
private Integer userId;
}
MyBatis 一對(duì)多查詢
查詢的主要難度在查詢 User 上,其關(guān)鍵是理解 @Many 注解相關(guān)的參數(shù)。
先把簡(jiǎn)單的 AccountDao 搞了。
@Mapper
public interface AccountDao {
@Results(id = "accountResultMap", value = {
@Result(property = "accountId", column = "account_id", id = true),
@Result(property = "accountName", column = "account_name"),
@Result(property = "userId", column = "user_id")
})
@Select(value = "SELECT * FROM accounts WHERE account_id = #{id}")
public Account findAccountById(@Param("id") Integer id);
@ResultMap(value = "accountResultMap")
@Select(value = "SELECT * FROM accounts WHERE user_id=#{id}")
public List<Account> findAccountByUserId(@Param("id") Integer id);
}
注意:這里我們定義了一個(gè) findAccountByUserId 查詢函數(shù)。因?yàn)?User 類在填充 Account 列表時(shí),是用 user_id 進(jìn)行查詢的。
再看 UserDao。
@Mapper
public interface UserDao {
@Results(id = "userResultMap", value = {
@Result(property = "userId", column = "user_id", id = true),
@Result(property = "userName", column = "user_name"),
@Result(property = "accounts", column = "user_id", javaType = List.class,
many = @Many(select = "com.sugarian.dao.AccountDao.findAccountByUserId"))
})
@Select(value = "SELECT * FROM users WHERE user_id=#{id}")
public User findUserById(@Param("id") Integer id);
}
注意下面抽取的部分
@Result(property = "userName", column = "user_name"),
@Result(property = "accounts", column = "user_id", javaType = List.class,
many = @Many(select = "com.sugarian.dao.AccountDao.findAccountByUserId"))
})
User 中的 accounts 是存放 Account 的列表,其在表結(jié)構(gòu)中是沒(méi)有對(duì)應(yīng)的列,所以它對(duì)應(yīng)的這條 @Result 實(shí)際上是再次執(zhí)行了一次 sql 索引,然后將值填充到 accounts 中。另外一點(diǎn),請(qǐng)看 column 是 user_id,這實(shí)際上就是以 user_id 作為參數(shù),findAccountByUserId 用進(jìn)行索引。
我們可以看看調(diào)試工具給出的信息:
2022-11-25 23:39:09,552 [DEBUG] com.sugarian.dao.UserDao.findUserById - ==> Preparing: SELECT * FROM users WHERE user_id=? 2022-11-25 23:39:09,552 [DEBUG] com.sugarian.dao.UserDao.findUserById - ==> Parameters: 1(Integer) 2022-11-25 23:39:09,553 [DEBUG] com.sugarian.dao.AccountDao.findAccountByUserId - ====> Preparing: SELECT * FROM accounts WHERE user_id=? 2022-11-25 23:39:09,553 [DEBUG] com.sugarian.dao.AccountDao.findAccountByUserId - ====> Parameters: 1(Integer) 2022-11-25 23:39:09,556 [DEBUG] com.sugarian.dao.AccountDao.findAccountByUserId - <==== Total: 3 2022-11-25 23:39:09,556 [DEBUG] com.sugarian.dao.UserDao.findUserById - <== Total: 1
明顯執(zhí)行了兩次 sql 查詢。對(duì)于第二個(gè)查詢,它從第一個(gè)查詢結(jié)果中取出其中的 user_id 列,作為查詢的參數(shù)。
其他參數(shù)如 javaType 指定返回類型。@Many 中的參數(shù) select 指定第二次查詢用的函數(shù)。
到此這篇關(guān)于MyBatis一對(duì)多關(guān)系使用@Many注解的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)MyBatis一對(duì)多@Many 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用html css javascript打造自己的RIA圖文教程
用html&css&javascript打造自己的RIA之一,包括了配置等2009-07-07
解決IDEA中同項(xiàng)目引用報(bào)紅問(wèn)題
在IDEA中,如果項(xiàng)目引用報(bào)紅,可能是因?yàn)镮DEA的引用緩存問(wèn)題,可以通過(guò)File->Invalidate Caches/Restart清空緩存并重建索引來(lái)解決,這個(gè)方法可以幫助解決同項(xiàng)目中引用找不到的問(wèn)題,恢復(fù)正常的項(xiàng)目引用,消除報(bào)紅2024-09-09
Hadoop環(huán)境配置之hive環(huán)境配置詳解
這篇文章主要介紹了Hadoop環(huán)境配置之hive環(huán)境配置,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12
支持SpEL表達(dá)式的自定義日志注解@SysLog介紹
這篇文章主要介紹了支持SpEL表達(dá)式的自定義日志注解@SysLog,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
Java?Stream函數(shù)式編程管道流結(jié)果處理
這篇文章主要為大家介紹了Java?Stream函數(shù)式編程管道流結(jié)果處理的示例過(guò)程解析需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03
MybatisPlus 主鍵策略的幾種實(shí)現(xiàn)方法
MybatisPlus-Plus支持多種主鍵生成策略,可以通過(guò)@TableId注解的type屬性配置,主要策略包括AUTO、INPUT、ASSING_ID、ASSING_UUID和NONE,每種策略適用于不同的場(chǎng)景,下面就來(lái)介紹一下2024-10-10
java實(shí)現(xiàn)砸金蛋抽獎(jiǎng)功能
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)砸金蛋抽獎(jiǎng)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11

