學(xué)習(xí)完Mybatis的基本操作之后,繼續(xù)學(xué)習(xí)Mybatis—XML配置文件、動態(tài)SQL。
Mybatis的XML配置文件
Mybatis的開發(fā)有兩種方式:
- 注解
- XML
之前學(xué)習(xí)的基本操作都是基于注解開發(fā)。使用Mybatis的注解方式,主要是來完成一些簡單的增刪改查功能。如果需要實現(xiàn)復(fù)雜的SQL功能,建議使用XML來配置映射語句,也就是將SQL語句寫在XML配置文件中。
XML配置文件規(guī)范
在Mybatis中使用XML映射文件方式開發(fā),需要符合一定的規(guī)范:
1. XML映射文件的名稱與Mapper接口名稱一致,并且將XML映射文件和Mapper接口放置在相同包下
(同包同名)
2. XML映射文件的namespace屬性為Mapper接口全限定名一致
3. XML映射文件中sql語句的id與Mapper接口中的方法名一致,并保持返回類型一致。
<select>標(biāo)簽:就是用于編寫select查詢語句的。
resultType屬性,指的是查詢返回的單條記錄所封裝的類型。
XML配置文件實現(xiàn)
第1步:創(chuàng)建XML映射文件
切記!: 在resource創(chuàng)建包時要用/分割符,如com/itheima/mapper,這樣才是在resource文件夾下創(chuàng)建了com文件夾,然后com文件夾里創(chuàng)建了itheima文件夾,如果創(chuàng)建包時復(fù)制路徑選錯,選擇復(fù)制了引用:com.itheima.mapper,那就只是在resource下創(chuàng)建了一個名字為“com.itheima.mapper”的子包,這樣系統(tǒng)就會報錯找不到XML映射文件!
第2步:編寫XML映射文件
xml映射文件中的dtd約束,直接從mybatis官網(wǎng)復(fù)制即可:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">
</mapper>
配置:XML映射文件的namespace屬性為Mapper接口全限定名
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
</mapper>
配置:XML映射文件中sql語句的id與Mapper接口中的方法名一致,并保持返回類型一致
最終xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
<!--查詢操作-->
<select id="list" resultType="com.itheima.pojo.Emp">
select * from emp
where name like concat('%',#{name},'%')
and gender = #{gender}
and entrydate between #{begin} and #{end}
order by update_time desc
</select>
</mapper>
將Mapper接口中的select注解注釋掉,只保留接口方法,運(yùn)行測試類可發(fā)現(xiàn)與上一節(jié)中使用注解查詢的方法運(yùn)行結(jié)果相同。
MybatisX的使用
MybatisX是一款基于IDEA的快速開發(fā)Mybatis的插件,為效率而生。
MybatisX的安裝:
可以通過MybatisX快速定位:
MybatisX的使用在后續(xù)學(xué)習(xí)中會繼續(xù)分享
Mybatis動態(tài)SQL
SQL語句會隨著用戶的輸入或外部條件的變化而變化,我們稱為:動態(tài)SQL。
在頁面原型中,列表上方的條件是動態(tài)的,是可以不傳遞的,也可以只傳遞其中的1個或者2個或者全部:
而在我們剛才編寫的SQL語句中,我們會看到,我們將三個條件直接寫死了。 如果頁面只傳遞了參數(shù)姓名name 字段,其他兩個字段 性別 和 入職時間沒有傳遞,那么這兩個參數(shù)的值就是null:
正確的做法應(yīng)該是:傳遞了參數(shù),再組裝這個查詢條件;如果沒有傳遞參數(shù),就不應(yīng)該組裝這個查詢條件。
比如:如果姓名輸入了"張", 對應(yīng)的SQL為:
select * from emp where name like '%張%' order by update_time desc;
如果姓名輸入了"張",,性別選擇了"男",則對應(yīng)的SQL為:
select * from emp where name like '%張%' and gender = 1 order by update_time desc;
在Mybatis中提供了很多實現(xiàn)動態(tài)SQL的標(biāo)簽,我們學(xué)習(xí)Mybatis中的動態(tài)SQL就是掌握這些動態(tài)SQL標(biāo)簽。
動態(tài)SQL-if
<if> :用于判斷條件是否成立。使用test屬性進(jìn)行條件判斷,如果條件為true,則拼接SQL。
<if test="條件表達(dá)式">
要拼接的sql語句
</if>
條件查詢 <if>與<where>
- 原有的SQL語句
<select id="list" resultType="com.itheima.pojo.Emp">
select * from emp
where name like concat('%',#{name},'%')
and gender = #{gender}
and entrydate between #{begin} and #{end}
order by update_time desc
</select>
- 動態(tài)SQL語句
<select id="list" resultType="com.itheima.pojo.Emp">
select * from emp
where
<if test="name != null">
name like concat('%',#{name},'%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="begin != null and end != null">
and entrydate between #{begin} and #{end}
</if>
order by update_time desc
</select>
PS:
如果判斷的類型是字符串類型最好加上空字符串判斷,如:
<if test="username != null and username != ''">
username = #{username},
</if>
測試方法:
@Test
public void testList(){
//性別數(shù)據(jù)為null、開始時間和結(jié)束時間也為null
List<Emp> list = empMapper.list("張", null, null, null);
for(Emp emp : list){
System.out.println(emp);
}
}
下面修改測試方法中的代碼,再次進(jìn)行測試,觀察執(zhí)行情況:
@Test
public void testList(){
//姓名為null
List<Emp> list = empMapper.list(null, (short)1, null, null);
for(Emp emp : list){
System.out.println(emp);
}
}
再次修改測試方法中的代碼,再次進(jìn)行測試:
@Test
public void testList(){
//傳遞的數(shù)據(jù)全部為null
List<Emp> list = empMapper.list(null, null, null, null);
for(Emp emp : list){
System.out.println(emp);
}
}
以上問題的解決方案:使用<where> 標(biāo)簽代替SQL語句中的where關(guān)鍵字。
<where> 只會在子元素有內(nèi)容的情況下才插入where子句,而且會自動去除子句的開頭的AND或OR
<select id="list" resultType="com.itheima.pojo.Emp">
select * from emp
<where>
<!-- if做為where標(biāo)簽的子元素 -->
<if test="name != null">
and name like concat('%',#{name},'%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="begin != null and end != null">
and entrydate between #{begin} and #{end}
</if>
</where>
order by update_time desc
</select>
測試方法:
@Test
public void testList(){
//只有性別
List<Emp> list = empMapper.list(null, (short)1, null, null);
for(Emp emp : list){
System.out.println(emp);
}
}
更新員工 <set>
動態(tài)更新員工信息,如果更新時傳遞有值,則更新;如果更新時沒有傳遞值,則不更新
解決方案:動態(tài)SQL
修改Mapper接口:
@Mapper
public interface EmpMapper {
//刪除@Update注解編寫的SQL語句
//update操作的SQL語句編寫在Mapper映射文件中
public void update(Emp emp);
}
修改Mapper映射文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
<!--更新操作-->
<update id="update">
update emp
set
<if test="username != null">
username=#{username},
</if>
<if test="name != null">
name=#{name},
</if>
<if test="gender != null">
gender=#{gender},
</if>
<if test="image != null">
image=#{image},
</if>
<if test="job != null">
job=#{job},
</if>
<if test="entrydate != null">
entrydate=#{entrydate},
</if>
<if test="deptId != null">
dept_id=#{deptId},
</if>
<if test="updateTime != null">
update_time=#{updateTime}
</if>
where id=#{id}
</update>
</mapper>
測試方法:
@Test
public void testUpdate2(){
//要修改的員工信息
Emp emp = new Emp();
emp.setId(20);
emp.setUsername("Tom222");
//調(diào)用方法,修改員工數(shù)據(jù)
empMapper.update(emp);
}
以上問題的解決方案:使用<set> 標(biāo)簽代替SQL語句中的set關(guān)鍵字
<set> :動態(tài)的在SQL語句中插入set關(guān)鍵字,并會刪掉額外的逗號。(用于update語句中)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
<!--更新操作-->
<update id="update">
update emp
<!-- 使用set標(biāo)簽,代替update語句中的set關(guān)鍵字 -->
<set>
<if test="username != null">
username=#{username},
</if>
<if test="name != null">
name=#{name},
</if>
<if test="gender != null">
gender=#{gender},
</if>
<if test="image != null">
image=#{image},
</if>
<if test="job != null">
job=#{job},
</if>
<if test="entrydate != null">
entrydate=#{entrydate},
</if>
<if test="deptId != null">
dept_id=#{deptId},
</if>
<if test="updateTime != null">
update_time=#{updateTime}
</if>
</set>
where id=#{id}
</update>
</mapper>
再次執(zhí)行測試方法,執(zhí)行的SQL語句:
小結(jié)
-
<if>
-
用于判斷條件是否成立,如果條件為true,則拼接SQL
-
形式:
<if test="name != null"> … </if>
-
-
<where>
- where元素只會在子元素有內(nèi)容的情況下才插入where子句,而且會自動去除子句的開頭的AND或OR
-
<set>
- 動態(tài)地在行首插入 SET 關(guān)鍵字,并會刪掉額外的逗號。(用在update語句中)
動態(tài)SQL-<foreach>
案例:員工刪除功能(既支持刪除單條記錄,又支持批量刪除)
SQL語句:
delete from emp where id in (1,2,3);
Mapper接口:
@Mapper
public interface EmpMapper {
//批量刪除
public void deleteByIds(List<Integer> ids);
}
XML映射文件:
- 使用
<foreach>
遍歷deleteByIds方法中傳遞的參數(shù)ids集合
<foreach collection="集合名稱" item="集合遍歷出來的元素/項" separator="每一次遍歷使用的分隔符"
open="遍歷開始前拼接的片段" close="遍歷結(jié)束后拼接的片段">
</foreach>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
<!--刪除操作-->
<delete id="deleteByIds">
delete from emp where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
</mapper>
測試類:
@SpringBootTest
class SpringbootMybatisCrudApplicationTests {
@Autowired
private EmpMapper empMapper;
@Test
public void testUpdate2(){
//要修改的員工id
List<Integer> ids = Arrays.asList(1,2,3);
//調(diào)用方法,修改員工數(shù)據(jù)
empMapper.deleteByIds(ids);
}
}
執(zhí)行的SQL語句:
動態(tài)SQL-<sql>&<include>
問題:在xml映射文件中配置的SQL,有時可能會存在很多重復(fù)的片段,此時就會存在很多冗余的代碼
我們可以對重復(fù)的代碼片段進(jìn)行抽取,將其通過<sql>
標(biāo)簽封裝到一個SQL片段,然后再通過<include>
標(biāo)簽進(jìn)行引用。
-
<sql>
:定義可重用的SQL片段 -
<include>
:通過屬性refid,指定包含的SQL片段
SQL片段: 抽取重復(fù)的代碼
然后通過<include>
標(biāo)簽在原來抽取的地方進(jìn)行引用。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.mapper.EmpMapper">
<sql id="commonSelect">
select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp
</sql>
<select id="list" resultType="com.itheima.pojo.Emp">
<include refid="commonSelect"/>
<where>
<if test="name != null">
name like concat('%',#{name},'%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="begin != null and end != null">
and entrydate between #{begin} and #{end}
</if>
</where>
order by update_time desc
</select>
</mapper>
動態(tài)SQL中的特殊符號(大于,小于,不等于)使用注意事項
大于(>,>=)、小于(<,<=)、不等于(<> ,!=)符號包含了尖括號,Mybatis使用的 *.xml文件格式。于是需要進(jìn)行相關(guān)的轉(zhuǎn)義或者使用 CDATA 區(qū)段。嚴(yán)格地講,在 XML 中僅有字符 “<“和”&” 是非法的。省略號、引號和大于號是合法的,但是把它們都替換為實體引用是個好的習(xí)慣。文章來源:http://www.zghlxwxcb.cn/news/detail-736314.html
可以參考java特殊文件 屬性文件properties和XML文件,和Mybatis 特殊符號(大于,小于,不等于)及常用函數(shù)總結(jié)文章來源地址http://www.zghlxwxcb.cn/news/detail-736314.html
到了這里,關(guān)于Mybatis—XML配置文件、動態(tài)SQL的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!