day3 - mybatis基本查詢映射配置&更新映射和緩存機制&查詢結(jié)果的封裝和高級映射&動態(tài)SQL

主要內(nèi)容
1. 應(yīng)用<select>元素實現(xiàn)數(shù)據(jù)查詢
2. <insert><update><delete>元素更新數(shù)據(jù)
3. 應(yīng)用<sql>元素實現(xiàn)重用,應(yīng)用緩存設(shè)置
4. 查詢返回結(jié)果的封裝處理
5. 動態(tài)SQL應(yīng)用

1. 應(yīng)用<select>元素實現(xiàn)數(shù)據(jù)查詢

select元素用來從數(shù)據(jù)庫中查詢數(shù)據(jù)結(jié)果,一個最簡單的select實現(xiàn)方式如下所示:


1.1 使用select元素實現(xiàn)數(shù)據(jù)查詢

1.1 <select>元素屬性說明

select元素屬性規(guī)范查詢中的動作。諸如,如何傳遞查詢參數(shù),映射返回結(jié)果,是否使用緩存,查詢超時限定等特性。

<select>常用的屬性

1.2 select常用的屬性

1.2 使用parameterType設(shè)置參數(shù)

  • parameterType是int, resultType是某個類的例子
    <select id="findStuByAge" resultType="stu" parameterType="int">
        <![CDATA[select * from student where age > #{age}]]>
    </select>

代碼實現(xiàn)

    public List<Student> findStuByAge(int age){
        return SqlSessionFactoryManager.getSqlSession().selectList("students.findStuByAge",age);
    }
  • parameterType是string, resultType是map的例子
    <select id="findStuByEmail" resultType="map" parameterType="string">
        <![CDATA[select * from student where email = #{email}]]>
    </select>

代碼實現(xiàn)

    public Map<String, Object> findStuByEmail(){
        String email = "123@163.com";
        return SqlSessionFactoryManager.getSqlSession().selectOne("students.findStuByEmail",email);
    }
  • parameterType是map, resultType是某個類的例子
    <select id="findStuByArgs" resultType="stu" parameterType="map">
        <![CDATA[select * from student where email <> #{email} and age > #{age}
        and birth > #{birth}
        ]]>
    </select>

代碼實現(xiàn)

    public List<Student> findStuByArgs(){
        String email = "123@163.com";
        int age = 18;
        String birth = "1900-01-01";
        Map<String, Object> map = new HashMap<>();
        map.put("email",email);
        map.put("age",age);
        map.put("birth",birth);
        return SqlSessionFactoryManager.getSqlSession()
                .selectList("students.findStuByArgs",map);
    }

2<insert><update><delete>元素更新數(shù)據(jù)

2.1 <insert><update>通用屬性

除了具有<select>等元素的通用屬性外,<insert>和<update>還具有以下相同常用屬性:


2.1 insert&update通用屬性

keyProperty和keyColumn相互對應(yīng)。

2.2 使用<insert>元素映射insert語句

保存一個department表的信息到數(shù)據(jù)庫中
mapper.xml中的內(nèi)容:

    <insert id="saveDepartment" parameterType="map" keyColumn="ID"
            keyProperty="id" statementType="PREPARED">
        <![CDATA[insert into department(id, name, code, newdate, descs)
            values(#{id},#{name},#{code},#{newdate},#{descs})]]>
    </insert>

代碼實現(xiàn):

    public int saveDepartment(Map<String, Object> map){
        System.out.println("執(zhí)行保存");
        //獲取sqlSession實例
        SqlSession sqlSession = SqlSessionFactoryManager.getSqlSession();
        int res = sqlSession.insert("deps.saveDepartment",map);
        sqlSession.commit();
        sqlSession.close();
        return res;
    }

2.3 使用<update>元素映射update語句

根據(jù)指定id更新數(shù)據(jù)庫的表
mapper.xml中的內(nèi)容:

    <update id="updateDepartmentById" parameterType="map" flushCache="true" statementType="PREPARED">
        <![CDATA[
            update department
            set descs = #{descs}, name = #{name}
            where id = #{id}]]>
    </update>

代碼實現(xiàn):

    /**
     * 實現(xiàn)按照部門id更新部門信息
     * @param map 部門map
     * @return
     */
    public int updateDepartmentById(Map<String, Object> map){
        System.out.println("執(zhí)行修改");
        //獲取sqlSession實例
        SqlSession sqlSession = SqlSessionFactoryManager.getSqlSession();
        int res = sqlSession.update("deps.updateDepartmentById",map);
        sqlSession.commit();
        sqlSession.close();
        return res;
    }

2.4 使用<delete>元素映射delete語句

根據(jù)給定的id刪除department的內(nèi)容
mapper.xml中的內(nèi)容:

    <delete id="removeDepById" parameterType="string" flushCache="true" statementType="PREPARED">

        <![CDATA[
            delete from department
            where id = #{id}]]>
    </delete>

代碼實現(xiàn):

    /**
     * 按照指定的部門id刪除此部門
     * @param depid 部門id
     * @return int
     */
    public int removeDepById(String depid){
        System.out.println("執(zhí)行刪除");
        //獲取sqlSession實例
        SqlSession sqlSession = SqlSessionFactoryManager.getSqlSession();
        int res = sqlSession.delete("deps.removeDepById", depid);
        sqlSession.commit();
        sqlSession.close();
        return res;
    }

3.應(yīng)用<sql>元素實現(xiàn)重用,應(yīng)用緩存設(shè)置

3.1 <sql>元素實現(xiàn)重用

//定義一個重復(fù)使用的sql語句塊

    <!--可重用的sql塊,可以被當(dāng)前映射中任何select, update及insert delete應(yīng)用-->
    <sql id="DEPCommons">
        id, name, code, newdate, descs </sql>

//其他語句中調(diào)用

    <!--使用include引用sql元素不能使用常量語義符號包圍, 否則無法進行解析-->
    <select id="queryDepList" resultType="dep" fetchSize="3">
        select <include refid = "DEPCommons"/> from department limit 0,3;
        <!--<![CDATA[select * from department limit 0,3;]]>-->
    </select>

3.2 應(yīng)用緩存設(shè)置

數(shù)據(jù)緩存可以增加數(shù)據(jù)的訪問操作效率,myBatis提供了設(shè)置sql的緩存策略和在sql映射中引用緩存策略。
myBatis使用cache元素在sql映射中設(shè)置緩存策略及使用ref-cache引用緩存策略。

3.2.1 myBatis緩存機制
3.1 myBatis緩存機制

myBatis一級緩存
一級緩存中每個SqlSession獨享緩存數(shù)據(jù)

導(dǎo)致一級緩存查詢失敗的因素

3.2 myBatis一級緩存查詢失敗的因素

myBatis二級緩存
二級緩存中每個mapper中SqlSession會共享緩存數(shù)據(jù)

設(shè)置sql緩存

3.3.1 設(shè)置sql緩存

mybatis提供的幾種緩存策略類型:

3.3.1 mybatis提供的幾種緩存策略類型

應(yīng)用緩存

cache-ref元素實現(xiàn)從一個mapper中引用當(dāng)前的mapper中的緩存策略并應(yīng)用。


3.3.2 應(yīng)用緩存

導(dǎo)致二級緩存查詢失敗的原因

3.3.3 導(dǎo)致二級緩存查詢失敗的原因

二級緩存的缺陷

3.4 二級緩存的缺陷.png

緩存策略

使用第三方專業(yè)緩存工具代替myBatis二級緩存[Ehcache, Redis]

4. 查詢返回結(jié)果的封裝處理

myBatis通常在映射<select>元素執(zhí)行sql使用returnType設(shè)置返回結(jié)果類型,有時需要對查詢返回結(jié)果進行特殊處理;<select>元素提供了returnMap屬性為查詢返回結(jié)果進行處理的更靈活方式。
returnMap屬性是對sql映射中某個returnMap元素的引用,而returnMap元素的定義決定了如何處理查詢返回結(jié)果。

4.1 resultMap基本映射應(yīng)用

Q: 數(shù)據(jù)庫表student列名稱和Student.Java類型屬性名稱不匹配,導(dǎo)致無法直接使用returnType指定為Student Java類型
S: 使用resultMap元素自定義返回結(jié)果的處理并映射記錄行為Student Java類型,使用resultMap屬性設(shè)置引用resultMap元素。
E:

    <!--使用列標(biāo)簽與實體bean屬性保持一致達到自動映射的目的-->
    <select id="queryProductList" resultType="pro" useCache="true" statementType="PREPARED">
        <![CDATA[
        select id proId,code proCode,name proName,price proPrice,quality proQuantity,descs proDescs from product;
        ]]>
    </select>

    <resultMap id="ProMapping" type="pro" autoMapping="false">
        <id column="ID" property="proId" javaType="string" jdbcType="VARCHAR"/>
        <result column="CODE" property="proCode" javaType="string" jdbcType="VARCHAR"/>
        <result column="NAME" property="proName" javaType="string" jdbcType="VARCHAR"/>
        <result column="PRICE" property="proPrice" javaType="double" jdbcType="DOUBLE"/>
        <result column="QUALITY" property="proQuantity" javaType="integer" jdbcType="INTEGER"/>
        <result column="DESCS" property="proDescs" javaType="string" jdbcType="VARCHAR"/>
    </resultMap>

resultMap和resultType封裝過程中只會有一個存在

4.2 resultMap元素說明

4.2.1 resultMap屬性
4.2.1 resultMap元素屬性
4.2.2 resultMap子元素
4.2.2 resultMap元素子元素
  • 高級復(fù)雜結(jié)果關(guān)聯(lián)映射(一對多):collection的使用

使用resultMap元素映射復(fù)雜的一對多關(guān)聯(lián)

    <select id="structTreeMap" resultMap="dep_emp_sal_map" statementType="PREPARED">
        <![CDATA[
        select d.id did, d.name dname, e.id eid, e.name ename,
               s.id sid, s.should, s.actual, s.mapYearMon
        from department d inner join emp e on d.id = e.DEPID
                          inner join salary s on e.id = s.empId;
        ]]>
    </select>

    <!--使用resultMap元素映射復(fù)雜的一對多關(guān)聯(lián)-->
    <resultMap id="dep_emp_sal_map" type="dep" autoMapping="false">
        <id column="did" property="id" javaType="string" jdbcType="VARCHAR"/>
        <result column="dname" property="name" javaType="string" jdbcType="VARCHAR"/>
        <collection property="employeeList" autoMapping="false" ofType="emp">
            <id column="eid" property="id" javaType="string" jdbcType="VARCHAR"/>
            <result column="ename" property="name" javaType="string" jdbcType="VARCHAR"/>
            <collection property="salaryList" ofType="sal" autoMapping="false">
                <id column="sid" property="id" javaType="string" jdbcType="VARCHAR"/>
                <result column="should" property="should" javaType="integer" jdbcType="INTEGER"/>
                <result column="actual" property="actual" javaType="integer" jdbcType="INTEGER"/>
                <result column="mapYearMon" property="mapYearMon" javaType="date" jdbcType="DATE"/>
            </collection>
        </collection>
    </resultMap>

使用resultMap實現(xiàn)關(guān)聯(lián)映射,實體數(shù)據(jù)使用map進行封裝,避免定義更多的VO類

    <!--將一對多關(guān)聯(lián)數(shù)據(jù)實體映射為map-->
    <select id="structTreeMap2" resultMap="depAndempAndsalAndmap" statementType="PREPARED">
        <![CDATA[
        select d.id did, d.name dname, e.id eid, e.name ename,
               s.id sid, s.should, s.actual, s.mapYearMon
        from department d inner join emp e on d.id = e.DEPID
                          inner join salary s on e.id = s.empId;
        ]]>
    </select>

    <!--使用resultMap元素映射復(fù)雜的一對多關(guān)聯(lián),實體數(shù)據(jù)使用Map進行封裝,減少使用實體類-->
    <resultMap id="depAndempAndsalAndmap" type="treeMap" autoMapping="false">
        <id column="did" property="id" javaType="string" jdbcType="VARCHAR"/>
        <result column="dname" property="name" javaType="string" jdbcType="VARCHAR"/>
        <collection property="employeeList" autoMapping="false" ofType="treeMap">
            <id column="eid" property="id" javaType="string" jdbcType="VARCHAR"/>
            <result column="ename" property="name" javaType="string" jdbcType="VARCHAR"/>
            <collection property="salaryList" ofType="treeMap" autoMapping="false">
                <id column="sid" property="id" javaType="string" jdbcType="VARCHAR"/>
                <result column="should" property="should" javaType="integer" jdbcType="INTEGER"/>
                <result column="actual" property="actual" javaType="integer" jdbcType="INTEGER"/>
                <result column="mapYearMon" property="mapYearMon" javaType="date" jdbcType="DATE"/>
            </collection>
        </collection>
    </resultMap>

提示: id元素是嵌套映射中非常重要的角色,通常必須要映射它,如果不使用id作為標(biāo)識結(jié)果,性能會有很大損耗。

  • 高級復(fù)雜結(jié)果關(guān)聯(lián)映射(一對一): myBatis提供resultMap元素的association子元素實現(xiàn)一對一關(guān)聯(lián)映射
  1. 使用association元素的select屬性指向一條sql查詢語句描述如何封裝結(jié)果
  2. 使用association元素的resultMap屬性指向association元素描述如何封裝結(jié)果(效率高)

使用association元素的select屬性指向一條sql查詢語句描述如何封裝結(jié)果

    <!-- 查詢員工 -->
    <select id="findEmpAndDoc" resultMap="findEmpMap" statementType="PREPARED">
        select  * from emp 
    </select>

    <resultMap id="findEmpMap" type="emp" autoMapping="false">
        <id column="id" javaType="string" jdbcType="VARCHAR" property="id"/>
        <result column="name" javaType="string" jdbcType="VARCHAR" property="name"/>
        <!--column指定應(yīng)該如何進行映射-->
        <association property="doc" autoMapping="false" column="id" javaType="doc"
                     select="findDocMap"/>
    </resultMap>

    <!--查詢檔案-->
    <select id="findDocMap" resultType="doc" parameterType="string" statementType="PREPARED">
        select  * from document where empid = #{empid};
    </select>

使用association元素的resultMap屬性指向association元素描述如何封裝結(jié)果(效率高, 僅僅去數(shù)據(jù)庫之中查詢一次)

    <!-- 查詢員工對象和對應(yīng)的檔案對象集合 -->
    <select id="findEmployeeAndDocument" resultMap="findEmpMap2" statementType="PREPARED">
        select e.id eid,e.name, d.id did, d.number from emp e inner join document d on
            e.id = d.empid;
    </select>

    <!--映射員工查詢返回結(jié)果-->
    <resultMap id="findEmpMap2" type="emp" autoMapping="false">
        <id column="eid" javaType="string" jdbcType="VARCHAR" property="id"/>
        <result column="name" javaType="string" jdbcType="VARCHAR" property="name"/>
        <association property="doc" javaType="doc" autoMapping="false"
                     resultMap="docMap" column="empid"/>
    </resultMap>

    <!--映射用戶檔案查詢返回結(jié)果-->
    <resultMap id="docMap" type="doc" autoMapping="false">
        <id column="did" javaType="string" jdbcType="VARCHAR" property="id"/>
        <result column="number" javaType="string" jdbcType="VARCHAR" property="number"/>
    </resultMap>

5. 動態(tài)SQL應(yīng)用

5.1 動態(tài)SQL應(yīng)用

5.1 if

if元素是構(gòu)成動態(tài)SQL語句非常重要的和使用比較頻繁的元素,它表示執(zhí)行一個邏輯判斷,如果為true則執(zhí)行if元素之內(nèi)的內(nèi)容,if元素有唯一的一個test屬性用來接收一個布爾表達式,if經(jīng)常用來組織where語句的連接生成

    <!--動態(tài)sql if的使用-->
    <select id="queryEmpListByGender" parameterType="int" resultType="emp" statementType="PREPARED">
        select id,name,birth,phone from emp
        <if test="'gender' != null">
            where gender = #{gender}
        </if>
    </select>

    <!--動態(tài)sql if的使用2-->
    <select id="queryEmpListByMap" parameterType="map" resultType="emp" statementType="PREPARED">
        select id,name,birth,phone from emp
        <if test="gender != null">
            where gender = #{gender}
        </if>
        <if test="name != null">
            and name like concat(#{name},"%")
            /*and name like '${name}%'*/
        </if>

    </select>

5.2 choose, when, otherwise

choose when otherwise類似于Java中的switch分支語句

    <!--choose when otherwise 動態(tài)sql-->
    <select id="queryEmpListByMap2" parameterType="map" resultType="emp" statementType="PREPARED">
        select id,name,birth,phone from emp where 1 = 1
        <choose>
            <when test="gender != null">and gender = #{gender}</when>
            <when test="name != null">and name not like '${name}%'</when>
            <when test="start != null and ends != null">
                and birth between #{start} and #{ends}
            </when>
            <otherwise>
                <if test="id != null">
                    and id = #{id}
                </if>
            </otherwise>
        </choose>
    </select>

5.3 trim, where, set

5.3.1 where

where元素用來代替用戶手寫的where sql關(guān)鍵字,它基本可以解決沒有給定條件時而出現(xiàn)錯誤sql語法
where元素能夠知道如果它包含的標(biāo)簽中有返回值的話,它就插入一個where, 如果標(biāo)簽返回的內(nèi)容以AND或OR開頭的,則它會剔除掉

示例:

    <!--動態(tài)sql 使用where元素代替手寫where 避免手寫where出錯-->
    <select id="queryEmpListByMap3" parameterType="map" resultType="emp" statementType="PREPARED">
        select id,name,birth,phone from emp
        <where>
            <choose>
                <when test="gender != null">and gender = #{gender}</when>
                <when test="name != null">and name not like '${name}%'</when>
                <when test="start != null and ends != null">
                    and birth between #{start} and #{ends}
                </when>
                <otherwise>
                    <if test="id != null">
                        and id = #{id}
                    </if>
                </otherwise>
            </choose>
        </where>
    </select>
5.3.2 trim

trim元素可以用來代替where set等元素設(shè)置自定義動態(tài)sql語句,它有三個屬性:
prefix: 指定前綴
suffix: 指定后綴
prefixOverrides: 設(shè)置分隔符(空格也屬于分隔符之列)

示例:

    <!--動態(tài)sql trim 元素替代 where-->
    <select id="queryEmpListByMap4" parameterType="map" resultType="emp" statementType="PREPARED">
        select id,name,birth,phone from emp
        <trim prefix="where" prefixOverrides="and|or">
            <if test="gender != null">gender = #{gender}</if>
            <if test="name != null">and name like concat(#{name},'%')</if>
        </trim>
    </select>
5.3.3 set

set元素用來實現(xiàn)update語句的更新,它取代set關(guān)鍵字設(shè)置更新列信息。

示例:

    <!--使用set元素代替手寫set更新sql語句關(guān)鍵字-->
    <update id="modifyEmployee" parameterType="emp" statementType="PREPARED">
        update emp
        <set>
            <if test="name != null">name = #{name},</if>
            <if test="gender != null">gender = #{gender},</if>
            <if test="address != null">address = #{address}</if>
        </set>
        where id = #{id}
    </update>

5.4 foreach

foreach是一個迭代功能的動態(tài)sql元素,通常在條件包含in或not in時使用其填充條件。
MyBatis會自動將有序集合及數(shù)組包裝成一個Map處理,并使用它的名稱作為key。List實例將使用"list"作為鍵,數(shù)組實例以"array"作為鍵。

示例:

    <!--使用foreach迭代參數(shù)集合-->
    <select id="queryEmpListForAddress" resultType="emp" statementType="PREPARED">
        select * from emp where address in
            <foreach collection="list" item="ele" index="index" separator=","
            open="(" close=")">
                #{ele}
            </foreach>
    </select>

    <!--使用foreach迭代參數(shù)集合(多參數(shù))-->
    <select id="queryEmpListForAddress2" resultType="emp" parameterType="map" statementType="PREPARED">
        select * from emp where
        birth between #{startTime} and #{endTime} and address in 
        <foreach collection="addList" index="index" item="ele" separator=","
                 open="(" close=")">
            #{ele}
        </foreach>
    </select>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容