<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          MyBatis動(dòng)態(tài)SQL(認(rèn)真看看, 以后寫SQL就爽多了)

          共 2540字,需瀏覽 6分鐘

           ·

          2020-07-29 12:23

          點(diǎn)擊上方藍(lán)色“小哈學(xué)Java”,選擇“設(shè)為星標(biāo)

          回復(fù)“資源”獲取獨(dú)家整理的學(xué)習(xí)資料!

          來(lái)源:cnblogs.com/homejim/p/9909657.html

          mybatis最新源碼和注釋


          MyBatis 令人喜歡的一大特性就是動(dòng)態(tài) SQL。在使用 JDBC 的過(guò)程中, 根據(jù)條件進(jìn)行 SQL 的拼接是很麻煩且很容易出錯(cuò)的。MyBatis 動(dòng)態(tài) SQL 的出現(xiàn), 解決了這個(gè)麻煩。

          MyBatis通過(guò) OGNL 來(lái)進(jìn)行動(dòng)態(tài) SQL 的使用的。

          目前, 動(dòng)態(tài) SQL 支持以下幾種標(biāo)簽

          元素作用備注
          if判斷語(yǔ)句單條件分支
          choose(when、otherwise)相當(dāng)于 Java 中的 if else多條件分支
          trim(where、set)輔助元素用于處理 SQL 拼接問(wèn)題
          foreach循環(huán)語(yǔ)句批量插入, 更新, 查詢時(shí)經(jīng)常用到
          bind創(chuàng)建一個(gè)變量, 并綁定到上下文中用于兼容不同的數(shù)據(jù)庫(kù), 防止 SQL 注入等

          1 數(shù)據(jù)準(zhǔn)備

          為了后面的演示, 創(chuàng)建了一個(gè) Maven 項(xiàng)目 mybatis-dynamic, 創(chuàng)建了對(duì)應(yīng)的數(shù)據(jù)庫(kù)和表

          DROP?TABLE?IF?EXISTS?`student`;

          CREATE?TABLE?`student`?(
          ??`student_id`?int(10)?unsigned?NOT?NULL?AUTO_INCREMENT?COMMENT?'編號(hào)',
          ??`name`?varchar(20)?DEFAULT?NULL?COMMENT?'姓名',
          ??`phone`?varchar(20)?DEFAULT?NULL?COMMENT?'電話',
          ??`email`?varchar(50)?DEFAULT?NULL?COMMENT?'郵箱',
          ??`sex`?tinyint(4)?DEFAULT?NULL?COMMENT?'性別',
          ??`locked`?tinyint(4)?DEFAULT?NULL?COMMENT?'狀態(tài)(0:正常,1:鎖定)',
          ??`gmt_created`?datetime?DEFAULT?CURRENT_TIMESTAMP?COMMENT?'存入數(shù)據(jù)庫(kù)的時(shí)間',
          ??`gmt_modified`?datetime?DEFAULT?CURRENT_TIMESTAMP?ON?UPDATE?CURRENT_TIMESTAMP?COMMENT?'修改的時(shí)間',
          ??`delete`?int(11)?DEFAULT?NULL,
          ??PRIMARY?KEY?(`student_id`)
          )?ENGINE=InnoDB?AUTO_INCREMENT=7?DEFAULT?CHARSET=utf8mb4?COLLATE=utf8mb4_0900_ai_ci?COMMENT='學(xué)生表';

          對(duì)應(yīng)的項(xiàng)目結(jié)構(gòu)

          項(xiàng)目結(jié)構(gòu)

          2 if 標(biāo)簽

          if 標(biāo)簽是我們最常使用的。在查詢、刪除、更新的時(shí)候很可能會(huì)使用到。必須結(jié)合 test 屬性聯(lián)合使用。

          2.1 在 WHERE 條件中使用 if 標(biāo)簽

          這是常見(jiàn)的一種現(xiàn)象, 我們?cè)谶M(jìn)行按條件查詢的時(shí)候, 可能會(huì)有多種情況。

          2.1.1 查詢條件

          根據(jù)輸入的學(xué)生信息進(jìn)行條件檢索

          1. 當(dāng)只輸入用戶名時(shí), 使用用戶名進(jìn)行模糊檢索;
          2. 當(dāng)只輸入性別時(shí), 使用性別進(jìn)行完全匹配
          3. 當(dāng)用戶名和性別都存在時(shí), 用這兩個(gè)條件進(jìn)行查詢匹配查詢

          2.1.2 動(dòng)態(tài) SQL

          接口函數(shù)

          ????/**
          ?????*?根據(jù)輸入的學(xué)生信息進(jìn)行條件檢索
          ?????* 1. 當(dāng)只輸入用戶名時(shí),?使用用戶名進(jìn)行模糊檢索;
          ?????*?2.?當(dāng)只輸入郵箱時(shí),?使用性別進(jìn)行完全匹配
          ?????*?3.?當(dāng)用戶名和性別都存在時(shí),?用這兩個(gè)條件進(jìn)行查詢匹配的用
          ?????*?@param?student
          ?????*?@return
          ?????*/
          ????????List?selectByStudentSelective(Student?student);

          對(duì)應(yīng)的動(dòng)態(tài) SQL

          ??"selectByStudentSelective"?resultMap="BaseResultMap"?parameterType="com.homejim.mybatis.entity.Student">
          ????select
          ????"Base_Column_List"?/>
          ????from?student
          ????where?1=1
          ????<if?test="name?!=?null?and?name?!=''">
          ??????and?name?like?concat('%',?#{name},?'%')
          ????if>
          ????<if?test="sex?!=?null">
          ??????and?sex=#{sex}
          ????if>
          ??

          在此 SQL 語(yǔ)句中, where 1=1 是多條件拼接時(shí)的小技巧, 后面的條件查詢就可以都用 and 了。

          同時(shí), 我們添加了 if 標(biāo)簽來(lái)處理動(dòng)態(tài) SQL

          ????<if?test="name?!=?null?and?name?!=''">
          ??????and?name?like?concat('%',?#{name},?'%')
          ????if>
          ????<if?test="sex?!=?null">
          ??????and?sex=#{sex}
          ????if>

          此 if 標(biāo)簽的 test 屬性值是一個(gè)符合 OGNL 的表達(dá)式, 表達(dá)式可以是 true 或 false。如果表達(dá)式返回的是數(shù)值, 則0為 false, 非 0 為 true;

          2.1.3 測(cè)試

          ??????@Test
          ????public?void?selectByStudent()?{
          ????????SqlSession?sqlSession?=?null;
          ????????sqlSession?=?sqlSessionFactory.openSession();
          ????????StudentMapper?studentMapper?=?sqlSession.getMapper(StudentMapper.class);

          ????????Student?search?=?new?Student();
          ????????search.setName("明");

          ????????System.out.println("只有名字時(shí)的查詢");
          ????????List?studentsByName?=?studentMapper.selectByStudentSelective(search);
          ????????for?(int?i?=?0;?i?????????????System.out.println(ToStringBuilder.reflectionToString(studentsByName.get(i),?ToStringStyle.MULTI_LINE_STYLE));
          ????????}

          ????????search.setName(null);
          ????????search.setSex((byte)?1);
          ????????System.out.println("只有性別時(shí)的查詢");
          ????????List?studentsBySex?=?studentMapper.selectByStudentSelective(search);
          ????????for?(int?i?=?0;?i?????????????System.out.println(ToStringBuilder.reflectionToString(studentsBySex.get(i),?ToStringStyle.MULTI_LINE_STYLE));
          ????????}

          ????????System.out.println("姓名和性別同時(shí)存在的查詢");
          ????????search.setName("明");
          ????????List?studentsByNameAndSex?=?studentMapper.selectByStudentSelective(search);
          ????????for?(int?i?=?0;?i?????????????System.out.println(ToStringBuilder.reflectionToString(studentsByNameAndSex.get(i),?ToStringStyle.MULTI_LINE_STYLE));
          ????????}

          ????????sqlSession.commit();
          ????????sqlSession.close();
          ????}

          只有名字時(shí)的查詢, 發(fā)送的語(yǔ)句和結(jié)果

          只有名字時(shí)的查詢

          查詢的條件只發(fā)送了

          where?1=1?and?name?like?concat('%',??,?'%')?

          只有性別時(shí)的查詢, 發(fā)送的語(yǔ)句和結(jié)果

          只有性別時(shí)的查詢

          查詢的條件只發(fā)送了

          ?where?1=1?and?sex=??

          姓名和性別同時(shí)存在的查詢, 發(fā)送的語(yǔ)句和結(jié)果

          姓名和性別同時(shí)存在的查詢

          查詢條件

          where?1=1?and?name?like?concat('%',??,?'%')?and?sex=??

          2.2 在 UPDATE 更新列中使用 if 標(biāo)簽

          有時(shí)候我們不希望更新所有的字段, 只更新有變化的字段。

          2.2.1 更新條件

          只更新有變化的字段, 空值不更新。

          2.2.1 動(dòng)態(tài) SQL

          接口方法

          ????/**
          ?????*?更新非空屬性
          ?????*/
          ????int?updateByPrimaryKeySelective(Student?record);

          對(duì)應(yīng)的 SQL

          ??"updateByPrimaryKeySelective"?parameterType="com.homejim.mybatis.entity.Student">
          ????update?student
          ????<set>
          ??????<if?test="name?!=?null">
          ????????`name`?=?#{name,jdbcType=VARCHAR},
          ??????if>
          ??????<if?test="phone?!=?null">
          ????????phone?=?#{phone,jdbcType=VARCHAR},
          ??????if>
          ??????<if?test="email?!=?null">
          ????????email?=?#{email,jdbcType=VARCHAR},
          ??????if>
          ??????<if?test="sex?!=?null">
          ????????sex?=?#{sex,jdbcType=TINYINT},
          ??????if>
          ??????<if?test="locked?!=?null">
          ????????locked?=?#{locked,jdbcType=TINYINT},
          ??????if>
          ??????<if?test="gmtCreated?!=?null">
          ????????gmt_created?=?#{gmtCreated,jdbcType=TIMESTAMP},
          ??????if>
          ??????<if?test="gmtModified?!=?null">
          ????????gmt_modified?=?#{gmtModified,jdbcType=TIMESTAMP},
          ??????if>
          ????set>
          ????where?student_id?=?#{studentId,jdbcType=INTEGER}

          2.2.3 測(cè)試

          ????@Test
          ????public?void?updateByStudentSelective()?{
          ????????SqlSession?sqlSession?=?null;
          ????????sqlSession?=?sqlSessionFactory.openSession();
          ????????StudentMapper?studentMapper?=?sqlSession.getMapper(StudentMapper.class);

          ????????Student?student?=?new?Student();
          ????????student.setStudentId(1);
          ????????student.setName("明明");
          ????????student.setPhone("13838438888");
          ????????System.out.println(studentMapper.updateByPrimaryKeySelective(student));

          ????????sqlSession.commit();
          ????????sqlSession.close();
          ????}

          結(jié)果如下

          在 UPDATE 更新列中使用 if 標(biāo)簽

          2.3 在 INSERT 動(dòng)態(tài)插入中使用 if 標(biāo)簽

          我們插入數(shù)據(jù)庫(kù)中的一條記錄, 不是每一個(gè)字段都有值的, 而是動(dòng)態(tài)變化的。在這時(shí)候使用 if 標(biāo)簽, 可幫我們解決這個(gè)問(wèn)題。

          2.3.1 插入條件

          只有非空屬性才插入。

          2.3.2 動(dòng)態(tài)SQL

          接口方法

          ????/**
          ?????*?非空字段才進(jìn)行插入
          ?????*/
          ????int?insertSelective(Student?record);

          對(duì)應(yīng)的SQL

          "insertSelective"?parameterType="com.homejim.mybatis.entity.Student">
          ????insert?into?student
          ????"("?suffix=")"?suffixOverrides=",">
          ??????<if?test="studentId?!=?null">
          ????????student_id,
          ??????if>
          ??????<if?test="name?!=?null">
          ????????`name`,
          ??????if>
          ??????<if?test="phone?!=?null">
          ????????phone,
          ??????if>
          ??????<if?test="email?!=?null">
          ????????email,
          ??????if>
          ??????<if?test="sex?!=?null">
          ????????sex,
          ??????if>
          ??????<if?test="locked?!=?null">
          ????????locked,
          ??????if>
          ??????<if?test="gmtCreated?!=?null">
          ????????gmt_created,
          ??????if>
          ??????<if?test="gmtModified?!=?null">
          ????????gmt_modified,
          ??????if>
          ????
          ????"values?("?suffix=")"?suffixOverrides=",">
          ??????<if?test="studentId?!=?null">
          ????????#{studentId,jdbcType=INTEGER},
          ??????if>
          ??????<if?test="name?!=?null">
          ????????#{name,jdbcType=VARCHAR},
          ??????if>
          ??????<if?test="phone?!=?null">
          ????????#{phone,jdbcType=VARCHAR},
          ??????if>
          ??????<if?test="email?!=?null">
          ????????#{email,jdbcType=VARCHAR},
          ??????if>
          ??????<if?test="sex?!=?null">
          ????????#{sex,jdbcType=TINYINT},
          ??????if>
          ??????<if?test="locked?!=?null">
          ????????#{locked,jdbcType=TINYINT},
          ??????if>
          ??????<if?test="gmtCreated?!=?null">
          ????????#{gmtCreated,jdbcType=TIMESTAMP},
          ??????if>
          ??????<if?test="gmtModified?!=?null">
          ????????#{gmtModified,jdbcType=TIMESTAMP},
          ??????if>
          ????
          ??

          這個(gè) SQL 大家應(yīng)該很熟悉, 畢竟是自動(dòng)生成的。

          2.3.3 測(cè)試

          ????@Test
          ????public?void?insertByStudentSelective()?{
          ????????SqlSession?sqlSession?=?null;
          ????????sqlSession?=?sqlSessionFactory.openSession();
          ????????StudentMapper?studentMapper?=?sqlSession.getMapper(StudentMapper.class);

          ????????Student?student?=?new?Student();
          ????????student.setName("小飛機(jī)");
          ????????student.setPhone("13838438899");
          ????????student.setEmail("[email protected]");
          ????????student.setLocked((byte)?0);

          ????????System.out.println(studentMapper.insertSelective(student));

          ????????sqlSession.commit();
          ????????sqlSession.close();
          ????}

          對(duì)應(yīng)的結(jié)果

          在 INSERT 動(dòng)態(tài)插入中使用 if 標(biāo)簽

          SQL 中, 只有非空的字段才進(jìn)行了插入。

          3 choose 標(biāo)簽

          choose when otherwise 標(biāo)簽可以幫我們實(shí)現(xiàn) if else 的邏輯。

          一個(gè) choose 標(biāo)簽至少有一個(gè) when, 最多一個(gè)otherwise

          下面是一個(gè)查詢的例子。

          3.1 查詢條件

          假設(shè) name 具有唯一性, 查詢一個(gè)學(xué)生

          • 當(dāng) studen_id 有值時(shí), 使用 studen_id 進(jìn)行查詢;
          • 當(dāng) studen_id 沒(méi)有值時(shí), 使用 name 進(jìn)行查詢;
          • 否則返回空

          3.2 動(dòng)態(tài)SQL

          接口方法

          ????/**
          ?????*?-?當(dāng) studen_id 有值時(shí),?使用 studen_id 進(jìn)行查詢;
          ?????*?-?當(dāng) studen_id 沒(méi)有值時(shí),?使用 name 進(jìn)行查詢;
          ?????*?-?否則返回空
          ?????*/
          ????Student?selectByIdOrName(Student?record);

          對(duì)應(yīng)的SQL

          ??"selectByIdOrName"?resultMap="BaseResultMap"?parameterType="com.homejim.mybatis.entity.Student">
          ????select
          ????"Base_Column_List"?/>
          ????from?student
          ????where?1=1
          ????
          ??????test="studentId?!=?null">
          ????????and?student_id=#{studentId}
          ??????
          ??????test="name?!=?null?and?name?!=?''">
          ????????and?name=#{name}
          ??????
          ??????
          ????????and?1=2
          ??????

          ????

          ??

          3.3 測(cè)試

          ?@Test
          ????public?void?selectByIdOrName()?{
          ????????SqlSession?sqlSession?=?null;
          ????????sqlSession?=?sqlSessionFactory.openSession();
          ????????StudentMapper?studentMapper?=?sqlSession.getMapper(StudentMapper.class);

          ????????Student?student?=?new?Student();
          ????????student.setName("小飛機(jī)");
          ????????student.setStudentId(1);

          ????????Student?studentById?=?studentMapper.selectByIdOrName(student);
          ????????System.out.println("有?ID?則根據(jù)?ID?獲取");
          ????????System.out.println(ToStringBuilder.reflectionToString(studentById,?ToStringStyle.MULTI_LINE_STYLE));

          ????????student.setStudentId(null);
          ????????Student?studentByName?=?studentMapper.selectByIdOrName(student);
          ????????System.out.println("沒(méi)有?ID?則根據(jù)?name?獲取");
          ????????System.out.println(ToStringBuilder.reflectionToString(studentByName,?ToStringStyle.MULTI_LINE_STYLE));

          ????????student.setName(null);
          ????????Student?studentNull?=?studentMapper.selectByIdOrName(student);
          ????????System.out.println("沒(méi)有?ID?和?name,?返回?null");
          ????????Assert.assertNull(studentNull);

          ????????sqlSession.commit();
          ????????sqlSession.close();
          ????}

          有 ID 則根據(jù) ID 獲取, 結(jié)果

          有 ID 則根據(jù) ID 獲取

          沒(méi)有 ID 則根據(jù) name 獲取

          沒(méi)有 ID 則根據(jù) name 獲取

          沒(méi)有 ID 和 name, 返回 null

          沒(méi)有 ID 和 name, 返回 null

          4 trim(set、where)

          這三個(gè)其實(shí)解決的是類似的問(wèn)題。如我們?cè)趯懬懊娴腫在 WHERE 條件中使用 if 標(biāo)簽] SQL 的時(shí)候, where 1=1 這個(gè)條件我們是不希望存在的。

          4.1 where

          4.1.1 查詢條件

          根據(jù)輸入的學(xué)生信息進(jìn)行條件檢索。

          1. 當(dāng)只輸入用戶名時(shí), 使用用戶名進(jìn)行模糊檢索;
          2. 當(dāng)只輸入性別時(shí), 使用性別進(jìn)行完全匹配
          3. 當(dāng)用戶名和性別都存在時(shí), 用這兩個(gè)條件進(jìn)行查詢匹配查詢

          不使用 where 1=1

          4.1.2 動(dòng)態(tài) SQL

          很顯然, 我們要解決這幾個(gè)問(wèn)題

          • 當(dāng)條件都不滿足時(shí):此時(shí) SQL 中應(yīng)該要不能有 where , 否則導(dǎo)致出錯(cuò)
          • 當(dāng) if 有條件滿足時(shí):SQL 中需要有 where, 且第一個(gè)成立的 if 標(biāo)簽下的 and | or 等要去掉

          這時(shí)候, 我們可以使用 where 標(biāo)簽。

          接口方法

          ????/**
          ?????*?根據(jù)輸入的學(xué)生信息進(jìn)行條件檢索
          ?????* 1. 當(dāng)只輸入用戶名時(shí),?使用用戶名進(jìn)行模糊檢索;
          ?????*?2.?當(dāng)只輸入郵箱時(shí),?使用性別進(jìn)行完全匹配
          ?????*?3.?當(dāng)用戶名和性別都存在時(shí),?用這兩個(gè)條件進(jìn)行查詢匹配的用
          ?????*/
          ????List?selectByStudentSelectiveWhereTag(Student?student);

          對(duì)應(yīng)的 SQL

          ??"selectByStudentSelectiveWhereTag"?resultMap="BaseResultMap"?parameterType="com.homejim.mybatis.entity.Student">
          ????select
          ????"Base_Column_List"?/>
          ????from?student
          ???<where>
          ????<if?test="name?!=?null?and?name?!=''">
          ??????and?name?like?concat('%',?#{name},?'%')
          ????if>
          ????<if?test="sex?!=?null">
          ??????and?sex=#{sex}
          ????if>
          ???where>
          ??

          4.1.3 測(cè)試

          ????
          ????@Test
          ????public?void?selectByStudentWhereTag()?{
          ????????SqlSession?sqlSession?=?null;
          ????????sqlSession?=?sqlSessionFactory.openSession();
          ????????StudentMapper?studentMapper?=?sqlSession.getMapper(StudentMapper.class);

          ????????Student?search?=?new?Student();
          ????????search.setName("明");

          ????????System.out.println("只有名字時(shí)的查詢");
          ????????List?studentsByName?=?studentMapper.selectByStudentSelectiveWhereTag(search);
          ????????for?(int?i?=?0;?i?????????????System.out.println(ToStringBuilder.reflectionToString(studentsByName.get(i),?ToStringStyle.MULTI_LINE_STYLE));
          ????????}
          ????????
          ????????search.setSex((byte)?1);
          ????????System.out.println("姓名和性別同時(shí)存在的查詢");
          ????????List?studentsBySex?=?studentMapper.selectByStudentSelectiveWhereTag(search);
          ????????for?(int?i?=?0;?i?????????????System.out.println(ToStringBuilder.reflectionToString(studentsBySex.get(i),?ToStringStyle.MULTI_LINE_STYLE));
          ????????}

          ????????System.out.println("姓名和性別都不存在時(shí)查詢");
          ????????search.setName(null);
          ????????search.setSex(null);
          ????????List?studentsByNameAndSex?=?studentMapper.selectByStudentSelectiveWhereTag(search);
          ????????for?(int?i?=?0;?i?????????????System.out.println(ToStringBuilder.reflectionToString(studentsByNameAndSex.get(i),?ToStringStyle.MULTI_LINE_STYLE));
          ????????}

          ????????sqlSession.commit();
          ????????sqlSession.close();
          ????}

          只有名字時(shí)的查詢, 有 where

          只有名字時(shí)的查詢

          姓名和性別同時(shí)存在的查詢, 有 where

          姓名和性別同時(shí)存在的查詢

          姓名和性別都不存在時(shí)查詢, 此時(shí), where 不會(huì)再出現(xiàn)了。

          姓名和性別都不存在時(shí)查詢

          4.2 set

          set 標(biāo)簽也類似, 在 [2.2 在 UPDATE 更新列中使用 if 標(biāo)簽] 中, 如果我們的方法 updateByPrimaryKeySelective 沒(méi)有使用 標(biāo)簽, 那么我們就要想辦法處理字段全為空的條件, 字段不為空的條件等。有了這個(gè), 我們只需要寫 if 標(biāo)簽即可, 不需要處理類似的問(wèn)題。

          4.3 trim

          set 和 where 其實(shí)都是 trim 標(biāo)簽的一種類型, 該兩種功能都可以使用 trim 標(biāo)簽進(jìn)行實(shí)現(xiàn)。

          4.3.1 trim 來(lái)表示 where

          如以上的 where 標(biāo)簽, 我們也可以寫成

          "where"?prefixOverrides="AND?|OR">

          表示當(dāng) trim 中含有內(nèi)容時(shí), 添加 where, 且第一個(gè)為 and 或 or 時(shí), 會(huì)將其去掉。而如果沒(méi)有內(nèi)容, 則不添加 where。

          4.3.2 trim 來(lái)表示 set

          相應(yīng)的, set 標(biāo)簽可以如下表示

          "SET"?suffixOverrides=",">

          表示當(dāng) trim 中含有內(nèi)容時(shí), 添加 set, 且最后的內(nèi)容為 , 時(shí), 會(huì)將其去掉。而沒(méi)有內(nèi)容, 不添加 set

          4.3.3 trim 的幾個(gè)屬性

          • prefix: 當(dāng) trim 元素包含有內(nèi)容時(shí), 增加 prefix 所指定的前綴
          • prefixOverrides: 當(dāng) trim 元素包含有內(nèi)容時(shí), 去除 prefixOverrides 指定的 前綴
          • suffix: 當(dāng) trim 元素包含有內(nèi)容時(shí), 增加 suffix 所指定的后綴
          • suffixOverrides:當(dāng) trim 元素包含有內(nèi)容時(shí), 去除 suffixOverrides 指定的后綴

          5 foreach 標(biāo)簽

          foreach 標(biāo)簽可以對(duì)數(shù)組, Map 或?qū)崿F(xiàn) Iterable 接口。

          foreach 中有以下幾個(gè)屬性

          • collection: 必填, 集合/數(shù)組/Map的名稱.
          • item: 變量名。即從迭代的對(duì)象中取出的每一個(gè)值
          • index: 索引的屬性名。當(dāng)?shù)膶?duì)象為 Map 時(shí), 該值為 Map 中的 Key.
          • open: 循環(huán)開(kāi)頭的字符串
          • close: 循環(huán)結(jié)束的字符串
          • separator: 每次循環(huán)的分隔符

          其他的比較好理解, collection 中的值應(yīng)該怎么設(shè)定呢?

          跟接口方法中的參數(shù)相關(guān)。

          1. 只有一個(gè)數(shù)組參數(shù)或集合參數(shù)

          默認(rèn)情況:集合collection=list, 數(shù)組是collection=array

          推薦:使用 @Param 來(lái)指定參數(shù)的名稱, 如我們?cè)趨?shù)前@Param("ids"), 則就填寫 collection=ids

          2. 多參數(shù)

          多參數(shù)請(qǐng)使用 @Param 來(lái)指定, 否則SQL中會(huì)很不方便

          3. 參數(shù)是Map

          指定為 Map 中的對(duì)應(yīng)的 Key 即可。其實(shí)上面的 @Param 最后也是轉(zhuǎn)化為 Map 的。

          4. 參數(shù)是對(duì)象

          使用屬性.屬性即可。

          5.1 在 where 中使用 foreach

          在 where條件中使用, 如按id集合查詢, 按id集合刪除等。

          5.1.1 查詢條件

          我們希望查詢用戶 id 集合中的所有用戶信息。

          5.1.2 動(dòng)態(tài) SQL

          函數(shù)接口

          ????/**
          ?????*?獲取?id?集合中的用戶信息
          ?????*?@param?ids
          ?????*?@return
          ?????*/
          ????List?selectByStudentIdList(List?ids);

          對(duì)應(yīng) SQL

          ??"selectByStudentIdList"?resultMap="BaseResultMap">
          ????select
          ????"Base_Column_List"?/>
          ????from?student
          ????where?student_id?in
          ????"list"?item="id"?open="("?close=")"?separator=","?index="i">
          ??????#{id}
          ????
          ??

          5.1.3 測(cè)試

          ????@Test
          ????public?void?selectByStudentIdList()?{
          ????????SqlSession?sqlSession?=?null;
          ????????sqlSession?=?sqlSessionFactory.openSession();
          ????????StudentMapper?studentMapper?=?sqlSession.getMapper(StudentMapper.class);

          ????????List?ids?=?new?LinkedList<>();
          ????????ids.add(1);
          ????????ids.add(3);

          ????????List?students?=?studentMapper.selectByStudentIdList(ids);
          ????????for?(int?i?=?0;?i?????????????System.out.println(ToStringBuilder.reflectionToString(students.get(i),?ToStringStyle.MULTI_LINE_STYLE));
          ????????}

          ????????sqlSession.commit();
          ????????sqlSession.close();
          ????}

          結(jié)果

          在 where 中使用 foreach

          5.2 foreach 實(shí)現(xiàn)批量插入

          可以通過(guò)foreach來(lái)實(shí)現(xiàn)批量插入。

          5.2.1 動(dòng)態(tài)SQL

          接口方法

          ????/**
          ?????*?批量插入學(xué)生
          ?????*/
          ????int?insertList(List?students);

          對(duì)應(yīng)的SQL

          ??"insertList">
          ????insert?into?student(name,?phone,?email,?sex,?locked)
          ????values
          ????"list"?item="student"?separator=",">
          ??????(
          ??????#{student.name},?#{student.phone},#{student.email},
          ??????#{student.sex},#{student.locked}
          ??????)
          ????
          ??

          5.2.2 測(cè)試

          ????@Test
          ????public?void?insertList()?{
          ????????SqlSession?sqlSession?=?null;
          ????????sqlSession?=?sqlSessionFactory.openSession();
          ????????StudentMapper?studentMapper?=?sqlSession.getMapper(StudentMapper.class);

          ????????List?students?=?new?LinkedList<>();
          ????????Student?stu1?=?new?Student();
          ????????stu1.setName("批量01");
          ????????stu1.setPhone("13888888881");
          ????????stu1.setLocked((byte)?0);
          ????????stu1.setEmail("[email protected]");
          ????????stu1.setSex((byte)?1);
          ????????students.add(stu1);

          ????????Student?stu2?=?new?Student();
          ????????stu2.setName("批量02");
          ????????stu2.setPhone("13888888882");
          ????????stu2.setLocked((byte)?0);
          ????????stu2.setEmail("[email protected]");
          ????????stu2.setSex((byte)?0);
          ????????students.add(stu2);

          ????????System.out.println(studentMapper.insertList(students));
          ????????sqlSession.commit();
          ????????sqlSession.close();
          ????}

          結(jié)果

          foreach 實(shí)現(xiàn)批量插入

          6 bind 標(biāo)簽

          bind 標(biāo)簽是通過(guò) OGNL 表達(dá)式去定義一個(gè)上下文的變量, 這樣方便我們使用。

          如在 selectByStudentSelective 方法中, 有如下

          <if?test="name?!=?null?and?name?!=''">
          ??????and?name?like?concat('%',?#{name},?'%')
          ????if>

          在 MySQL 中, 該函數(shù)支持多參數(shù), 但在 Oracle 中只支持兩個(gè)參數(shù)。那么我們可以使用 bind 來(lái)讓該 SQL 達(dá)到支持兩個(gè)數(shù)據(jù)庫(kù)的作用

          <if?test="name?!=?null?and?name?!=''">
          ?????<bind?name="nameLike"?value="'%'+name+'%'"/>
          ?????and?name?like?#{nameLike}
          if>

          更改后的查詢結(jié)果如下

          bind 標(biāo)簽的使用

          END


          有熱門推薦?

          1.?天天在用 Stream,那你知道如此強(qiáng)大的 Stream 的實(shí)現(xiàn)原理嗎?

          2.?kill -9 進(jìn)程殺不掉,怎么辦?

          3.?Java 集合框架綜述,這篇讓你吃透!

          4.?一套簡(jiǎn)單通用的Java后臺(tái)管理系統(tǒng),拿來(lái)即用,非常方便(附項(xiàng)目地址)

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù)?Java?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。

          謝謝支持喲 (*^__^*)

          瀏覽 40
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本天堂在线视频 | 99精品在线 | 国产灌醉| 午夜一区二区三区免费视频 | 一级片在线免费看 |