1. 程式人生 > >【Mybatis】(六)動態SQL

【Mybatis】(六)動態SQL

【Mybatis】(一)第一個mybatis例項中已經建立了資料庫和基本的執行環境,接下來將介紹Mybatis動態SQL

1、定義EmployeeMapperDynamicSQL介面

package com.lhk.mybatis.dao;
import com.lhk.mybatis.bean.Employee;
import org.apache.ibatis.annotations.Param;
import java.util.List;

/**
 * @author lhk
 * @create 2018-09-16 20:21
 */
public interface EmployeeMapperDynamicSQL {

    // 查詢員工,要求攜帶了哪個欄位查詢欄位就帶上這個欄位的值,測試where
    public List<Employee> getEmpByConditionIf(Employee employee);

    // 查詢員工,測試Trim
    public List<Employee> getEmpByConditionTrim(Employee employee);

    // 查詢員工,測試Choose,When,otherwise
    public List<Employee> getEmpByConditionChoose(Employee employee);

    // 更新員工資訊
    public void updateEmp(Employee employee);

    // 插入員工資訊
    public void insertEmp(Employee employee);

    // 通過foreach在指定集合中查詢員工id
    public List<Employee> getEmpByConditionForeach(@Param("ids") List<Integer> id);

    // 通過foreach批量插入員工資訊
    public void addEmp(@Param("emps") List<Employee> employee);
}

2、定義EmployeeMapperDynamicSQL.xml配置檔案

<?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">
<mapper namespace="com.lhk.mybatis.dao.EmployeeMapperDynamicSQL">
    <!--
        • if 判斷
        • choose (when, otherwise) 分支選擇(帶了break的switch-case)
            如果帶了id就用id查,如果帶了lastName就用lastName查;只會進入其中一個
        • trim (where(封裝查詢條件), set(封裝修改條件)) 字串擷取
        • foreach
    -->

    <resultMap id="Simple" type="com.lhk.mybatis.bean.Employee">
        <result column="last_name" property="lastName"></result>
    </resultMap>


    <!--查詢員工,要求攜帶了哪個欄位查詢欄位就帶上這個欄位的值
        getEmpByConditionIf
    -->
    <select id="getEmpByConditionIf" resultMap="Simple">
        select * from tb1_employee
--         where
        <where>
            <!--
            測試where:
            1、當if條件不滿足,即where元素中沒有內容,在SQL語句中就不會出現where
            2、當if條件滿足,where元素的內容是以and開頭,where會自動去掉開頭的and or,以保證where條件正確
            3、where不能解決SQL語句後面多出的and or,要通過trim解決
            test:判斷表示式,從引數中取值進行判斷-->
            <if test="id!=null">
                id=#{id}
            </if>
            <if test="lastName!=null and lastName!=''">
                and last_name like #{lastName}
            </if>
            <if test="email!=null and email.trim()!=''">
                and email=#{email}
            </if>
            <if test="gender==0 and gender==1">
                and gender=#{gender}
            </if>
        </where>
    </select>


    <!--通過Trim方式 getEmpByConditionTrim -->
    <select id="getEmpByConditionTrim" resultMap="Simple">
        select * from tb1_employee
        --         where
        <!--
            where,set標籤的功能都可以通過Trim來實現
            解決SQL語句後面多出的and or,where標籤不能解決

        <trim prefix="" 字首,當trim元素內包含內容時,會給內容增加prefix指定的字首
              prefixOverrides="" 字首覆蓋,當trim元素內包含內容時,會把內容中匹配的字首字串去掉
              suffix="" 字尾,當trim元素內包含內容時,會給內容增加suffix指定的字尾
              suffixOverrides="" 字尾覆蓋,當trim元素內包含內容時,會把內容中匹配的字尾字串去掉
        </trim>
        -->


        <!--自定義字串擷取規則-->
        <!--在SQL語句前面新增where,去除SQL語句中後面多餘的and -->
        <trim prefix="where" prefixOverrides="" suffix="" suffixOverrides="and">
            <!-- test:判斷表示式,從引數中取值進行判斷-->
            <if test="id!=null">
                id=#{id} and
            </if>
            <if test="lastName!=null and lastName!=''">
                last_name like #{lastName} and
            </if>
            <if test="email!=null and email.trim()!=''">
                email=#{email} and
            </if>
            <if test="gender==0 and gender==1">
                gender=#{gender}
            </if>
        </trim>
    </select>


    <!--測試分支選擇 getEmpByConditionChoose -->
    <select id="getEmpByConditionChoose" resultMap="Simple">
        select * from tb1_employee
        <where>
            <!-- 如果帶了id就用id查,如果帶了lastName就用lastName查;只會進入其中一個 -->
            <choose>
                <when test="id!=null">
                    id=#{id}
                </when>
                <when test="lastName!=null">
                    last_name like #{lastName}
                </when>
                <when test="email!=null">
                    email=#{email}
                </when>
                <otherwise>
                    gender=0
                </otherwise>
            </choose>
        </where>
    </select>

    <!-- 測試update  updateEmp
        只更新要更新的值。為null的值就不更新
        set:1、如果該標籤包含的元素中有返回值,就插入一個set
             2、如果set後面的字串是以逗號結尾,就刪除這個逗號
             3、如果set元素中沒有內容,則仍然會出現SQL錯誤,所以id=#{id}仍有保留的必要
     -->
    <update id="updateEmp">
        update tb1_employee
        <set>
            <if test="lastName!=null">
                last_name=#{lastName},
            </if>
            <if test="email!=null">
                email=#{email},
            </if>
            <if test="gender!=null">
              gender=#{gender}
            </if>
            id=#{id},
        </set>
        where id=#{id}
    </update>

    <!--測試insert insertEmp
        只插入要插入的值。為null的值就不插入。
        在列的部分增加if條件,則values的部分也要增加相同的if條件,
        必須保證上下相互對應,完全匹配
    -->
    <insert id="insertEmp">
        insert into tb1_employee(
        <if test="id!=null and id!=''">
            id,
        </if>
        <if test="lastName!=null and lastName!=''">
            last_name,
        </if>
        <if test="email!=null and email!=''">
            email,
        </if>
        <if test="gender!=null and gender!=''">
            gender
        </if>
        )
        <trim suffixOverrides=",">
            values(
            <if test="id!=null and id!=''">
                #{id},
            </if>
            <if test="lastName!=null and lastName!=''">
                #{lastName},
            </if>
            <if test="email!=null and email!=''">
                #{email},
            </if>
            <if test="gender!=null and gender!=''">
                #{gender}
            </if>
            )
        </trim>
    </insert>


    <!--測試foreach getEmpByConditionForeach-->
    <!--
        collection:指定要遍歷的集合,
               list型別的引數會特殊處理封裝在map中,map的key就叫list
        item:將當前遍歷出的元素賦值給指定的變數
        separate:每個元素之間的分隔符
        open:遍歷出所有的結果拼接一個開始字元
        close:遍歷出所有的結果拼接一個結束字元
        index:遍歷list的時候,index是list的索引,item是list的值
               遍歷map的時候,index是map的key,item是map的值
    -->
    <select id="getEmpByConditionForeach" resultMap="Simple">
        select * from tb1_employee where id in

        <foreach collection="ids" item="item_id" separator="," open="(" close=")">
            #{item_id}
        </foreach>
    </select>

    <!-- 批量儲存:addEmp-->
    <insert id="addEmp">
        insert into tb1_employee(last_name,email,gender,d_id)
        values
        <foreach collection="emps" item="emp" separator=",">
            (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
        </foreach>
    </insert>
</mapper>

3、定義MybatisDynamicSQLTest測試類

package com.lhk.mybatis.test;

import com.lhk.mybatis.bean.Department;
import com.lhk.mybatis.bean.Employee;
import com.lhk.mybatis.dao.EmployeeMapperDynamicSQL;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author lhk
 * @create 2018-09-16 20:46
 */
public class MybatisDynamicSQLTest {
    public SqlSessionFactory getSqlSessionFactory() throws IOException {
        String resource = "conf/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        return new SqlSessionFactoryBuilder().build(inputStream);
    }

    /**
     * 測試If
     */
    @Test
    public void testgetEmpByConditionIf() throws IOException {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession sqlSession = sqlSessionFactory.openSession();

        try {
            EmployeeMapperDynamicSQL mapper = sqlSession.getMapper(EmployeeMapperDynamicSQL.class);
            Employee employee = new Employee(2,"%e%","
[email protected]
","1"); List<Employee> list = mapper.getEmpByConditionIf(employee); for (Employee emp : list) { System.out.println(emp); } //查詢的時候如果某些條件沒有,SQL拼裝可能會出問題 //1、給where後面加上1=1,以後的條件都and xxx //2、mybatis使用where標籤將所有的查詢條件包括在內 //mybatis就會將where標籤中的拼裝的SQL中多的and,or去掉。只會去掉第一個多出來的and,or }finally { sqlSession.close(); } } /** * 測試Trim */ @Test public void testGetEmpByConditionTrim() throws IOException { SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sqlSessionFactory.openSession(); try { EmployeeMapperDynamicSQL mapper = sqlSession.getMapper(EmployeeMapperDynamicSQL.class); Employee employee = new Employee(null, "%e%", "[email protected]", "1"); List<Employee> list = mapper.getEmpByConditionTrim(employee); for (Employee emp : list) { System.out.println(emp); } }finally { sqlSession.close(); } } /** * 測試Choose */ @Test public void testGetEmpByConditionChoose() throws IOException { SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sqlSessionFactory.openSession(); try { EmployeeMapperDynamicSQL mapper = sqlSession.getMapper(EmployeeMapperDynamicSQL.class); Employee employee = new Employee(null, null, "[email protected]", "1"); List<Employee> list = mapper.getEmpByConditionChoose(employee); for (Employee emp : list) { System.out.println(emp); } }finally { sqlSession.close(); } } /** * 測試set */ @Test public void testUpdateEmp() throws IOException { SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sqlSessionFactory.openSession(); try { EmployeeMapperDynamicSQL mapper = sqlSession.getMapper(EmployeeMapperDynamicSQL.class); Employee employee = new Employee(null, null, null, null); mapper.updateEmp(employee); sqlSession.commit(); // 提交 }finally { sqlSession.close(); } } /** * 測試insert */ @Test public void testInsertEmp() throws IOException { SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sqlSessionFactory.openSession(); try { EmployeeMapperDynamicSQL mapper = sqlSession.getMapper(EmployeeMapperDynamicSQL.class); Employee employee = new Employee(null, "lll", null, "0"); mapper.insertEmp(employee); sqlSession.commit(); // 提交 }finally { sqlSession.close(); } } /** * 測試foreach實現in集合 */ @Test public void testGetEmpByConditionForeach() throws IOException { SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sqlSessionFactory.openSession(); try { EmployeeMapperDynamicSQL mapper = sqlSession.getMapper(EmployeeMapperDynamicSQL.class); List<Employee> list = mapper.getEmpByConditionForeach(Arrays.asList(2,6)); for (Employee emp : list) { System.out.println(emp); } }finally { sqlSession.close(); } } /** * 測試foreach實現批量插入 */ @Test public void testBatchSave() throws IOException { SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession sqlSession = sqlSessionFactory.openSession(); try { EmployeeMapperDynamicSQL mapper = sqlSession.getMapper(EmployeeMapperDynamicSQL.class); List<Employee> emps = new ArrayList<>(); emps.add(new Employee(null,"Smith","[email protected]","1",new Department(1))); emps.add(new Employee(null,"Tom","[email protected]","0",new Department(2))); mapper.addEmp(emps); sqlSession.commit(); //提交 }finally { sqlSession.close(); } } }