2. Mybatis的XML配置文件
Mybatis的開發(fā)有兩種方式:
- 注解
- XML
2.1 XML配置文件規(guī)范
使用Mybatis的注解方式,主要是來完成一些簡單的增刪改查功能。如果需要實(shí)現(xiàn)復(fù)雜的SQL功能,建議使用XML來配置映射語句,也就是將SQL語句寫在XML配置文件中。
在Mybatis中使用XML映射文件方式開發(fā),需要符合一定的規(guī)范:
-
XML映射文件的名稱與Mapper接口名稱一致,并且將XML映射文件和Mapper接口放置在相同包下(同包同名)
-
XML映射文件的namespace屬性為Mapper接口全限定名一致
-
XML映射文件中sql語句的id與Mapper接口中的方法名一致,并保持返回類型一致。
<select>標(biāo)簽:就是用于編寫select查詢語句的。
- resultType屬性,指的是查詢返回的單條記錄所封裝的類型。
2.2 XML配置文件實(shí)現(xiàn)
第1步:創(chuà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 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>
運(yùn)行測試類,執(zhí)行結(jié)果:
2.3 MybatisX的使用
MybatisX是一款基于IDEA的快速開發(fā)Mybatis的插件,為效率而生。
MybatisX的安裝:
可以通過MybatisX快速定位:
MybatisX的使用在后續(xù)學(xué)習(xí)中會繼續(xù)分享
學(xué)習(xí)了Mybatis中XML配置文件的開發(fā)方式了,大家可能會存在一個疑問:到底是使用注解方式開發(fā)還是使用XML方式開發(fā)?
官方說明:https://mybatis.net.cn/getting-started.html
**結(jié)論:**使用Mybatis的注解,主要是來完成一些簡單的增刪改查功能。如果需要實(shí)現(xiàn)復(fù)雜的SQL功能,建議使用XML來配置映射語句。
3. Mybatis動態(tài)SQL
3.1 什么是動態(tài)SQL
在頁面原型中,列表上方的條件是動態(tài)的,是可以不傳遞的,也可以只傳遞其中的1個或者2個或者全部。
而在我們剛才編寫的SQL語句中,我們會看到,我們將三個條件直接寫死了。 如果頁面只傳遞了參數(shù)姓名name 字段,其他兩個字段 性別 和 入職時間沒有傳遞,那么這兩個參數(shù)的值就是null。
此時,執(zhí)行的SQL語句為:
這個查詢結(jié)果是不正確的。正確的做法應(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;
SQL語句會隨著用戶的輸入或外部條件的變化而變化,我們稱為:動態(tài)SQL。
在Mybatis中提供了很多實(shí)現(xiàn)動態(tài)SQL的標(biāo)簽,我們學(xué)習(xí)Mybatis中的動態(tài)SQL就是掌握這些動態(tài)SQL標(biāo)簽。
3.2 動態(tài)SQL-if
<if>
:用于判斷條件是否成立。使用test屬性進(jìn)行條件判斷,如果條件為true,則拼接SQL。
<if test="條件表達(dá)式">
要拼接的sql語句
</if>
接下來,我們就通過<if>
標(biāo)簽來改造之前條件查詢的案例。
3.2.1 條件查詢
示例:把SQL語句改造為動態(tài)SQL方式
- 原有的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>
測試方法:
@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);
}
}
執(zhí)行的SQL語句:
下面呢,我們修改測試方法中的代碼,再次進(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);
}
}
執(zhí)行結(jié)果:
再次修改測試方法中的代碼,再次進(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);
}
}
執(zhí)行的SQL語句:
以上問題的解決方案:使用<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);
}
}
執(zhí)行的SQL語句:
3.2.2 更新員工
案例:完善更新員工功能,修改為動態(tài)更新員工數(shù)據(jù)信息
- 動態(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("Tom111");
emp.setName("湯姆111");
emp.setUpdateTime(LocalDateTime.now());
//調(diào)用方法,修改員工數(shù)據(jù)
empMapper.update(emp);
}
執(zhí)行的SQL語句:
再次修改測試方法,觀察SQL語句執(zhí)行情況:
@Test
public void testUpdate2(){
//要修改的員工信息
Emp emp = new Emp();
emp.setId(20);
emp.setUsername("Tom222");
//調(diào)用方法,修改員工數(shù)據(jù)
empMapper.update(emp);
}
執(zhí)行的SQL語句:
以上問題的解決方案:使用<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語句中)
3.3 動態(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="集合遍歷出來的元素/項(xiàng)" 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>
執(zhí)行的SQL語句:
3.4 動態(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ù)的代碼文章來源:http://www.zghlxwxcb.cn/news/detail-789200.html
<sql id="commonSelect">
select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp
</sql>
然后通過<include>
標(biāo)簽在原來抽取的地方進(jìn)行引用。操作如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-789200.html
<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>
到了這里,關(guān)于【JaveWeb教程】(27)Mybatis的XML配置文件與Mybatis動態(tài)SQL 詳細(xì)代碼示例講解的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!