<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
表之間的關係有幾種:一對多、多對一、 一對一、多對多
在多對一關係中,把多的部分拆成一個一個物件其實就是一對一關係,如賬戶和使用者是多對一關係,但每個賬戶只對應一個使用者。所以在mybatis中,多對一的關係可以看成一對一的關係。
這裡我把一對多和多對一的xml設定方式總結了一下,同時還有載入方式。
一對多,多對多:通常情況下我們都是採用延遲載入。
多對一,一對一:通常情況下我們都是採用立即載入。
至於註解方式和多對多查詢的xml和註解方式我會另外寫部落格。
我們以使用者和賬戶為例,使用者可以有多個賬戶,賬戶只能對應一個使用者。所以使用者對賬戶是一對多關係,賬戶對使用者是多對一關係。表如下圖所示,使用者表user,賬戶表account,賬戶表UID對應使用者表id。
首先我們要在User實體類中新增List accounts的集合成員變數,表示一對多對映關係,主表實體含有從表實體的集合參照。
public class User implements Serializable{ private Integer id; private String username; private String address; private String sex; private Date birthday; //一對多對映關係,主表實體含有從表實體的集合參照 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; } }
同時在User Dao介面中提供查詢所有方法findAll,在Account Dao介面中提供根據id查詢user的方法findById,以便延時載入時呼叫。
這裡說明因為使用者可能對應許多賬戶,當我們查詢使用者時可能並不需要賬戶資訊,而且如果我們每次查詢使用者時都立即查詢使用者的賬戶資訊,並且賬戶資訊有很多,勢必對記憶體有很大的開銷。所以當我們需要賬戶資訊時再呼叫findById方法去查詢使用者對應的賬戶資訊。
public interface IUserDao { /** * 查詢所有操作,並攜帶賬戶資訊 * @return */ List<User> findAll(); /** * 根據id查詢一個使用者 * @param uid */ User findById(Integer uid); }
public interface IAccountDao { /** * 查詢所有賬戶 * @return */ List<Account> findAll(); /** * 根據使用者id查詢賬戶 * @param uid * @return */ List<Account> findByUid(Integer uid); }
然後設定userDao.xml,說明會在程式碼中給出。
<mapper namespace="com.cc.dao.IUserDao"> <!--定義resultMap--> <!--因為在主組態檔中設定了domain包下的所有實體類別名,所以這裡封裝型別只需要寫實體類名即可,不分大小寫--> <resultMap id="userWithAccount" type="user"> <!--封裝user物件--> <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隊形中account集合的對映--> <!--定義一對多的關係對映,實現對account的封裝,用collection標籤 ofType屬性指定內容:要封裝的實體物件型別 select屬性指定內容:查詢使用者的唯一標識 column屬性指定內容:使用者根據id查詢是所需要的引數 --> <collection property="accounts" ofType="account" column="id" select="com.cc.dao.IAccountDao.findByUid"></collection> </resultMap> <!--查詢所有--> <select id="findAll" resultMap="userWithAccount"> select * from user </select> <!--根據id查詢一個使用者--> <select id="findById" parameterType="java.lang.Integer" resultType="user"> select * from user where id=#{uid}; </select> </mapper>
當然我們還要在主組態檔中開啟延時載入,預設情況下是立即載入。
lazyLoadingEnabled:是否啟用延遲載入,mybatis預設為false,不啟用延遲載入。lazyLoadingEnabled屬性控制全域性是否使用延遲載入,特殊關聯關係也可以通過巢狀查詢中fetchType屬性單獨設定(fetchType屬性值lazy或者eager)。
也就是說我們可以不用在主組態檔中設定而在userDao.xml中設定,這裡我們採用全域性設定。
<!--設定引數--> <settings> <!--開啟Mybatis支援延時載入--> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"></setting> </settings> <!--設定domain包下所有實體類別名--> <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//在測試方法執行之前執行 public void init() throws IOException { //1.讀取組態檔,生成位元組輸入流 in = Resources.getResourceAsStream("SqlMapConfig.xml"); //2.生成SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); //3.獲取SqlSession sqlSession = factory.openSession(); //4.獲取dao的代理物件 userDao = sqlSession.getMapper(IUserDao.class); } @After//在測試方法執行之後執行 public void destory() throws IOException { //提交事務 sqlSession.commit(); //關閉資源 sqlSession.close(); in.close(); } /** * 測試查詢所有賬戶 */ @Test public void TestFindAll() { //5.執行查詢所有方法 List<User> userList = userDao.findAll(); for (User user : userList) { System.out.println(user); System.out.println(user.getAccounts()); } } }
先把遍歷輸出部分程式碼註釋掉,測試可以看出我們只查詢了使用者資訊。
然後去掉註釋,發現當我們需要輸出使用者賬戶時,他就會去查詢使用者的賬戶資訊。
步驟其實和一對多差不多。
首先我們在account實體類中加入user成員變數表示一對一對映。
public class Account implements Serializable { private Integer id; private Integer uid; private Double money; //從表實體應該包含一個主表實體的物件參照 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介面中需要的的方法在上面總結一對多查詢時的圖中已經給出。
然後設定accountDao.xml,這裡是立即查詢,在我們已經設定全域性延時載入的情況下,我們需要設定fetchType=“eager”。
<mapper namespace="com.cc.dao.IAccountDao"> <!--開啟account支援二級快取--> <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> <!--定義一對一的關係對映,實現對user的封裝 select屬性指定內容:查詢使用者的唯一標識 column屬性指定內容:使用者根據id查詢是所需要的引數 fetchType屬性指定內容:lazy延時載入,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> <!--根據使用者id查詢--> <select id="findByUid" parameterType="java.lang.Integer" resultType="account" useCache="true"> select * from account where uid = #{uid} </select> </mapper>
然後我們就可以測試。可以看出當查詢賬戶時就立即查詢了對應的使用者資訊。
第一嘗試部落格,肯定有很多欠缺的地方,希望大家看到能評論指出。我自己學mybatis時間也不是很長,這裡只給出了簡單的案例。如果什麼理解不到位的地方也請大家諒解並指出。以後我會更多的寫部落格,希望能夠給一起處在學習階段的人一些啟發。
到此這篇關於mybatis多表查詢的實現(xml方式)的文章就介紹到這了,更多相關mybatis多表查詢內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45