什麼是動態SQL?
動態sql是mybatis的核心,主要是對sql語句進行靈活操作,通過表達式進行判斷,對sql進行靈活的拼接、組裝。
實例
用戶信息綜合查詢列表和用戶信息查詢列表總數這兩個statement的定義使用動態sql。對查詢條件進行判斷,如果輸入參數不爲空才進行查詢條件拼接。
Mapper.xml
<!-- 用戶信息綜合查詢
#{userCustom.sex}:取出pojo包裝對象中性別值
${userCustom.username}:取出pojo包裝對象中用戶名稱
-->
<select id="findUserList" parameterType="cn.itcast.mybatis.po.UserQueryVo"
resultType="cn.itcast.mybatis.po.UserCustom">
SELECT * FROM USER
<!--
where可以自動去掉條件中的第一個and
-->
<where>
<if test="userCustom!=null">
<if test="userCustom.sex!=null and userCustom.sex!=''">
and user.sex = #{userCustom.sex}
</if>
<if test="userCustom.username!=null and userCustom.username!=''">
and user.username LIKE '%${userCustom.username}%'
</if>
</if>
</where>
</select>
<select id="findUserCount" parameterType="cn.itcast.mybatis.po.UserQueryVo" resultType="int">
SELECT count(*) FROM USER
<!--
where可以自動去掉條件中的第一個and
-->
<where>
<if test="userCustom!=null">
<if test="userCustom.sex!=null and userCustom.sex!=''">
and user.sex = #{userCustom.sex}
</if>
<if test="userCustom.username!=null and userCustom.username!=''">
and user.username LIKE '%${userCustom.username}%'
</if>
</if>
</where>
</select>
測試代碼
//用戶信息的綜合 查詢
@Test
public void testFindUserList() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
//創建UserMapper對象,mybatis自動生成mapper代理對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//創建包裝對象,設置查詢條件
UserQueryVo userQueryVo = new UserQueryVo();
UserCustom userCustom = new UserCustom();
//由於這裏使用動態sql,如果不設置某個值,條件不會拼接在sql中
//userCustom.setSex("1");
userCustom.setUsername("小明");
userQueryVo.setUserCustom(userCustom);
//調用userMapper的方法
List<UserCustom> list = userMapper.findUserList(userQueryVo);
System.out.println(list);
}
sql片段
將上邊實現的動態sql判斷代碼塊抽取出來,組成一個sql片段。其它的statement中就可以引用sql片段。方便程序員進行開發。
定義sql片段
<!-- 定義sql片段
id:sql片段的唯 一標識
經驗:是基於單表來定義sql片段,這樣話這個sql片段可重用性才高
在sql片段中不要包括 where
-->
<sql id="query_user_where">
<if test="userCustom!=null">
<if test="userCustom.sex!=null and userCustom.sex!=''">
and user.sex = #{userCustom.sex}
</if>
<if test="userCustom.username!=null and userCustom.username!=''">
and user.username LIKE '%${userCustom.username}%'
</if>
</if>
</sql>
引用sql片段
<!-- 用戶信息綜合查詢
#{userCustom.sex}:取出pojo包裝對象中性別值
${userCustom.username}:取出pojo包裝對象中用戶名稱
-->
<select id="findUserList" parameterType="cn.itcast.mybatis.po.UserQueryVo"
resultType="cn.itcast.mybatis.po.UserCustom">
SELECT * FROM USER
<!--
where可以自動去掉條件中的第一個and
-->
<where>
<!-- 引用sql片段 的id,如果refid指定的id不在本mapper文件中,需要前邊加namespace -->
<include refid="query_user_where"></include>
<!-- 在這裏還要引用其它的sql片段 -->
</where>
</select>
其中的關鍵是這一句引用:
<!-- 引用sql片段 的id,如果refid指定的id不在本mapper文件中,需要前邊加namespace -->
<include refid="query_user_where"></include>
foreach
向sql傳遞數組或List,mybatis使用foreach解析
應用場景
在用戶查詢列表和查詢總數的statement中增加多個id輸入查詢。
類似下面的sql語句:
SELECT * FROM USER WHERE id=1 OR id=10 OR id=16
SELECT * FROM USER WHERE id IN(1,10,16)
在輸入參數類型中添加List ids傳入多個id
public class UserQueryVo {
//傳入多個id
private List<Integer> ids;
修改Mapper.xml
WHERE id=1 OR id=10 OR id=16,在查詢條件中,查詢條件定義成一個sql片段,需要修改sql片段。
<if test="ids!=null">
<!-- 使用 foreach遍歷傳入ids
collection:指定輸入 對象中集合屬性
item:每個遍歷生成對象中
open:開始遍歷時拼接的串
close:結束遍歷時拼接的串
separator:遍歷的兩個對象中需要拼接的串
-->
<!-- 使用實現下邊的sql拼接:
AND (id=1 OR id=10 OR id=16)
-->
<foreach collection="ids" item="user_id" open="AND (" close=")" separator="or">
<!-- 每個遍歷需要拼接的串 -->
id=#{user_id}
</foreach>
測試代碼
修改上面的測試方法,傳入多個id進行測試。
//創建包裝對象,設置查詢條件
UserQueryVo userQueryVo = new UserQueryVo();
UserCustom userCustom = new UserCustom();
//由於這裏使用動態sql,如果不設置某個值,條件不會拼接在sql中
//userCustom.setSex("1");
userCustom.setUsername("小明");
//傳入多個id
List<Integer> ids = new ArrayList<Integer>();
ids.add(1);
ids.add(10);
ids.add(16);
//將ids通過userQueryVo傳入statement中
userQueryVo.setIds(ids);
userQueryVo.setUserCustom(userCustom);
//調用userMapper的方法
List<UserCustom> list = userMapper.findUserList(userQueryVo);
System.out.println(list);