終于把論文寫得差不多了,系統也不急着完成,可以抽出點時間來完成這個系列的部落格了。在寫本部落格之前我是惶恐不安的,進階映射一貫是持久層架構裡的重中之重,小到自己開發小系統,大到企業級開發,表的存在從來就不獨立的。複雜交錯的表之間的聯系有時的确讓背景開發人員頭疼,而作為一個架構,要做的事就是把這種複雜程度降到最低。既然如此,我們就趕快進入正文吧。
先說一對一吧,前幾篇博文裡用到了User類,今天我們再加上一個Orders訂單類
一個訂單隻能由一個使用者建立,是以根據訂單查找使用者是一對一的查找,是以當我想查出訂單關聯使用者的所有記錄怎麼查呢?
我們知道這個查詢時不用輸入參數的,是以在select裡面是不用輸入parameterType的,由此可知查詢關鍵就在resultType了,的确,但是今天resultType有時會不夠用,當然這都是後話了,在一對一查詢裡面resultType完全是夠用的,是以先看看這個怎麼用吧
先分析一波,我們之前的所有的輸出都有相會映射成相應的類,而我們現在沒有一個既包含User屬性又包含Orders的類怎麼辦呢?
沒錯,就是建立一個滿足以上條件的類,在這裡有一個小技巧,我們大多時候不需要關聯表裡的所有屬性,比如在這裡我們隻要user類的使用者名和位址兩個屬性時,可以建立一個Orders類的擴充類,在該擴充類裡添加屬性username和address,就像下面
解決了映射類,接下來就是xml檔案了
先把sql語句貼上來
SELECT
orders.*, user.username, user.address
FROM
orders,
user
WHERE
orders.user_id = user.id;
這個sql語句很簡單我就不多說了,有了這個mapper.xml就簡單了
<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接口中的方法寫了
//查詢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架構的内容等等。。。
最後最後說一點,這些知識我也是在短期内學完的,算是現學現賣,如果哪位大神“随意”看了一眼發現了錯誤或者有更好的見解還請不吝賜教啊
轉載于:https://www.cnblogs.com/scuury/p/8575189.html