mybatis多表查詢的實(shí)現(xiàn)(xml方式)
前言
表之間的關(guān)系有幾種:一對(duì)多、多對(duì)一、 一對(duì)一、多對(duì)多
在多對(duì)一關(guān)系中,把多的部分拆成一個(gè)一個(gè)對(duì)象其實(shí)就是一對(duì)一關(guān)系,如賬戶和用戶是多對(duì)一關(guān)系,但每個(gè)賬戶只對(duì)應(yīng)一個(gè)用戶。所以在mybatis中,多對(duì)一的關(guān)系可以看成一對(duì)一的關(guān)系。
這里我把一對(duì)多和多對(duì)一的xml配置方式總結(jié)了一下,同時(shí)還有加載方式。
一對(duì)多,多對(duì)多:通常情況下我們都是采用延遲加載。
多對(duì)一,一對(duì)一:通常情況下我們都是采用立即加載。
至于注解方式和多對(duì)多查詢的xml和注解方式我會(huì)另外寫博客。
數(shù)據(jù)庫表及關(guān)系
我們以用戶和賬戶為例,用戶可以有多個(gè)賬戶,賬戶只能對(duì)應(yīng)一個(gè)用戶。所以用戶對(duì)賬戶是一對(duì)多關(guān)系,賬戶對(duì)用戶是多對(duì)一關(guān)系。表如下圖所示,用戶表user,賬戶表account,賬戶表UID對(duì)應(yīng)用戶表id。
一對(duì)多查詢
首先我們要在User實(shí)體類中添加List accounts的集合成員變量,表示一對(duì)多映射關(guān)系,主表實(shí)體含有從表實(shí)體的集合引用。
public class User implements Serializable{ private Integer id; private String username; private String address; private String sex; private Date birthday; //一對(duì)多映射關(guān)系,主表實(shí)體含有從表實(shí)體的集合引用 private List<Account> accounts; public List<Account> getAccounts() { return accounts; } public void setAccounts(List<Account> accounts) { this.accounts = accounts; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", address='" + address + '\'' + ", sex='" + sex + '\'' + ", birthday=" + birthday + '}'; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
同時(shí)在User Dao接口中提供查詢所有方法findAll,在Account Dao接口中提供根據(jù)id查詢user的方法findById,以便延時(shí)加載時(shí)調(diào)用。
這里說明因?yàn)橛脩艨赡軐?duì)應(yīng)許多賬戶,當(dāng)我們查詢用戶時(shí)可能并不需要賬戶信息,而且如果我們每次查詢用戶時(shí)都立即查詢用戶的賬戶信息,并且賬戶信息有很多,勢(shì)必對(duì)內(nèi)存有很大的開銷。所以當(dāng)我們需要賬戶信息時(shí)再調(diào)用findById方法去查詢用戶對(duì)應(yīng)的賬戶信息。
public interface IUserDao { /** * 查詢所有操作,并攜帶賬戶信息 * @return */ List<User> findAll(); /** * 根據(jù)id查詢一個(gè)用戶 * @param uid */ User findById(Integer uid); }
public interface IAccountDao { /** * 查詢所有賬戶 * @return */ List<Account> findAll(); /** * 根據(jù)用戶id查詢賬戶 * @param uid * @return */ List<Account> findByUid(Integer uid); }
然后配置userDao.xml,說明會(huì)在代碼中給出。
<mapper namespace="com.cc.dao.IUserDao"> <!--定義resultMap--> <!--因?yàn)樵谥髋渲梦募信渲昧薲omain包下的所有實(shí)體類別名,所以這里封裝類型只需要寫實(shí)體類名即可,不分大小寫--> <resultMap id="userWithAccount" type="user"> <!--封裝user對(duì)象--> <id property="id" column="id"></id> <result property="username" column="username"></result> <result property="address" column="address"></result> <result property="sex" column="sex"></result> <result property="birthday" column="birthday"></result> <!--配置user隊(duì)形中account集合的映射--> <!--定義一對(duì)多的關(guān)系映射,實(shí)現(xiàn)對(duì)account的封裝,用collection標(biāo)簽 ofType屬性指定內(nèi)容:要封裝的實(shí)體對(duì)象類型 select屬性指定內(nèi)容:查詢用戶的唯一標(biāo)識(shí) column屬性指定內(nèi)容:用戶根據(jù)id查詢是所需要的參數(shù) --> <collection property="accounts" ofType="account" column="id" select="com.cc.dao.IAccountDao.findByUid"></collection> </resultMap> <!--查詢所有--> <select id="findAll" resultMap="userWithAccount"> select * from user </select> <!--根據(jù)id查詢一個(gè)用戶--> <select id="findById" parameterType="java.lang.Integer" resultType="user"> select * from user where id=#{uid}; </select> </mapper>
當(dāng)然我們還要在主配置文件中開啟延時(shí)加載,默認(rèn)情況下是立即加載。
lazyLoadingEnabled:是否啟用延遲加載,mybatis默認(rèn)為false,不啟用延遲加載。lazyLoadingEnabled屬性控制全局是否使用延遲加載,特殊關(guān)聯(lián)關(guān)系也可以通過嵌套查詢中fetchType屬性單獨(dú)配置(fetchType屬性值lazy或者eager)。
也就是說我們可以不用在主配置文件中配置而在userDao.xml中配置,這里我們采用全局配置。
<!--配置參數(shù)--> <settings> <!--開啟Mybatis支持延時(shí)加載--> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"></setting> </settings> <!--配置domain包下所有實(shí)體類別名--> <typeAliases> <!--<typeAlias type="com.cc.domain.User" alias="user"></typeAlias>--> <package name="com.cc.domain"></package> </typeAliases>
然后我們就可以測試了
public class UserTest { private InputStream in; private SqlSessionFactory factory; private SqlSession sqlSession; private IUserDao userDao; @Before//在測試方法執(zhí)行之前執(zhí)行 public void init() throws IOException { //1.讀取配置文件,生成字節(jié)輸入流 in = Resources.getResourceAsStream("SqlMapConfig.xml"); //2.生成SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //3.獲取SqlSession sqlSession = factory.openSession(); //4.獲取dao的代理對(duì)象 userDao = sqlSession.getMapper(IUserDao.class); } @After//在測試方法執(zhí)行之后執(zhí)行 public void destory() throws IOException { //提交事務(wù) sqlSession.commit(); //關(guān)閉資源 sqlSession.close(); in.close(); } /** * 測試查詢所有賬戶 */ @Test public void TestFindAll() { //5.執(zhí)行查詢所有方法 List<User> userList = userDao.findAll(); for (User user : userList) { System.out.println(user); System.out.println(user.getAccounts()); } } }
先把遍歷輸出部分代碼注釋掉,測試可以看出我們只查詢了用戶信息。
然后去掉注釋,發(fā)現(xiàn)當(dāng)我們需要輸出用戶賬戶時(shí),他就會(huì)去查詢用戶的賬戶信息。
多對(duì)一及一對(duì)一查詢
步驟其實(shí)和一對(duì)多差不多。
首先我們?cè)赼ccount實(shí)體類中加入user成員變量表示一對(duì)一映射。
public class Account implements Serializable { private Integer id; private Integer uid; private Double money; //從表實(shí)體應(yīng)該包含一個(gè)主表實(shí)體的對(duì)象引用 private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getUid() { return uid; } public void setUid(Integer uid) { this.uid = uid; } public Double getMoney() { return money; } public void setMoney(Double money) { this.money = money; } @Override public String toString() { return "Account{" + "id=" + id + ", uid=" + uid + ", money=" + money + '}'; } }
Dao接口中需要的的方法在上面總結(jié)一對(duì)多查詢時(shí)的圖中已經(jīng)給出。
然后配置accountDao.xml,這里是立即查詢,在我們已經(jīng)配置全局延時(shí)加載的情況下,我們需要配置fetchType=“eager”。
<mapper namespace="com.cc.dao.IAccountDao"> <!--開啟account支持二級(jí)緩存--> <cache/> <!--定義封裝account和user的resultMap--> <resultMap id="accountAndUser" type="account"> <id property="id" column="aid"></id> <result property="uid" column="uid"></result> <result property="money" column="money"></result> <!--定義一對(duì)一的關(guān)系映射,實(shí)現(xiàn)對(duì)user的封裝 select屬性指定內(nèi)容:查詢用戶的唯一標(biāo)識(shí) column屬性指定內(nèi)容:用戶根據(jù)id查詢是所需要的參數(shù) fetchType屬性指定內(nèi)容:lazy延時(shí)加載,eager立即加載。 --> <association property="user" column="uid" javaType="user" select="com.cc.dao.IUserDao.findById" fetchType="eager"></association> </resultMap> <!--查詢所有--> <select id="findAll" resultMap="accountAndUser"> SELECT * from account </select> <!--根據(jù)用戶id查詢--> <select id="findByUid" parameterType="java.lang.Integer" resultType="account" useCache="true"> select * from account where uid = #{uid} </select> </mapper>
然后我們就可以測試。可以看出當(dāng)查詢賬戶時(shí)就立即查詢了對(duì)應(yīng)的用戶信息。
總結(jié)
第一嘗試博客,肯定有很多欠缺的地方,希望大家看到能評(píng)論指出。我自己學(xué)mybatis時(shí)間也不是很長,這里只給出了簡單的案例。如果什么理解不到位的地方也請(qǐng)大家諒解并指出。以后我會(huì)更多的寫博客,希望能夠給一起處在學(xué)習(xí)階段的人一些啟發(fā)。
到此這篇關(guān)于mybatis多表查詢的實(shí)現(xiàn)(xml方式)的文章就介紹到這了,更多相關(guān)mybatis多表查詢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
簡單解析java方法在調(diào)用在內(nèi)存中的執(zhí)行過程
這篇文章主要介紹了簡單解析java方法在調(diào)用在內(nèi)存中的執(zhí)行過程,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-07-07springBoot下實(shí)現(xiàn)java自動(dòng)創(chuàng)建數(shù)據(jù)庫表
這篇文章主要介紹了springBoot下實(shí)現(xiàn)java自動(dòng)創(chuàng)建數(shù)據(jù)庫表的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07Java解壓縮zip - 解壓縮多個(gè)文件或文件夾實(shí)例
本篇文章主要介紹了Java解壓縮zip - 解壓縮多個(gè)文件或文件夾實(shí)例,非常具有實(shí)用價(jià)值,有需要的可以了解一下。2016-12-12實(shí)例講解Java的設(shè)計(jì)模式編程中責(zé)任鏈模式的運(yùn)用
這篇文章主要介紹了Java的設(shè)計(jì)模式編程中責(zé)任鏈模式的運(yùn)用,講解了通過條件判斷結(jié)構(gòu)來分配不同對(duì)象的責(zé)任權(quán)限,需要的朋友可以參考下2016-02-02SpringBoot項(xiàng)目War包部署無法注冊(cè)到Nacos中的解決
這篇文章主要介紹了SpringBoot項(xiàng)目War包部署無法注冊(cè)到Nacos中的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01云IDE:Eclipse Che:Eclipse下一代IDE(推薦)
這篇文章主要介紹了云IDE:Eclipse Che:Eclipse下一代IDE,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09