終於把論文寫得差很少了,系統也不急着完成,能夠抽出點時間來完成這個系列的博客了。在寫本博客以前我是驚慌失措的,高級映射一向是持久層框架裏的重中之重,小到本身開發小系統,大到企業級開發,表的存在歷來就不獨立的。複雜交錯的表之間的聯繫有時的確讓後臺開發人員頭疼,而做爲一個框架,要作的事就是把這種複雜程度降到最低。既然如此,咱們就趕快進入正文吧。java
先說一對一吧,前幾篇博文裏用到了User類,今天咱們再加上一個Orders訂單類spring
一個訂單隻能由一個用戶建立,因此根據訂單查找用戶是一對一的查找,因此當我想查出訂單關聯用戶的全部記錄怎麼查呢?sql
咱們知道這個查詢時不用輸入參數的,因此在select裏面是不用輸入parameterType的,由此可知查詢關鍵就在resultType了,的確,可是今天resultType有時會不夠用,固然這都是後話了,在一對一查詢裏面resultType徹底是夠用的,因此先看看這個怎麼用吧數據庫
先分析一波,咱們以前的全部的輸出都有相會映射成相應的類,而咱們如今沒有一個既包含User屬性又包含Orders的類怎麼辦呢?mybatis
沒錯,就是新建一個知足以上條件的類,在這裏有一個小技巧,咱們大多時候不須要關聯表裏的全部屬性,好比在這裏咱們只要user類的用戶名和地址兩個屬性時,能夠建立一個Orders類的擴展類,在該擴展類裏添加屬性username和address,就像下面app
解決了映射類,接下來就是xml文件了框架
先把sql語句貼上來測試
SELECT orders.*, user.username, user.address FROM orders, user WHERE orders.user_id = user.id;
這個sql語句很簡單我就很少說了,有了這個mapper.xml就簡單了ui
<select id="findOrderCustom" resultType="com.mybatis.pojo.OrderCustom"> SELECT orders.*, user.username, user.address FROM orders, user WHERE orders.user_id = user.id; </select>
而後就是遵循規範把mapper接口中的方法寫了spa
//查詢Orders關聯User使用resultType public List<OrderCustom> findOrderCustom();
最後是測試代碼
public class UserMapperTest { private SqlSessionFactory sqlSessionFactory; @Before public void setUp() throws Exception { //獲得配置文件流 InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml"); //建立會話會話工廠 sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindOrderCustom() throws Exception { //建立會話 SqlSession sqlSession = sqlSessionFactory.openSession(); //建立mapper代理對象 UserMapper userMapper= sqlSession.getMapper(UserMapper.class); List<OrderCustom> list=userMapper.findOrderCustom(); //調用代理對象的方法,打印結果 System.out.println(list.size()); sqlSession.close(); } }
大功告成,這個測試代碼我已經測試過了沒有問題,因此若是有跟初學者想拿着博主的代碼運行一遍也是沒有問題的。
其實從最開始學到如今,博主一直有一個疑問,爲了實現映射一直以來表和類中屬性的命名都要保持一致。可是咱們的java類規範命名都是用駝峯命名法,而數據庫中屬性命名大多采用下劃線,這樣保持一致不得不改變一方的命名規則,有沒有什麼方法能夠兩全呢?
答案就是resultMap,跟resultType直接進行類的映射不一樣,resultMap講究的是屬性的映射。爲了舉例我再引進一個類,商品類Goods
表結構是這樣的
接下來要作的事就是使用resultMap從表中查出全部的數據
在使用resultMap以前要先定義它,怎麼定義呢,看代碼
<!-- 定義resultMap --> <resultMap type="com.mybatis.pojo.Goods" id="goodsResultMap"> <id column="id" property="id"/> <result column="goods_name" property="goodsName"/> <result column="goods_price" property="goodsPrice"/> </resultMap>
主鍵用的是id,普通屬性統一使用result。其中column和property分別表明在表和類中的屬性名。resultMap的id是爲了讓下面的select語句引用的,接下來就給出select語句
<!-- 用resultMap查詢goods信息 --> <select id="findGoodsResultMap" resultMap="goodsResultMap"> select * from goods </select>
整個xml的工做就算完成了,老規矩,下面給出mapper接口中的方法和測試代碼(注意全部的測試都要加上@before的內容,我這裏就懶得再寫了)
//查詢goods使用resultMap public List<Goods> findGoodsResultMap();
//測試查詢goods使用resultMap @Test public void testFindGoodsResultMap() throws Exception { //建立會話 SqlSession sqlSession = sqlSessionFactory.openSession(); //建立mapper代理對象 UserMapper userMapper= sqlSession.getMapper(UserMapper.class); List<Goods> list=userMapper.findGoodsResultMap(); //調用代理對象的方法,打印結果 System.out.println(list.size()); sqlSession.close(); }
寫到這裏,是否是有人想叫博主用resultMap的方法來寫一寫以前一對一的查詢呢,放心吧,我後面也會講到的。
首先看需求,若是我想列出全部用戶的全部訂單,可是用戶信息又不能重複該怎麼辦,這個時候resultType就不夠用了,由於需求是用戶信息不能重複因此訂單類要以list的方式存在
用戶類中以下所示
而咱們的user表可否直接與上面的類對應呢,顯然是不行的,既然不行的話resultMap就要上場了,以前就說過resultMap是細化到屬性的對應的,咱們徹底能夠將User類中的list中的對象細化到單獨對應orders表,這樣問題就解決了啊,那resultMap要怎麼定義呢
首先把除去list的屬性映射完(懶得麻煩就只寫了id,username,address三個屬性),寫完就是下面這個樣子
<resultMap type="com.mybatis.pojo.User" id="userAndOrdersResultMap"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="address" property="address"/> </resultMap>
千萬要記住咱們的主表是user表,因此這裏的type是User類
在resultMap裏有一個屬性collection,這個屬性是專門爲list準備的,讓咱們來看看加上這個會是什麼樣子的
<resultMap type="com.mybatis.pojo.User" id="userAndOrdersResultMap"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="address" property="address"/> <collection property="orderList" ofType="com.mybatis.pojo.Orders"> <id column="id" property="id"/> <result column="user_id" property="user_id"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> </collection> </resultMap>
在collection中的property對應類中的屬性名,ofType對應類中的list中的對象類型,在這裏就是Orders類了,剩下的東西就和以前的配置徹底同樣了,無非是將orders類中的屬性名和表中的屬性名對應了。
接下來就是select語句了
<!-- 查詢用戶關聯訂單使用resultMap --> <select id="findUserAndOrdersResultMap" resultMap="userAndOrdersResultMap"> SELECT user.id, user.username, user.address, orders.* FROM orders, user WHERE user.id = orders.user_id; </select>
是否是sql語句發現和以前寫的好像是同樣的,啊哈哈,我也是寫完才發現的,需求是隨便編的。。。
下面是mapper接口中的方法和測試代碼(注意全部的測試都要加上@before的內容,我這裏就懶得再寫了)
//查詢User關聯Orders使用resultMap public List<User> findUserAndOrdersResultMap();
//測試查詢User關聯Orders使用resultMap @Test public void testFindUserAndOrdersResultMap() throws Exception { //建立會話 SqlSession sqlSession = sqlSessionFactory.openSession(); //建立mapper代理對象 UserMapper userMapper= sqlSession.getMapper(UserMapper.class); List<User> list=userMapper.findUserAndOrdersResultMap(); //調用代理對象的方法,打印結果 System.out.println(list.size()); sqlSession.close(); }
個人數據庫orders表中有三條記錄,兩條是同一個用戶建立的,因此輸出結果應該是2,沒問題
最後囉嗦一點
若是需求變成訂單再關聯商品信息該怎麼寫呢,咱們知道訂單和商品也是一對一的,即一個訂單裏面只能有一個該商品的記錄(注意,這裏的一個指的不是一件,若是用戶買了多件該商品最後也會變成一個商品記錄,變的只是數量而已),至關於在Orders類中增長一個Goods類做爲屬性,這個時候該怎麼寫呢,Mybatis提供了一個叫作association的屬性用於關聯類,至關於在collection里加上一個association,這個時候,xml文件會變成這樣
<resultMap type="com.mybatis.pojo.User" id="userAndOrdersResultMap"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="address" property="address"/> <collection property="orderList" ofType="com.mybatis.pojo.Orders"> <id column="id" property="id"/> <result column="user_id" property="user_id"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/>
<association property="goods" javaType="com.mybatis.pojo.Goods"> <id column="id" property="id"/> <result column="goods_name" property="goodsName"/> <result column="goods_price" property="goodsPrice"/> </association>
</collection> </resultMap>
這個博主就不去測試了,反正套路都是同樣的
有了association,以前那個訂單關聯用戶的查詢也就迎刃而解了,只需在Orders類中加一個用戶類的屬性緊接着配一個association就OK了。
終於寫完了,我長舒了一口氣,花了大半個下午的時間呢,後面還會寫多對多查詢,整合spring框架的內容等等。。。
最後最後說一點,這些知識我也是在短時間內學完的,算是現學現賣,若是哪位大神「隨意」看了一眼發現了錯誤或者有更好的看法還請不吝賜教啊