1. 程式人生 > >Day2 Mybatis初識(二)

Day2 Mybatis初識(二)

junit tro 遍歷 sep combo user 類對象 cti 參數

mapper接口開發

傳統dao的開發問題(ibatis)

方法調用:字符串易錯,硬編碼

mapper代理開發

a) 編寫全局配置

b) 編寫接口(自動根據接口和映射文件創建實現類)

c) 編寫映射文件

  規範:

  A. 映射文件和mapper接口同包同名(批量加載映射文件)

  B. 接口的全限定名稱必須和mapper映射文件的namespace保持一致

  C. 接口中方法名稱和mapper中的標簽id保持一致

  D. 方法的參數類型和mapper的paramerType保持一致

  E. 方法的返回值類型和mapper的resultType和resultMap保持一致

<mapper namespace="mapper.BookMapper">
    <select id="queryAll" resultType="book">
      select * from book
    </select>
</mapper>

d) 測試

SqlSession session = MybatisUtils.getSession();
        //根據mapper接口生成實現類對象
        BookMapper mapper = session.getMapper(BookMapper.class
); System.out.println(mapper.queryAll()); MybatisUtils.closeSession(); //junit:單元測試 //1.加入junit的jar //2.使用junit實現測試(@test:作為單元直接運行 @before/@after:在test之前運行 )

輸入參數和輸出結果

輸出結果

a) resultType:

如果結果集中所有的字段和對象中屬性名稱一一對應則映射成功;

如果結果集中字段的名稱和屬性名稱部分一致,則一致的部分映射成功。

如果結果集中字段的名稱和屬性名稱都不一致,則不會創建對象。

b) 字段和屬性不一致實現封裝

A. 起別名

B. resultMap(實現字段和屬性之間的映射)

<!-- 實現結果集和對象的映射
        id:唯一標識
        type:封裝的對象類型
     -->
    <resultMap type="book" id="bookMap">
        <!-- id:描述主鍵字段和屬性之間的映射關系 
            column:字段
            property:屬性
        -->
        <id column="bi" property="bid"/>
        <!-- result:非主鍵字段的映射 -->
        <result column="bnam" property="bname"/>
        <result column="autho" property="author"/>
        <result column="pric" property="price"/>
    </resultMap>
    
    <select id="queryAll" resultMap="bookMap">
      select * from book
    </select>

動態sql

if:
<select id="queryCombo" parameterType="book" resultType="book">
        select * from book where 1 = 1
        <if test="bid != 0">
            and bid = #{bid}
        </if>
        <if test="bname != null">
            and bname = #{bname}
        </if>
    </select>

choose:
<choose>
            <when test="bid != 0">
                and bid = #{bid}
            </when>
            <otherwise>
                and bname = #{bname}
            </otherwise>
</choose>

where
<where>
            <if test="bid != 0">
                and bid = #{bid}
            </if> 
            <if test="bname != null">
                and bname = #{bname}
            </if> 
</where>


foreach:
select * from book where bid in
        <!-- collection:遍歷的集合
            item:每一項值
            open:開始
            close:結束
            separator:分隔符
         -->
        <foreach collection="list" item="bid" open="(" close=")" separator=",">
            #{bid}
        </foreach>

高級結果映射

1) 查詢的結果集分布於多張表

2) 一對多:Role和User(查詢role級聯查詢所有的員工信息)

<resultMap type="role" id="RoleMap">
        <id column="rid" property="rid"/>
        <result column="rname" property="rname"/>
        <!-- collection:將結果集數據封裝到集合中
                property:屬性
                ofType:單個對象的類型
                column:關聯的鍵
         -->
        <collection property="users" ofType="user" column="rid">
            <id column="uid" property="uid"/>
            <result column="uname" property="uname"/>
            <result column="rid" property="rid"/>
        </collection>
    </resultMap>
    <select id="queryRoleAndUser" resultMap="RoleMap">
        select * from role r left join `user` u on r.rid = u.rid
    </select>


Rolemapper.xml
<resultMap type="role" id="RoleMap2">
        <id column="rid" property="rid"/>
        <result column="rname" property="rname"/>
        <!-- collection:將結果集數據封裝到集合中
                property:屬性
                ofType:單個對象的類型
                column:關聯的鍵
         -->
        <collection property="users" ofType="user" column="rid" 
          select="mapper.UserMapper.selectUser">
        </collection>
    </resultMap>
    <select id="queryRoleAndUser2" resultMap="RoleMap2">
        select * from role
    </select>
UserMapper.xml
<select id="selectUser" resultType="user">
        select * from user where rid = #{rid}
    </select>

3) 一對一:查詢user及其角色(user)

<resultMap type="user" id="userMap">
        <id column="uid" property="uid"/>
        <result column="uname" property="uname"/>
        <!-- 將結果集數據封裝到對象中
            property:對象的屬性名稱
            column:外鍵
            javaType:對象的類型
         -->
        <association property="role" column="rid" javaType="role">
            <id column="rid" property="rid"/>
            <result column="rname" property="rname"/>
        </association>
    </resultMap>
   <select id="queryUserAndRole" resultMap="userMap">
       select * from user u
        left join role r
        on u.rid = r.rid;
   </select>

UserMapper:
<resultMap type="user" id="userMap2">
        <id column="uid" property="uid"/>
        <result column="uname" property="uname"/>
        <!-- 將結果集數據封裝到對象中
            property:對象的屬性名稱
            column:外鍵
            javaType:對象的類型
         -->
        <association property="role" column="rid" javaType="role" 
            select="mapper.RoleMapper.selectRole">
        </association>
    </resultMap>
   <select id="queryUserAndRole2" resultMap="userMap2">
          select * from user
   </select>

RoleMapper
<select id="selectRole" resultType="role">
        select * from role where rid = #{rid}
</select>

延遲加載

1) 延遲加載:按需加載(懶加載),只加載主查詢,需要用到子查詢信息時才去查詢。

2) <collection><association>都具有延遲加載功能。但是默認關閉。

3) 需要打開延遲加載:

<settings>
    <!-- 延遲加載全局開關 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 3.4.1以上為false,否則為true -->
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

緩存

一級緩存

Mybatis中的一級緩存時默認開啟的。

在內存中一塊區域,以類似於map方式進行數據管理。

當用戶第一次查詢時,會根據sql,參數,rowbounds以及statement的id生成cacheKey,先從二級緩存中獲取數據,如果為空,將從一級緩存中根據生成key獲取value值,如果也為空,就從數據庫進行查詢,然後將key和查詢的結果放置到一級緩存中。

當用戶再次查詢時,仍舊生成cacheKey,通過key從一級緩存中獲取值,如果有值此時將直接返回不再查詢數據庫。

一級緩存是session級別的緩存。

如果執行增刪改會清空一級緩存。

二級緩存

在內存中一塊區域,以類似於map方式進行數據管理。

當用戶第一次查詢時,會根據sql,參數,rowbounds以及statement的id生成cacheKey,先從二級緩存中獲取數據,如果為空,將從一級緩存中根據生成key獲取value值,如果也為空,就從數據庫進行查詢,然後將key和查詢的結果放置到一級緩存中。

當用戶再次查詢時,仍舊生成cacheKey,通過key從一級緩存中獲取值,如果有值此時將直接返回不再查詢數據庫。

如果執行增刪改會清空二級緩存

二級緩存是跨session的緩存。

默認二級緩存關閉。

實體類必須序列化。

<cache>

//讀取配置文件轉換為流
        InputStream is = Resources.getResourceAsStream("Mybatis.xml");
        //創建ssf對象
        SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(is);
        
        SqlSession session = ssf.openSession(true);
        SqlSession session2 = ssf.openSession(true);
        SqlSession session3 = ssf.openSession(true);
        
        //根據mapper接口生成實現類對象
        BookMapper mapper = session.getMapper(BookMapper.class);
        BookMapper mapper2 = session2.getMapper(BookMapper.class);
        BookMapper mapper3 = session3.getMapper(BookMapper.class);
        
        System.out.println(mapper.queryAll());
        session.close();
        
        System.out.println(mapper2.queryAll());
        session2.close();
        
        System.out.println(mapper3.queryAll());
        session3.close();

Day2 Mybatis初識(二)