Mybatis學習筆記(六) —— 動態sql
通過mybatis提供的各種標籤方法實現動態拼接sql。
需求:根據性別和名字查詢使用者
查詢sql:
SELECT id, username, birthday, sex, address FROM `user` WHERE sex = 1 AND username LIKE '%張%'
一、if標籤
1.1 Mapper.xml檔案
UserMapper.xml配置sql,如下:
<!-- 根據條件查詢使用者 --> <select id="queryUserByWhere" parameterType="user" resultType="user"> SELECT id, username, birthday, sex, address FROM `user` WHERE sex = #{sex} AND username LIKE '%${username}%' </select>
1.2 Mapper介面
/** * 根據條件查詢使用者 * @param user * @return */ List<User> queryUserByWhere(User user);
1.3 測試方法
@Test public void testQueryUserByWhere() throws Exception { // mybatis和spring整合,整合之後,交給spring管理 SqlSession sqlSession = sqlSessionFactory.openSession(); // 建立Mapper介面的動態代理物件,整合之後,交給spring管理 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 使用userMapper執行根據條件查詢使用者 User user = new User(); user.setSex("男"); user.setUsername("張"); List<User> list = userMapper.queryUserByWhere(user); for (User user2 : list) { System.out.println(user2); } // mybatis和spring整合,整合之後,交給spring管理 sqlSession.close(); }
1.4 效果
如果註釋掉 user.setSex("男"),測試結果如下圖:
測試結果二很顯然不合理。
按照之前所學的,要解決這個問題,需要編寫多個sql,查詢條件越多,需要編寫的sql就更多了,顯然這樣是不靠譜的。
解決方案,使用動態sql的if標籤
1.5 使用if標籤
改造UserMapper.xml,如下:
<!-- 根據條件查詢使用者 --> <select id="queryUserByWhere" parameterType="user" resultType="user"> SELECT id, username, birthday, sex, address FROM `user` WHERE 1=1 <if test="sex != null and sex != ''"> AND sex = #{sex} </if> <if test="username != null and username != ''"> AND username LIKE '%${username}%' </if> </select>
1.6 效果
測試OK
注意:判斷是否為空字串時,單(雙)引號裡面不能填空格,否則會報錯
二、Where標籤
上面的sql還有where 1=1 這樣的語句,很麻煩
可以使用where標籤進行改造
改造UserMapper.xml,如下
<!-- 根據條件查詢使用者 --> <select id="queryUserByWhere" parameterType="user" resultType="user"> SELECT id, username, birthday, sex, address FROM `user` <!-- where標籤可以自動新增where,同時處理sql語句中第一個前AND關鍵字 --> <where> <if test="sex!=null and sex != ' '"> AND sex = #{sex} </if> <if test="username!=null and username != ''"> AND username LIKE '%${username}%' </if> </where> </select>
三、sql片段
Sql中可將重複的sql提取出來,使用時用include引用即可,最終達到sql重用的目的。
把上面例子中的id, username, birthday, sex, address提取出來,作為sql片段,如下:
<!-- 宣告sql片段 --> <sql id="userFields"> id, username, birthday, sex, address </sql> <!-- 根據條件查詢使用者 --> <select id="queryUserByWhere" parameterType="user" resultType="user"> SELECT <include refid="userFields"/> FROM `user` <!-- where標籤可以自動新增where,同時處理sql語句中第一個前AND關鍵字 --> <where> <if test="sex!=null and sex != ' '"> AND sex = #{sex} </if> <if test="username!=null and username != ''"> AND username LIKE '%${username}%' </if> </where> </select>
如果要使用別的Mapper.xml配置的sql片段,可以在refid前面加上對應的Mapper.xml的namespace
四、foreach標籤
向sql傳遞陣列或List,mybatis使用foreach解析
需求:根據多個id查詢使用者資訊
查詢sql:SELECT * FROM user WHERE id IN (1,10,24)
4.1 改造QueryVo
public class QueryVo { // 包含其他的pojo private User user; private List<Integer> ids; get/set... }
4.2 Mapper.xml檔案
UserMapper.xml新增sql:
<!-- 根據ids查詢使用者 --> <select id="queryUserByIds" parameterType="queryVo" resultType="user"> SELECT * FROM `user` <where> <!-- foreach標籤,進行遍歷 --> <!-- collection:遍歷的集合,這裡是QueryVo的ids屬性 --> <!-- item:遍歷的專案,可以隨便寫,,但是和後面的#{}裡面要一致 --> <!-- open:在前面新增的sql片段 --> <!-- close:在結尾處新增的sql片段 --> <!-- separator:指定遍歷的元素之間使用的分隔符 --> <foreach collection="ids" item="item" open="id IN (" close=")" separator=","> #{item} </foreach> </where> </select>
4.3 Mapper介面
在UserMapper介面中新增方法:
/** * 根據ids查詢使用者 * @param queryVo * @return */ List<User> queryUserByIds(QueryVo queryVo);
4.4 測試方法
@Test public void testQueryUserByIds() throws Exception { // mybatis和spring整合,整合之後,交給spring管理 SqlSession sqlSession = sqlSessionFactory.openSession(); // 建立Mapper介面的動態代理物件,整合之後,交給spring管理 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); QueryVo queryVo = new QueryVo(); List<Integer> ids = new ArrayList<>(); ids.add(1); ids.add(10); ids.add(16); queryVo.setIds(ids); List<User> list = userMapper.queryUserByIds(queryVo); for (User user : list) { System.out.println(user); } // mybatis和spring整合,整合之後,交給spring管理 sqlSession.close(); }
效果: