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

1 數(shù)據(jù)準(zhǔn)備
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é)生表';

2 if 標(biāo)簽
2.1 在 WHERE 條件中使用 if 標(biāo)簽
2.1.1 查詢條件
當(dāng)只輸入用戶名時(shí), 使用用戶名進(jìn)行模糊檢索; 當(dāng)只輸入性別時(shí), 使用性別進(jìn)行完全匹配 當(dāng)用戶名和性別都存在時(shí), 用這兩個(gè)條件進(jìn)行查詢匹配查詢
2.1.2 動(dòng)態(tài) SQL
????/**
?????*?根據(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);
??
????<if?test="name?!=?null?and?name?!=''">
??????and?name?like?concat('%',?#{name},?'%')
????if>
????<if?test="sex?!=?null">
??????and?sex=#{sex}
????if>
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();
????}

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

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

where?1=1?and?name?like?concat('%',??,?'%')?and?sex=??
2.2 在 UPDATE 更新列中使用 if 標(biāo)簽
2.2.1 更新條件
2.2.1 動(dòng)態(tài) SQL
????/**
?????*?更新非空屬性
?????*/
????int?updateByPrimaryKeySelective(Student?record);
?? "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();
????}

2.3 在 INSERT 動(dòng)態(tài)插入中使用 if 標(biāo)簽
2.3.1 插入條件
2.3.2 動(dòng)態(tài)SQL
????/**
?????*?非空字段才進(jìn)行插入
?????*/
????int?insertSelective(Student?record);
"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>
????
??
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();
????}

3 choose 標(biāo)簽
3.1 查詢條件
當(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);
??
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();
????}



4 trim(set、where)
4.1 where
4.1.1 查詢條件
當(dāng)只輸入用戶名時(shí), 使用用戶名進(jìn)行模糊檢索; 當(dāng)只輸入性別時(shí), 使用性別進(jìn)行完全匹配 當(dāng)用戶名和性別都存在時(shí), 用這兩個(gè)條件進(jìn)行查詢匹配查詢
4.1.2 動(dòng)態(tài) SQL
當(dāng)條件都不滿足時(shí):此時(shí) SQL 中應(yīng)該要不能有 where , 否則導(dǎo)致出錯(cuò) 當(dāng) if 有條件滿足時(shí):SQL 中需要有 where, 且第一個(gè)成立的 if 標(biāo)簽下的 and | or 等要去掉
????/**
?????*?根據(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);
??
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();
????}



4.2 set
updateByPrimaryKeySelective 沒(méi)有使用 標(biāo)簽, 那么我們就要想辦法處理字段全為空的條件, 字段不為空的條件等。有了這個(gè), 我們只需要寫(xiě) if 標(biāo)簽即可, 不需要處理類似的問(wèn)題。4.3 trim
4.3.1 trim 來(lái)表示 where
"where"?prefixOverrides="AND?|OR">
4.3.2 trim 來(lái)表示 set
"SET"?suffixOverrides=",">
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)簽
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)的分隔符
5.1 在 where 中使用 foreach
5.1.1 查詢條件
5.1.2 動(dòng)態(tài) SQL
????/**
?????*?獲取?id?集合中的用戶信息
?????*?@param?ids
?????*?@return
?????*/
????List?selectByStudentIdList(List ?ids);
??
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();
????}

5.2 foreach 實(shí)現(xiàn)批量插入
5.2.1 動(dòng)態(tài)SQL
????/**
?????*?批量插入學(xué)生
?????*/
????int?insertList(List?students);
?? "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();
????}

6 bind 標(biāo)簽
selectByStudentSelective 方法中, 有如下<if?test="name?!=?null?and?name?!=''">
??????and?name?like?concat('%',?#{name},?'%')
????if>
<if?test="name?!=?null?and?name?!=''">
?????<bind?name="nameLike"?value="'%'+name+'%'"/>
?????and?name?like?#{nameLike}
if>

---END--- 重磅!碼農(nóng)突圍-技術(shù)交流群已成立 掃碼可添加碼農(nóng)突圍助手,可申請(qǐng)加入碼農(nóng)突圍大群和細(xì)分方向群,細(xì)分方向已涵蓋:Java、Python、機(jī)器學(xué)習(xí)、大數(shù)據(jù)、人工智能等群。 一定要備注:開(kāi)發(fā)方向+地點(diǎn)+學(xué)校/公司+昵稱(如Java開(kāi)發(fā)+上海+拼夕夕+猴子),根據(jù)格式備注,可更快被通過(guò)且邀請(qǐng)進(jìn)群 ▲長(zhǎng)按加群 推薦閱讀
? ?我在谷歌,女友在亞馬遜,曬出2人總收入,網(wǎng)友:好酸 ???為什么建議大家使用 Linux 開(kāi)發(fā)?爽(外加七個(gè)感嘆號(hào)) ???華科女博士年薪156萬(wàn)入職華為!最新回應(yīng):在深圳也難買房… ???Mysql,再見(jiàn)吧,select * ! ?? 他曾經(jīng)復(fù)讀才考上三本,如今讓華為開(kāi)出201萬(wàn)年薪(其實(shí)還拒絕了360萬(wàn)offer) ?? 痛惜!才29歲,年輕博士不幸離世 最近面試BAT,整理一份面試資料《Java面試BAT通關(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ù)?BAT?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。 如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝 明天見(jiàn)(??ω??)??
評(píng)論
圖片
表情

