0064 MyBatis動態SQL--choose-when-otherwise--foreach--set--bind

讀寫數據庫的時候,每每要根據傳入的參數的不一樣,改變sql語句。
好比:若是傳入了某個參數值,那就查詢對應的字段,沒傳入,那就不查,這就是0048中的where--if
再好比:java

  1. 若是傳入了某個參數值,那就只查詢這個字段,若是沒傳入,就看下一個字段是否傳入,若是這些字段值都沒有傳入,那就按默認的條件查詢。這是choose--when--otherwise
  2. update操做的時候,若是傳入了某個參數值,那就更新該字段,若是沒傳入那就不更新該字段。這是set
  3. 若是要用in查詢將某個集合中相關的數據都查出來,這就要foreach
  4. 若是程序傳進來的參數值,還須要進一步拼接,這就要bind

choose--when--otherwise

查詢書籍信息,若是傳入了isbn號,那就只查這個字段,沒傳入的話,就看書名,有的話就查書名,若是isbn和書名都沒有,那就把douban評分大於7分的查出來.
相似於switch,選擇一條執行mysql

<mapper namespace="net.sonng.mbt.mapper.BookMapper">
    <select id="findBooks" parameterType="net.sonng.mbt.entity.Book" resultType="net.sonng.mbt.entity.Book">
        SELECT * FROM book WHERE 
            <choose>
                <when test="isbn!=null" > <!-- 若是傳入了isbn號,那就只按isbn查 -->
                    isbn=#{isbn}
                </when>
                <when test="name!=null">   <!-- 若是沒傳入isbn號,就看是否有書名,有的話就只按書名查 -->
                    `name`=#{name}         <!-- 注意name貌似是mysql的關鍵字,用上橫(上劃線)括起來 -->
                </when>
                <otherwise>           <!-- 若是isbn和書名都沒有,就將douban>7的書籍查出來 -->
                    douban>7     <!-- 實踐證實,大於號>在這裏能夠正經常使用,換成轉移字符:&gt;,也能用 -->
                </otherwise>
            </choose>
    </select>
</mapper>

BookMapper.java接口略
測試類:sql

package net.sonng.mbt.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import net.sonng.mbt.entity.Book;
import net.sonng.mbt.mapper.BookMapper;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class BookTest {
    public static void main(String[] args) throws IOException{
        InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session=sqlSessionFactory.openSession();
        BookMapper bookMapper=session.getMapper(BookMapper.class);
        Book book=new Book();
        book.setName("深刻理解Java 7 核心技術與最佳實踐");
        book.setPress("機械工業出版社");
        book.setAuthor("成富著");
        book.setDouban(6.9f);
        book.setIsbn("9787111380399");                  //傳入了isbn
        List<Book> books=bookMapper.findBooks(book);
        for(Book b:books){
            System.out.println(b);
        }
    }
}

輸出以下:數據庫

DEBUG [main] - ==>  Preparing: SELECT * FROM book WHERE isbn=?   //傳入了isbn就只按isbn查
DEBUG [main] - ==> Parameters: 9787111380399(String)
DEBUG [main] - <==      Total: 1
Book [id=5, name=深刻理解Java 7 核心技術與最佳實踐, press=機械工業出版社, author=成富著, isbn=9787111380399, douban=6.9]

book.setIsbn("9787111380399");註釋掉,輸出以下:apache

DEBUG [main] - ==>  Preparing: SELECT * FROM book WHERE `name`=?         //沒有isbn,有name,就只按name查
DEBUG [main] - ==> Parameters: 深刻理解Java 7 核心技術與最佳實踐(String)
DEBUG [main] - <==      Total: 1
Book [id=5, name=深刻理解Java 7 核心技術與最佳實踐, press=機械工業出版社, author=成富著, isbn=9787111380399, douban=6.9]

book.setName("深刻理解Java 7 核心技術與最佳實踐");註釋掉,輸出以下:編程

DEBUG [main] - ==>  Preparing: SELECT * FROM book WHERE douban>7   //isbn和書名都沒有,就把douban>7的列出了,下面有3條查詢結果
DEBUG [main] - ==> Parameters: 
DEBUG [main] - <==      Total: 3
Book [id=1, name=深刻理解Java虛擬機 JVM高級特性與最佳實踐, press=機械工業出版社, author=周志明著, isbn=9787111421900, douban=8.8]
Book [id=2, name=瘋狂Java講義 第3版, press=電子工業出版社, author=李剛著, isbn=9787121236693, douban=7.8]
Book [id=4, name=Java編程思想 第4版, press=機械工業出版社, author=(美)Bruce Eckel著, isbn=9787111213826, douban=9.1]

set

更新一條書籍信息,可能更新name、press、isbn、author、douban的一個或多個數組

<select id="findBookById" parameterType="int" resultType="net.sonng.mbt.entity.Book">
        SELECT * FROM book WHERE id=#{id}
    </select>
    <update id="updateBook" parameterType="net.sonng.mbt.entity.Book" >
        UPDATE book 
        <set>  <!-- set跟where的做用相似 -->
            <if test="name!=null" >`name`=#{name},</if>
            <if test="press!=null" >press=#{press},</if>
            <if test="author!=null" >author=#{author},</if>
            <if test="isbn!=null" >isbn=#{isbn},</if>
            <if test="douban!=null" >douban=#{douban}</if>
        </set>
        WHERE id=${id}
    </update>

測試類:session

package net.sonng.mbt.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import net.sonng.mbt.entity.Book;
import net.sonng.mbt.mapper.BookMapper;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class BookTest {
    public static void main(String[] args) throws IOException{
        InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session=sqlSessionFactory.openSession();
        BookMapper bookMapper=session.getMapper(BookMapper.class);
        Book book=bookMapper.findBookById(5);   //update的時候,通常先將數據查出來再修改數據再更新
        book.setDouban(10.0f);
        bookMapper.updateBook(book);
        session.commit();             //注意不要忘了提交事務
        session.close();
    }
}

foreach

用in查詢的時候,傳入的參數個數不明確,這時候就用foreach進行遍歷mybatis

<select id="findBookInId" parameterType="list" resultType="net.sonng.mbt.entity.Book">
        SELECT * FROM book WHERE id In 
        <foreach item="id" index="i" collection="list" open="(" separator="," close=")">
            #{id}
        </foreach>
    </select>

測試類:app

package net.sonng.mbt.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import net.sonng.mbt.entity.Book;
import net.sonng.mbt.mapper.BookMapper;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class BookTest {
    public static void main(String[] args) throws IOException{
        InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session=sqlSessionFactory.openSession();
        BookMapper bookMapper=session.getMapper(BookMapper.class);
        List<Integer> ids=new ArrayList<Integer>();
        ids.add(1);
        ids.add(2);
        ids.add(5);
        List<Book> books=bookMapper.findBookInId(ids);
        for(Book book:books){
            System.out.println(book);
        }
        session.close();
    }
}

輸出以下:

DEBUG [main] - ==>  Preparing: SELECT * FROM book WHERE id In ( ? , ? , ? ) 
DEBUG [main] - ==> Parameters: 1(Integer), 2(Integer), 5(Integer)
DEBUG [main] - <==      Total: 3
Book [id=1, name=深刻理解Java虛擬機 JVM高級特性與最佳實踐, press=機械工業出版社, author=周志明著, isbn=9787111421900, douban=8.8]
Book [id=2, name=瘋狂Java講義 第3版, press=電子工業出版社, author=李剛著, isbn=9787121236693, douban=7.8]
Book [id=5, name=深刻理解Java 7 核心技術與最佳實踐, press=機械工業出版社, author=成富著, isbn=9787111380399, douban=10.0]

foreach元素的幾個屬性:
----item:迭代元素的別名
----index:指定一個名字,用於表示在迭代過程當中,每次迭代到的位置
----collection:傳進來的參數的類型:list(單參數且參數類型爲List)、array(單參數且參數類型爲數組)、map(多參數)
----open:in後面的語句以什麼開始
----separator:元素間的分隔符
----close:in後面的語句以什麼結束

bind

該元素從OGNL表達式建立一個變量並將其綁定到上下文

<select id="findBookLikeName" parameterType="string" resultType="net.sonng.mbt.entity.Book">
        <bind name="pattern" value="'%'+_parameter+'%'" />   <!-- 傳進來的參數是java,這裏將其拼接成:%java% -->
        SELECT * FROM book WHERE `name` LIKE #{pattern}
    </select>

測試類:

package net.sonng.mbt.test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import net.sonng.mbt.entity.Book;
import net.sonng.mbt.mapper.BookMapper;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class BookTest {
    public static void main(String[] args) throws IOException{
        InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session=sqlSessionFactory.openSession();
        BookMapper bookMapper=session.getMapper(BookMapper.class);
        List<Book> books=bookMapper.findBookLikeName("java");
        for(Book book:books){
            System.out.println(book);
        }
        session.close();
    }
}

輸出:

DEBUG [main] - ==>  Preparing: SELECT * FROM book WHERE `name` LIKE ? 
DEBUG [main] - ==> Parameters: %java%(String)   //傳入的參數是拼接後的字符串
DEBUG [main] - <==      Total: 4
Book [id=1, name=深刻理解Java虛擬機 JVM高級特性與最佳實踐, press=機械工業出版社, author=周志明著, isbn=9787111421900, douban=8.8]
Book [id=2, name=瘋狂Java講義 第3版, press=電子工業出版社, author=李剛著, isbn=9787121236693, douban=7.8]
Book [id=4, name=Java編程思想 第4版, press=機械工業出版社, author=(美)Bruce Eckel著, isbn=9787111213826, douban=9.1]
Book [id=5, name=深刻理解Java 7 核心技術與最佳實踐, press=機械工業出版社, author=成富著, isbn=9787111380399, douban=10.0]

bind的value屬性:
----_parameter:注意下劃線,表示傳進來的參數自己
----parameter:沒有下劃線,表示傳進來的參數的parameter屬性
----_parameter.getName():注意下劃線,表示調用傳進來的參數對象的getName()方法的返回值

小結

if:傳進來的某個參數不爲空,那麼查詢該字段
where:能夠動態的處理and和,
choose--otherwise:從前日後,哪一個參數傳進來了,那就只查詢該參數,不然按otherwise查詢
set:用於update語句,跟where做用相似
foreach:多用於IN查詢,用於迭代傳進來的參數集合
bind:將傳進來的參數進行一些修改

這個文檔能夠看看:https://www.kancloud.cn/digest/andyalien-mybatis/190191

相關文章
相關標籤/搜索