MyBatis動態SQL

項目的建立和以前同樣,具體的看以前的文章,總體結構就是這樣java

1、if

對於該標籤的執行,當 test 的值爲 true 時,會將其包含的 SQL 片段拼接到其所在的 SQL 語句中。
語法:<if test=」條件」> sql 語句的部分 </if>sql

接口方法:StudentDao數據庫

// 動態的sql時,使用java對象做爲參數
    List<Student> selectStudentIf(Student student);

mapper文件:StudentDao.xml數組

<!--if的使用
         <if test="使用的參數爲java對象屬性值做爲判斷條件">
         語法:屬性=xxx值
    -->

    <!-- 
	注意,當這樣寫的時候,name不知足而age知足的時候會出現問題
    正常:select id,name,age,email from student where name = ? or age > ?
    不正常: select id,name,age,email from student where or age > ? 
	這個時候會有語法錯誤
    因此寫的是時候要在where後面這樣
    where 1=1
    這樣寫的話即便name不知足,後面的也不不會出現語法錯誤
    select id,name,age,email from student where 1=1 or age > ?
    但這樣也會出現其餘的bug,由於是or,而且1=1永遠爲true,因此age不管傳入多大都會有數據的
    -->
    <select id="selectStudentIf" resultType="com.md.domain.Student">

      select id,name,age,email from student
      where 1=1
      <if test="name != null and name != '' ">
          name = #{name}
      </if>

      <if test="age > 0" >
          or age > #{age}
      </if>

    </select>

測試mybatis

@Test
    public void testSelectStudentIf(){

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);

        Student student = new Student();
        student.setAge(20);
        
        List<Student> studentList = dao.selectStudentIf(student);
        studentList.forEach(stu-> System.out.println(stu));
		sqlSession.close();

    }

此時即便數據庫中,不管年紀多大的都會被查出來,因此就有了下面的標籤app

2、where

<if/>標籤的中存在一個比較麻煩的地方:須要在 where 後手工添加 1=1 的子句。由於,若 where 後
的全部<if/>條件均爲 false,而 where 後若又沒有 1=1 子句,則 SQL 中就會只剩下一個空的 where,SQL
出錯。因此,在 where 後,須要添加永爲真子句 1=1,以防止這種狀況的發生。但當數據量很大時,會
嚴重影響查詢效率dom

使用<where/>標籤,在有查詢條件時,能夠自動添加上 where 子句;沒有查詢條件時,不會添加where 子句。須要注意的是,第一個<if/>標籤中的 SQL 片段,能夠不包含 and。不過,寫上 and 也不錯,系統會將多出的 and 去掉。但其它<if/>中 SQL 片段的 and,必需要求寫上。不然 SQL 語句將拼接出錯測試

<where> 用來包含 多個<if>的, 當多個if有一個成立的, <where>會自動增長一個where關鍵字,並去掉 if中多餘的 and ,or等ui

語法:<where> 其餘動態 sql </where>3d

接口方法

// 動態的sql時,使用java對象做爲參數
    List<Student> selectStudentWhere(Student student);

mapper

<!--where的使用

        select id,name,age,email from student WHERE name = ? or age > ?
        select id,name,age,email from student WHERE age > ?
        這樣就避免了上面的bug
    -->

    <select id="selectStudentWhere" resultType="com.md.domain.Student">

      select id,name,age,email from student
      <where>
          <if test="name != null and name != '' ">
              name = #{name}
          </if>

          <if test="age > 0" >
              or age > #{age}
          </if>

      </where>

    </select>

測試:

@Test
    public void testSelectStudentWhere(){

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);

        Student student = new Student();
        student.setName("白昊天");
        student.setAge(20);

        List<Student> studentList = dao.selectStudentWhere(student);
        studentList.forEach(stu-> System.out.println(stu));
        sqlSession.close();


    }

此時就不會出現以前的bug了

3、foreach

<foreach/>標籤用於實現對於數組與集合的遍歷。對其使用,須要注意:

  • collection 表示要遍歷的集合類型, list ,array 等。
  • open、close、separator 爲對遍歷內容的 SQL 拼接

語法

<foreach collection=" 集合類型" open=" 開始的字符" close=" 結束的字符"
item=" 集合中的成員" separator=" 集合成員之間的分隔符">
#{item 的值}
</foreach>

例子,查詢學號100一、100二、1003學生的信息

若是是用純java來拼接這個查詢sql語句

@Test
    public void testfor(){
        List<Integer> list = new ArrayList<>();
        list.add(1001);
        list.add(1002);
        list.add(1003);

        String sql = "select * from student where id in";

        StringBuilder builder = new StringBuilder("");


        // 添加開始
        builder.append("(");
        for (Integer i : list){
            builder.append(i).append(",");
        }
        // 由於最後多添加了一個逗號,因此在這裏進行刪除
        builder.deleteCharAt(builder.length()-1);

        builder.append(")");

        sql = sql + builder.toString();
        System.out.println(sql);

//        select * from student where id in(1001,1002,1003)

    }

1. 用法一

接口

// 傳入的是普通list
List<Student> selectForeachOne(List<Integer> idlist);

mapper

select id,name,age,email from student where id in ( ? , ? , ? )

<select id="selectForeachOne" resultType="com.md.domain.Student">

      select id,name,age,email from student where id in
      <foreach collection="list" item="myid" open="(" close=")" separator=",">

        #{myid}

      </foreach>
    </select>

測試:

@Test
    public void testSelectForeachOne(){

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);

        List<Integer> list = new ArrayList<>();
        list.add(1001);
        list.add(1002);
        list.add(1003);

        List<Student> studentList = dao.selectForeachOne(list);
        studentList.forEach(stu-> System.out.println(stu));

        sqlSession.close();
    }

2. 用法二

接口

//    foreach 用法二 , 傳入的是對象集合
    List<Student> selectForeachTwo(List<Student> stulist);

mapper文件

因爲傳入的是對象,因此要用對象.屬性

<select id="selectForeachTwo" resultType="com.md.domain.Student">

        select id,name,age,email from student where id in
        <foreach collection="list" item="stu" open="(" close=")" separator=",">
            #{stu.id}
        </foreach>

    </select>

測試方法

@Test
    public void testSelectForeachTwo(){

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);

        List<Student> students = new ArrayList<>();
        Student stu1 = new Student();
        stu1.setId(1003);
        students.add(stu1);

        List<Student> studentList = dao.selectForeachTwo(students);
        studentList.forEach(stu-> System.out.println(stu));
//        select id,name,age,email from student where id in ( ? )
//        Student{id=1003, name='白昊天', email='ht@qq.com', age=18}
        sqlSession.close();
    }

固然了,對於mapper文件的sql語句還能夠這樣寫

<!-- 直接在外面寫小括號,只有能湊成完成的sql語句就行-->
    <select id="selectForeachTwo" resultType="com.md.domain.Student">

        select id,name,age,email from student where id in (
        <foreach collection="list" item="stu" separator=",">
            #{stu.id}
        </foreach>
        )
    </select>

效果和上面的是同樣的,能完成的拼湊出sql語句便可

4、sql代碼片斷

<sql/>標籤用於定義 SQL 片段,以便其它 SQL 標籤複用。

而其它標籤使用該 SQL 片段,須要使用<include/>子標籤。該<sql/>標籤能夠定義 SQL 語句中的任何部分,因此<include/>子標籤能夠放在動態 SQL的任何位置

接口方法:

List<Student> selectStudentSqlFragment(List<Student> stuList);

mapper文件

<!-- 建立 sql 片斷 id: 片斷的自定義名稱 -->
<sql id="studentSql">
	select id,name,email,age from student
</sql>
<select id="selectStudentSqlFragment" resultType="com.md.domain.Student">
<!-- 引用 sql 片斷 -->
	<include refid="studentSql"/>
	<if test="list !=null and list.size > 0 ">
	where id in
	<foreach collection="list" open="(" close=")"
		item="stuobject" separator=",">
	#{stuobject.id}
	</foreach>
<	/if>
</select>

測試方法

@Test
public void testSelectSqlFragment() {
	List<Student> list = new ArrayList<>();
	Student s1 = new Student();
	s1.setId(1002);
	list.add(s1);
	s1 = new Student();
	s1.setId(1005);
	list.add(s1);
	List<Student> studentList = studentDao.selectStudentSqlFragment(list);
	studentList.forEach( stu -> System.out.println(stu));
}

5、總結

根據條件可以使用不一樣的sql語句,使用mybatis標籤

1. if

判斷條件,條件爲true,就會把if以前的sql加入到主sql語句以後

2. where

<where> 標籤裏面多個if標籤,若是有一個if判斷爲true,就會在sql的後面加入where關鍵字,而還會自動的去掉無用的and、or等字符

3. foreach

循環數組,list集合,主要看語法格式

4. sql代碼片斷

複用經常使用的sql語句

  • 先定義<sql id="自定義名惟一" > sql語句 </sql>
  • 再使用 <include refid = "id的值">
相關文章
相關標籤/搜索