1. 程式人生 > >MyBatis學習總結(02)

MyBatis學習總結(02)

今日大綱

  • 動態sql
  • 快取
  • 介面繫結
  • 或者叫動態代理
  • ResultType

    1、動態sql
    相當於條件查詢,在程式碼中使用if語句來拼裝sql語句,它會造成資源浪費,而且,不易於維護。If、switch語句是Java程式碼之罪。
    在寫sql語句的時候,直接進行拼裝。
    特殊字元轉義

&lt;    <   小於
&gt;    >   大於
&amp;   &   和號
&apos;  '   省略號
&quot;  "   引號

< if>標籤:
標籤,相當於程式碼中的if(){}else{}
它幫我們做資料判斷

    <select id="getUsers" resultType="user">
        select * from t_user 
            where 1=1 
            <if test="name != null and name !='' ">
                and name = #{name}
            </if>
            <if test="pwd !=null and pwd !='' ">
                and pwd =#{pwd}
</if> <if test="age &gt; 23"> and name ='王思聰' </if> </select>

< where>標籤
標籤就想到與sql語句中where條件,當where標籤內的if判斷條件執行,才執行where標籤,如果if不執行,where也不執行,所以 1=1 就省略掉了。
Where標籤,會自動判斷sql語句,如果第一個and開始的,就省略掉,一般情況下,在if判斷條件中都加and關鍵字。

    <select id="getUsers" resultType="user">
        select * from t_user 
            <where> 
                <if test="name != null and name !='' ">
                    and name = #{name}
                </if>
                <if test="pwd !=null and pwd !='' ">
                    and pwd =#{pwd}
                </if>
                <if test="age &gt; 23">
                    and name ='王思聰'
                </if>
            </where>
    </select>

< choose>標籤
標籤就相當於程式碼中switch,標籤:當條件滿足的時候執行when標籤內容,當所有的when標籤內容不滿足時,執行預設標籤中的內容。

    <select id="getUsers1" resultType="user">
        select * from t_user 
            <where> 
                <choose>
                    <when test="name != null and name !=''">
                        and name= #{name}
                    </when>

                    <otherwise>
                        and age &gt; 23
                    </otherwise>
                </choose>
            </where>
    </select>

< sql >和< include >
標籤:用於定義sql語句
標籤:用於引用標籤定義的sql語句,這個引用可以在sql語句的任何位置

    <sql id="select">
         id,name,pwd
    </sql>
    <sql id="from">
        from t_user
    </sql>
    <select id="getUsers2" resultType="user">
        <!-- select * from t_user t where t.id in(select id from t_user1 where name =?)
        sql:語句的拆分,一般不用於單表操作,一般用於多表操作
        include:引用sql語句,可以在任何位置
        -->
        select 
        <include refid="select"/>
        <include refid="from"/>
    </select>

< bind>標籤

標籤用於給引數追加資料,隨便新增

    <select id="getUserByName" resultType="user">
        <!-- bind:給引數追加內容,寫的方式 '%'+name+'%'
            現在講引數進行追加,然後再進行資料判斷
            如果引數為空:會報錯
        -->
        <bind name="name" value="name+'123'"/>
        select * from t_user 
            <where>
                <if test="name != null and name!='' ">
                    name like #{name}
                </if>
            </where>
    </select>

< set>標籤
標籤主要用於update語句。相對於update語句中set關鍵字,它會自動消除多餘的”,”

    <!--  set 標籤應用-->
    <update id="updateUser">
        <!-- update t_user set name=? and pwd=? where id =? -->
        update t_user 
            <set>
                <if test="name != null and name !=''">
                    name = #{name},
                </if>
                <if test="pwd != null and pwd !='' ">
                    pwd = #{pwd}
                </if>
            </set>
            <where>
                id=#{id}
            </where>

    </update>

< foreach>標籤
< foreach>標籤,主要用迴圈遍歷,
Select * from t_user where id in(name),name就可以使用foreach

<!-- foreach應用 -->
    <select id="findUsers" resultType="user">
        select * from t_user 
            <where>
                id in
                    <!-- 
                        collection:集合物件
                        open:指的是以什麼開始
                        close:指的是以什麼結尾,與open成對出現
                        separator:指的資料以什麼進行分割
                        item:指的遍歷的資料項
                        mybatis的會自動給string資料新增'',不需要我們手動新增
                     -->
                    <foreach collection="list" open="(" separator="," close=")" item="ids">
                        #{ids}
                    </foreach>
            </where>
    </select>
    <select id="findUsersByName" resultType="user">
        select * from t_user
            <where>
                name in 
                <foreach collection="list" open="(" separator="," close=")" item="names">
                    #{names}
                </foreach>
            </where>
    </select>

< trim>標籤
< trim>標籤在mybatis裡面是去除and|or|,

    <select id="queryUsers" resultType="user">
        select * from t_user 
            <!--
                prefix:字首
                suffix:字尾
                prefixOverrides:字首結束,去掉and|or關鍵字
                suffixOverrides:字尾結束,去掉and|or關鍵字
                <where><set>本身自帶了去掉and|or|,的功能
              -->
            <trim prefix="WHERE"  prefixOverrides="AND|OR">
                <if test="name != null and name !='' ">
                    and name = #{name}
                </if>
                <if test="pwd !=null and pwd !='' ">
                    and pwd =#{pwd}
                </if>
                <if test="age &gt; 23">
                    and name ='王思聰'
                </if>
            </trim>
    </select>

簡單型別傳遞引數

    <!-- 簡單型別引數傳遞:現在一次傳遞多個引數 
        如果是多個簡單型別的引數使用[param引數下標從1開始]
        在佔位符中的name值是:[param引數下標從1開始],不是引數名稱
    -->
    <select id="findUsersByParam" resultType="user">
        select * from t_user 
            <where> 
                <if test="param1 != null and param1 !='' ">
                    and name = #{param1}
                </if>
                <if test="param2 !=null and param2 !='' ">
                    and pwd =#{param2}
                </if>
                <if test="param3 &gt; 23">
                    and name ='王思聰'
                </if>
            </where>
    </select>   
    <!-- 簡單型別引數傳遞:一次傳遞一個引數 
        作為判斷條件的時候:使用_parameter來進行判斷
        佔位符中應用還是引數名稱
    -->
    <select id="findUsersByParam1" resultType="user">
        select * from t_user
            <where>
                <if test="_parameter != null and _parameter != ''">
                    name = #{name}
                </if>
            </where>
    </select>

介面類:

public interface UserMapper {

    List<User> getUsers(Map<String, Object> map);

    List<User> getUsers1(User user);

    List<User> getUsers2();

    List<User> getUserByName(User user);

    int updateUser(User user);

    List<User> findUsers(List<Integer> ids);

    List<User> findUsersByName(List<String> names);

    List<User> queryUsers(User user);

    List<User> findUsersByParam(String name,String pwd, Integer age);

    List<User> findUsersByParam1(String name);
}

測試類:

package com.bjsxt.test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.bjsxt.mapper.UserMapper;
import com.bjsxt.pojo.User;
import com.bjsxt.utils.MybatisUtil;

public class TestMybatis {

    private SqlSession session ;

    @Before
    public void getSession(){
        session = MybatisUtil.getSession();
    }

    @After
    public void closeSession(){
        MybatisUtil.closeSession();
    }
    /**
     * 
     * @Description:   foreach應用
     * @author mao
     * @date   2017年10月11日
     */
    @Test
    public void findUsers(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<Integer> ids = new ArrayList<>();
        ids.add(2);
        ids.add(3);
        ids.add(6);
        ids.add(7);
        List<User> findUsers = mapper.findUsers(ids);
        for (User user : findUsers) {
            System.out.println(user);
        }
    }

    @Test
    public void findUsersByName(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<String> names = new ArrayList<>();
        names.add("王二麻子");
        names.add("張三丰");
        List<User> findUsersByName = mapper.findUsersByName(names);
        for (User user : findUsersByName) {
            System.out.println(user);
        }
    }

    @Test
    public void queryUsers(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
        user.setName("王二麻子");
        List<User> queryUsers = mapper.queryUsers(user);
        for (User user2 : queryUsers) {
            System.out.println(user2);
        }
    }
    /**
     * 
     * @Description:   簡單型別引數傳遞:多個簡單型別
     * @author mao
     * @date   2017年10月11日
     */
    @Test
    public void findUsersByParam(){

        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> findUsersByParam = mapper.findUsersByParam("王二麻子", "12345", 22);
        for (User user : findUsersByParam) {
            System.out.println(user);
        }

    }

    @Test
    public void findUsersByParam1(){

        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> findUsersByParam1 = mapper.findUsersByParam1("王二麻子");
        for (User user : findUsersByParam1) {
            System.out.println(user);
        }

    }

    @Test
    public void getUsers(){
        /**
         * 模糊查詢
         * 字元拼接查詢
         * 使用程式碼進行模糊查詢,它效率很低
         * if(){}else{}稱之為程式碼之罪
         * mybatis提供了動態sql,可以在sql中直接使用一些判斷條件
         */
        StringBuffer sb = new StringBuffer();
        sb.append("select * from t_user where 1=1 ");
        User user = new User();
        if(user.getName() !=null){
            sb.append(" and name= XXX");
        }
        if(user.getPwd() != null){
            sb.append(" and pwd=XXX");
        }

        //執行sql
    }

    @Test
    public void getUserDymic(){

        UserMapper mapper = session.getMapper(UserMapper.class);
        Map<String, Object> map = new HashMap<>();
        map.put("name", "王二麻子");
//      map.put("pwd", "12345");
//      map.put("age", 26);
        List<User> users = mapper.getUsers(map);
        for (User user : users) {
            System.out.println(user);
        }

    }
    @Test
    public void getUsers1(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
        //user.setName("王二麻子");
        List<User> users1 = mapper.getUsers1(user);
        for (User user2 : users1) {
            System.out.println(user2);
        }
    }

    @Test
    public void getUsers3(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> users2 = mapper.getUsers2();
        for (User user : users2) {
            System.out.println(user);
        }
    }

    @Test
    public void getUserByName(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
        user.setName("張");
        List<User> userByName = mapper.getUserByName(user);
        for (User user2 : userByName) {
            System.out.println(user2);
        }
    }

    @Test
    public void updateUser(){

        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
        user.setName("張666");
        //user.setPwd("456");
        user.setId(3);
        int updateUser = mapper.updateUser(user);
        session.commit();
        System.out.println(updateUser);

    }
}

Sql拼接:
1.Java程式碼
2.Mybatis提供的動態sql
3.不使用Java程式碼和mybatis提供的動態sql:主要用報表
報表:經過封裝後,還是jsp或者html,直接操作資料庫,在報表工具中直接寫的是sql語句。

    <!-- 不使用Java程式碼  和 mybatis的標籤拼接sql查詢資料庫資料  -->
    <select id="getUsersByParams" resultType="user">

        select * from t_user 
            where 
                (#{name} is null or name= #{name}) 
                and (#{pwd} is null or pwd = #{pwd})

    </select>

測試:

    public void getUsers6(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
        user.setName("王二麻子");
        List<User> usersByParams = mapper.getUsersByParams(user);
        for (User user2 : usersByParams) {
            System.out.println(user2);
        }
    }

快取:
就是將資料放到記憶體中,電商專案,它的很多資料都是放在快取中的。提高查詢效率。但是mybatis的快取做的不好,有大量資料冗餘。
一級快取
一級快取:SqlSession,預設開啟的,直接使用。
查詢一條資料,又查詢同樣的一條資料,執行sql語句,查詢第一條資料的時候,已經將資料放到一級快取裡面,在Sqlsession 沒有關閉的情況下,查詢同樣的一條資料是從是快取獲取,不執行sql語句。
是依據 對映檔案中標籤中id屬性值進行快取(statementid進行快取的)

    @Test
    public void getUserById(){

        UserMapper mapper = session.getMapper(UserMapper.class);
        Map<String, Object> map = new HashMap<>();
        map.put("id", 3);
        User userById = mapper.getUserById(map);
        System.out.println(userById);

        Map<String, Object> map1 = new HashMap<>();
        map1.put("id", 3);
        User userById1 = mapper.getUserById2(map1);
        System.out.println(userById1);

    }

配置檔案:

    <select id="getUserById" resultType="user">
        select * from t_user where id = #{id}
    </select>
    <select id="getUserById2" resultType="user">
        select * from t_user where id = #{id}
    </select>   

二級快取
二級快取:SqlSessionFactory,開啟需要在對映檔案中進行配置
MyBatis 包含一個非常強大的查詢快取特性,它可以非常方便地配置和定製。MyBatis 3 中的快取實現的很多改進都已經實現了,使得它更加強大而且易於配置。
預設情況下是沒有開啟快取的,除了區域性的 session 快取,可以增強變現而且處理迴圈依賴也是必須的。要開啟二級快取,你需要在你的 SQL 對映檔案中新增一行:
對映語句檔案中的所有 select 語句將會被快取。
對映語句檔案中的所有 insert,update 和 delete 語句會重新整理快取。
快取會使用 Least Recently Used(LRU,最近最少使用的)演算法來收回。
根據時間表(比如 no Flush Interval,沒有重新整理間隔), 快取不會以任何時間順序 來重新整理。
快取會儲存列表集合或物件(無論查詢方法返回什麼)的 1024 個引用。
快取會被視為是 read/write(可讀/可寫)的快取,意味著物件檢索不是共享的,而且可以安全地被呼叫者修改,而不干擾其他呼叫者或執行緒所做的潛在修改。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  <!-- 
    namespace:相當於包的概念
        要保證在一個對映檔案中,保證statementid為唯一
   -->
  <mapper namespace="com.bjsxt.mapper.UserMapper">

    <!-- 
        <if>標籤:相當於java程式碼中的if語句
        if:簡單型別傳遞
        if標籤:Java程式碼中的if判斷條件 使用的是 && || 
            在if標籤中使用的是 and
     -->
    <select id="getUsers" resultType="user">

        select * from t_user 
            where 1=1 
            <if test="_parameter != null and _parameter !='' ">
                and name like #{name}
            </if>
    </select>
    <!-- if語句的:物件和集合型別傳遞 -->
    <select id="getUsers1" resultType="user">

        select * from t_user 
            where 1=1 
            <if test="name != null and name !='' ">
                and name like #{name}
            </if>
    </select>
    <!-- if語句:多個判斷條件, 
        where標籤:去掉sql語句的where關鍵字
                mybatis會自動的進行判斷,再進行刪除
            它會自動判斷,它內部的語句第一個 關鍵字是否是and 如果是,自動的去掉
            所以,一般使用where標籤,它內部的所有if判斷條件都新增and關鍵字
    -->
     <select id="getUsers2" resultType="user">
        select * from t_user 
            <where>
                <if test="name != null and name !='' ">
                    and name like #{name}
                </if>
                <if test="age &gt; 33">
                    and age &gt; 33
                </if>
            </where>
    </select>
    <!-- 
        choose標籤:就相當於Java程式碼中的switch語句,當一個條件成立的話,後面的所有判斷條件都不執行
        switch(falg){
            case falg:xxx; ==> when
            case falg:xxx; ==> when
            default: ==》otherwise
                XXX;
        }
     -->
     <select id="getUsers3" resultType="user">
        select * from t_user
            <where>
                <choose>
                    <when test="name != null and name != ''">
                        and name like #{name}
                    </when>
                    <when test="age &gt; 33">
                        and age &gt; 33
                    </when>
                    <otherwise>
                        and pwd ='zhangsanf'
                    </otherwise>
                </choose>
            </where>
     </select>
     <!-- 
        bind標籤:相當於字串拼接,它可以在引數的前後新增內容
        name屬性值:引數名稱
        value屬性值:對引數進行改造
      -->
      <select id="getUsers4" resultType="user">
        <bind name="name" value="'%'+name+'%'"/>
        <!-- 
            先進行資料新增,再進行資料判斷,
            引數為空,會報錯,bind報錯
         -->
        select * from t_user
            <where>
                <if test="name != null and name != ''">
                    and name like #{name}
                </if>
            </where>
      </select>
      <!-- 
        set標籤:它就相當於 update語句set關鍵字,set關鍵字對自動去掉,號
       -->
       <update id="updateUser">
            <!-- update t_user set name=#{name} , age =#{age} where id=#{id} -->
            update t_user 
                <set>
                    <if test="name != null and name != ''">
                        name=#{name},
                    </if>
                    <if test="age != null">
                        age=#{age},
                    </if>
                </set>
                <where>
                    <if test="id != null">
                        id=#{id}
                    </if>
                </where>
       </update>
       <!-- foreach標籤:相當於Java程式碼中的for迴圈
            需求:查詢該集合中主鍵的值
            collection:指的是集合物件,對應的傳遞過來的引數集合型別
            open:以什麼開始
            separator:資料以什麼分割
            close:以什麼結尾,與open成單出現
            item:引數名稱,對應傳遞過來的引數名稱
            如果遍歷的是string型別,mybatis會自動的新增''號,不需要我們手動新增
        -->
       <select id="getUsers5" resultType="user">
            select * from t_user
                <where>
                    id in
                    <foreach collection="list" open="(" separator="," close=")" item="ids">
                        #{ids}
                    </foreach>
                </where>
       </select>
       <select id="getUsers6" resultType="user">
            select * from t_user
                <where>
                    name in
                    <foreach collection="list" open="(" separator="," close=")" item="names">
                        #{names}
                    </foreach>
                </where>
       </select>      
       <!-- 
         trim標籤:
        -->
       <select id="getUsers7" resultType="user">
            select * from t_user 
                <!-- 
                prefix:字首
                prefixOverrides:字首以什麼結束
                suffix:後置
                suffixOverrides:後置以什麼結束
                 -->
                <trim prefix="WHERE" prefixOverrides="AND|OR">
                    <if test="name != null and name != ''">
                        and name like #{name}
                    </if>
                    <if test="age &gt; 33">
                        and age &gt; 33
                    </if>
                </trim>
       </select> 

       <!-- 
            <sql>標籤:在外部定義sql語句
            <include>標籤:在內部引用sql語句
            可以拼裝成一個完成的sql語句,
            一般當sql語句量很大得時候,進行使用
        -->
       <sql id="select">
            select id,name,pwd,age 
       </sql>
       <sql id="from"> 
            from  t_user
       </sql>
       <select id="getUser8" resultType="user">
            <include refid="select"/>
            <include refid="from"/>
       </select>

       <update id="updateUser3">
        update t_user set 
            name = #{0},age=#{1} 
            where id= #{2}
       </update>

  </mapper>

介面:

public interface UserMapper {

     List<User> getUsers(String name);

     List<User> getUsers1(User User);

     List<User> getUsers2(Map<String, Object> map);

     List<User> getUsers3(Map<String, Object> map);

     int updateUser(Map<String, Object> map);

     int updateUser3(String name,Integer age,Integer id);

}

實現類:

    /**
     * 
     * @Description:介面代理   
     * @author mao
     * @date   2017年10月30日
     */
    @Test
    public void getUsers(){
        //IUserDao userDao = new UserDaoImpl();
        /**
         * mybatis的通過getMapper來實現自動建立mapper介面的實現類
         * mapper.getUsers==》mybatis的session.selectList();
         */
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> users = mapper.getUsers("%張%");
//      List<User> users = session.selectList("getUsers","%張%");
        for (User user : users) {
            System.out.println(user);
        }

    }
    /**
     * 
     * @Description:   
     * @author mao
     * @date   2017年10月30日
     */
    @Test
    public void getUsers1(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
        user.setName("%張%");
        List<User> users1 = mapper.getUsers1(user);
        for (User user2 : users1) {
            System.out.println(user2);
        }
    }
    /**
     * 
     * @Description:介面實現修改   
     * @author mao
     * @date   2017年10月30日
     */
    @Test
    public void updataUser(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        Map<String, Object> map = new HashMap<>();
        map.put("name", "陳二狗");
        map.put("age", 33);
        map.put("id", 100);
        int updateUser = mapper.updateUser(map);
        System.out.println(updateUser);
        session.commit();
    }

    /**
     * 
     * @Description:傳遞多個簡單型別引數   
     * 在statement中接收引數使用:引數的下標或者param1
     * 引數下邊從0開始
     * param[args] :[args]使用1開始;例如:param1
     * @author mao
     * @date   2017年10月30日
     */
    @Test
    public void updateUser1(){

        UserMapper mapper = session.getMapper(UserMapper.class);
        int updateUser3 = mapper.updateUser3("田876", 33, 100);
        System.out.println(updateUser3);
        session.commit();

    }

    /**
     * 
     */
    @Test
    public void getUsers2(){

        List<User> selectList = session.selectList("com.bjsxt.mapper.UserMapper.getUsers","%張%");
        for (User user : selectList) {
            System.out.println(user);
        }

    }

}

ResultType
對映檔案中的statement中的resultType;
resultType:物件型別、簡單型別、集合型別
配置檔案:

  <!-- 
    namespace:相當於包的概念
        要保證在一個對映檔案中,保證statementid為唯一
   -->
  <mapper namespace="com.bjsxt.mapper.UserMapper">

    <select id="getUsers" resultType="user">
        select * from t_user
    </select>
    <!--resultType返回簡單型別 -->
    <select id="getUsers1" resultType="int">
        select id,name,pwd from t_user 
    </select>   
    <!--resultType返回集合型別 -->
    <select id="getUsers2" resultType="map">
        select id,name,pwd from t_user where name like #{_parameter}
    </select> 

  </mapper>

介面:

public interface UserMapper {

     List<User> getUsers();

     List<Integer> getUsers1();

     List<Map<Object, Object>> getUsers2(String name);
}

實現類:

    /**
     * 
     * @Description:resultType返回值為物件型別   
     * @author mao
     * @date   2017年10月30日
     */
    @Test
    public void getUsers(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> users = mapper.getUsers();
        for (User user : users) {
            System.out.println(user);
        }

    }
    /**
     * 
     * @Description:resultType返回簡單型別
     * 1.在statement中的resultType中設定返回值型別
     * 2.在sql語句中 ,如果查詢欄位有多個,要保證第一個欄位與返回值型別一致  
     * @author mao
     * @date   2017年10月30日
     */
    @Test
    public void getUsers1(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<Integer> users1 = mapper.getUsers1();
        for (Integer integer : users1) {
            System.out.println(integer);
        }
    }
    /**
     * 
     * @Description:resultType返回map集合型別
     * 1.介面中定義的方法返回值是Map集合   
     * @author mao
     * @date   2017年10月30日
     */
    @Test
    public void getUsers2(){

        UserMapper mapper = session.getMapper(UserMapper.class);
        List<Map<Object, Object>> users2 = mapper.getUsers2("%張%");
        for (Map<Object, Object> map : users2) {
            System.out.println(map);
        }

    }