Mybatis第三篇【動態SQL】

動態SQL

何爲動態SQL??回顧一下咱們以前寫的SSH項目中,有多條件查詢的狀況,以下圖java

這裏寫圖片描述

咱們當時剛開始作的時候,是須要在Controller中判斷SQL是否已經有條件了,由於SQL語句須要拼接起來….這樣乾的話,就很是容易出錯的。sql

以下的代碼,若是有多個條件的話,那麼拼接起來很容易出錯!數組

public String listUI() {

        //查詢語句
        String hql = "FROM Info i ";
        List<Object> objectList  = new ArrayList<>();

        //根據info是否爲null來判斷是不是條件查詢。若是info爲空,那麼是查詢全部。
        if (info != null) {
            if (StringUtils.isNotBlank(info.getTitle())) {
                hql += "where i.title like ?";
                objectList.add("%" + info.getTitle() + "%");
            }
        }
        infoList = infoServiceImpl.findObjects(hql,objectList);
        ActionContext.getContext().getContextMap().put("infoTypeMap", Info.INFO_TYPE_MAP);
        return "listUI";
    }

後來,咱們以爲這樣很差,因而就專門寫了一個查詢助手類:markdown

package zhongfucheng.core.utils;

import java.util.ArrayList;
import java.util.List;

/** * Created by ozc on 2017/6/7. */
public class QueryHelper {

    private String fromClause = "";
    private String whereClause = "";
    private String orderbyClause = "";
    private List<Object> objectList;

    public static String ORDER_BY_ASC = "asc";
    public static String ORDER_BY_DESC = "desc";



    //FROM子句只出現一次
    /** * 構建FROM字句,並設置查詢哪張表 * @param aClass 用戶想要操做的類型 * @param alias 別名 */
    public QueryHelper(Class aClass, String alias) {
        fromClause = " FROM " + aClass.getSimpleName() + " " + alias;
    }
    //WHERE字句能夠添加多個條件,但WHERE關鍵字只出現一次
    /** * 構建WHERE字句 * @param condition * @param objects * @return */
    public QueryHelper addCondition(String condition, Object... objects) {
        //若是已經有字符了,那麼就說明已經有WHERE關鍵字了
        if (whereClause.length() > 0) {
            whereClause += " AND " + condition;
        } else {
            whereClause += " WHERE" + condition;
        }
        //在添加查詢條件的時候,?對應的查詢條件值
        if (objects == null) {
            objectList = new ArrayList<>();
        }

        for (Object object : objects) {
            objectList.add(object);
        }

        return this;
    }
    /** * * @param property 要排序的屬性 * @param order 是升序仍是降序 * @return */
    public QueryHelper orderBy(String property, String order) {

        //若是已經有字符了,那麼就說明已經有ORDER關鍵字了
        if (orderbyClause.length() > 0) {
            orderbyClause += " , " + property +" " + order;
        } else {
            orderbyClause += " ORDER BY " + property+" " + order;
        }
        return this;
    }

    /** * 返回HQL語句 */
    public String returnHQL() {
        return fromClause + whereClause + orderbyClause;
    }

    /** * 獲得參數列表 * @return */
    public List<Object> getObjectList() {
        return objectList;
    }
}

這樣一來的話,咱們就不用本身手動拼接了,給咱們的查詢助手類去拼接就行了。ide

而若是咱們使用Mybatis的話,就能夠免去查詢助手類了。由於Mybatis內部就有動態SQL的功能【動態SQL就是自動拼接SQL語句】測試

動態查詢

<!--多條件查詢【動態SQL】-->
    <!--會自動組合成一個正常的WHERE字句-->
    <!--name值會從map中尋找-->

    <select id="findByCondition" resultMap="studentMap" parameterType="map">

        select * from students

        <where>
            <if test="name!=null">
                and name=#{name}
            </if>
            <if test="sal!=null">
                and sal &lt; #{sal}
            </if>
        </where>

    </select>

查詢出來小於9000塊的人this

public List<Student> findByCondition(String name,Double sal) throws Exception {
        //獲得鏈接對象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空間.SQL片斷的ID,就能夠調用對應的映射文件中的SQL
            /** * 因爲咱們的參數超過了兩個,而方法中只有一個Object參數收集 * 所以咱們使用Map集合來裝載咱們的參數 */
            Map<String, Object> map = new HashMap();
            map.put("name", name);
            map.put("sal", sal);
            return sqlSession.selectList("StudentID.findByCondition", map);
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }
    public static void main(String[] args) throws Exception {
        StudentDao studentDao = new StudentDao();
        List<Student> students = studentDao.findByCondition(null,9000D);
        for (Student student : students) {
            System.out.println(student.getId() + "---" + student.getName() + "----" + student.getSal());
        }


    }

這裏寫圖片描述

動態更新

這裏寫圖片描述

<!--動態更新-->
    <!--不要忘了逗號-->
    <update id="updateByConditions" parameterType="map">

        update students
        <set>
            <if test="name!=null">
                 name = #{name},
            </if>
            <if test="sal!=null">
                 sal = #{sal},
            </if>
        </set>
        where id = #{id}
    </update>

給出三個更新的字段spa

public void updateByConditions(int id,String name,Double sal) throws Exception {
        //獲得鏈接對象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空間.SQL片斷的ID,就能夠調用對應的映射文件中的SQL
            /** * 因爲咱們的參數超過了兩個,而方法中只有一個Object參數收集 * 所以咱們使用Map集合來裝載咱們的參數 */
            Map<String, Object> map = new HashMap();
            map.put("id", id);
            map.put("name", name);
            map.put("sal", sal);
            sqlSession.update("StudentID.updateByConditions", map);
            sqlSession.commit();
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }

    public static void main(String[] args) throws Exception {
        StudentDao studentDao = new StudentDao();
        studentDao.updateByConditions(2,"haha",500D);

    }

這裏寫圖片描述

動態刪除

這裏寫圖片描述
之前咱們使用JDBC也好,Hibernate也好,想要批量刪除的時候,老是使用的是循環刪除。而咱們如今使用的是Mybatis,SQL語句是本身寫的。因此咱們能夠寫下以下的SQL來進行刪除code

delete from students where id in (?,?,?,?);

而咱們的Mybatis又支持動態SQL,因此刪除起來就很是方便了!server

<delete id="deleteByConditions" parameterType="int">

        <!-- foreach用於迭代數組元素
             open表示開始符號
             close表示結束符合
             separator表示元素間的分隔符
             item表示迭代的數組,屬性值能夠任意,但提倡與方法的數組名相同
             #{ids}表示數組中的每一個元素值
         -->
        delete from students where id in
         <foreach collection="array" open="(" close=")" separator="," item="ids">
             #{ids}
         </foreach>

    </delete>

刪除編號爲2,3,4的記錄

public void deleteByConditions(int... ids) throws Exception {
        //獲得鏈接對象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空間.SQL片斷的ID,就能夠調用對應的映射文件中的SQL
            /** * 因爲咱們的參數超過了兩個,而方法中只有一個Object參數收集 * 所以咱們使用Map集合來裝載咱們的參數 */
            sqlSession.delete("StudentID.deleteByConditions", ids);
            sqlSession.commit();
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }

    public static void main(String[] args) throws Exception {
        StudentDao studentDao = new StudentDao();
        studentDao.deleteByConditions(2,3,4);

    }

這裏寫圖片描述

動態插入

咱們要想動態插入的話,就比其餘的DML語句稍微複雜一點,由於它有兩部分是不肯定的,日常的SQL語句是這樣的:

insert into student(id,name,sal) values(?,?,?) 

這裏寫圖片描述

SQL代碼塊是不能像以前那樣幫咱們自動去除多餘的逗號的,所以咱們須要使用trim標籤來本身手動去除…

編寫insertSQL語句的時候,不要忘了寫()括號。

<!--SQL片斷默認是不幫咱們自動生成合適的SQL,所以須要咱們本身手動除去逗號-->
    <sql id="key">
        <trim suffixOverrides=",">
            <if test="id!=null">
                id,
            </if>

            <if test="id!=null">
                name,
            </if>

            <if test="id!=null">
                sal,
            </if>
        </trim>
    </sql>

    <sql id="value">
        <trim suffixOverrides=",">
            <if test="id!=null">
                #{id},
            </if>

            <if test="id!=null">
                #{name},
            </if>

            <if test="id!=null">
                #{sal},
            </if>
        </trim>
    </sql>
    <!--動態插入-->
    <insert id="insertByConditions" parameterType="zhongfucheng.Student">

        insert into students (<include refid="key"/>) values
        (<include refid="value"/>)

    </insert>

測試三個不一樣內容的數據

public void insertByConditions(Student student) throws Exception {
        //獲得鏈接對象
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        try{
            //映射文件的命名空間.SQL片斷的ID,就能夠調用對應的映射文件中的SQL
            sqlSession.insert("StudentID.insertByConditions", student);
            sqlSession.commit();
        }catch(Exception e){
            e.printStackTrace();
            sqlSession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }

    public static void main(String[] args) throws Exception {
        StudentDao studentDao = new StudentDao();
        studentDao.insertByConditions(new Student(55, null, null));//name和sal爲空

        studentDao.insertByConditions(new Student(66, "haxi", null));//sal爲空
        studentDao.insertByConditions(new Student(77, null, 3999d));//name爲空


    }

這裏寫圖片描述

相關文章
相關標籤/搜索