Mybatis實現高級映射一對1、一對多查詢

終於把論文寫得差很少了,系統也不急着完成,能夠抽出點時間來完成這個系列的博客了。在寫本博客以前我是驚慌失措的,高級映射一向是持久層框架裏的重中之重,小到本身開發小系統,大到企業級開發,表的存在歷來就不獨立的。複雜交錯的表之間的聯繫有時的確讓後臺開發人員頭疼,而做爲一個框架,要作的事就是把這種複雜程度降到最低。既然如此,咱們就趕快進入正文吧。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框架的內容等等。。。

最後最後說一點,這些知識我也是在短時間內學完的,算是現學現賣,若是哪位大神「隨意」看了一眼發現了錯誤或者有更好的看法還請不吝賜教啊

相關文章
相關標籤/搜索