MyBatis 的動態 SQL 使用 OGNL 表達式
http://commons.apache.org/proper/commons-ognl/language-guide.html
在 XML 中的一些特殊字符需要轉義,參考 HTML ISO-8859-1 手冊
http://www.w3school.com.cn/tags/html_ref_entities.html
一、IF
https://www.cnblogs.com/jhxxb/p/10637219.html
<select id="selectMyUserByIF" resultType="myUser" parameterType="myUser"> select * from myuser where <if test="id != null"> id = #{id} </if> <if test="name != null && name != """> and name like #{name} </if> <if test="age == 0 or age == 1"> and age = #{age} </if> </select>
入參沒有ID屬性時會報錯,會拼接成 where and,解決:可以在 where 后添加一個恆成立,如 1=1。或者使用 where 標簽,會自動去除 SQL 中多出來的 and 或 or
二、WHERE
<select id="selectMyUserByIF" resultType="myUser" parameterType="myUser"> select * from myuser <where> <if test="id != null"> id = #{id} </if> <if test="name != null and name != ''.toString()"> and name like #{name} </if> <if test="age == 0 or age == 1"> and age = #{age} </if> </where> </select>
where 標簽只能去除第一個 and 或 or,所以不能把條件符號寫多個或寫在后面
三、SET
<update id="updateMyUser" parameterType="myUser"> update myuser <!-- 用作更新 --> <set> <if test="name != null"> name = #{name}, </if> <if test="age != null"> age = #{age} </if> </set> where id = #{id} </update>
四、TRIM
<select id="selectMyUserByIF" resultType="myUser" parameterType="myUser"> select * from myuser <!-- prefix:替換拼接后字符串的前綴,單獨使用則為添加。prefixOverrides:想替換的前綴類容(條件),單獨使用則為刪除 suffix:替換拼接后字符串的后綴,單獨使用則為添加。suffixOverrides:想替換的后綴類容(條件),單獨使用則為刪除 --> <trim prefix="where" prefixOverrides="AND | OR" suffixOverrides="and"> <if test="id != null"> id = #{id} and </if> <if test="name != null and name.trim() != ''"> name like #{name} </if> </trim> </select>
trim 標簽可以替代 where 標簽
<!-- 等效於 where 標簽 --> <trim prefix="WHERE" prefixOverrides="AND |OR "> ... </trim>
trim 標簽也可以替代 set 標簽
<!-- 等效於 set 標簽 --> <trim prefix="set" suffixOverrides=","> ... </trim>
五、CHOOSE
<select id="selectMyUserByIF" resultType="myUser" parameterType="myUser"> select * from myuser <where> <!-- 類似於 if-else if-else 分支結構 --> <choose> <when test="id != null"> id = #{id} </when> <when test="name != null and name.trim() != ''"> name like #{name} </when> <otherwise> age = 22 </otherwise> </choose> </where> </select>
六、FOREACH
Map 入參
<!--public List<MyUser> selectMyUserByArray(Map<String,Object> maps);--> <select id="selectMyUserByArray" resultType="myUser"> select * from myuser where id in <!-- collection:指定要遍歷的集合或數組(list 和 array 參數都會特殊處理封裝在 Map 中,Map 的 key 默認為 list 或 array) 入參為單個 list 或 array 時 collection 值默認為 list 或 array,若接口方法指定了 @Param 注解,則為 @Param 的值 入參為多個參數可以封裝為 Map,collection 值為 Map 中集合或數組對應的 key 的值(Map 的 key 最好為 String 類型) open:給結果拼接一個前綴 close:給結果拼接一個后綴 item:集合中每一個元素在迭代時的別名,#{item} 取出變量的值,也就是當前遍歷出的元素 separator:每個元素之間的分隔符 index:索引 遍歷 list 或 arrays 時,index 是當前索引(下標),item 為索引對應的值 遍歷 map 時 index 表示 map 的 key,item 為 map 的 value --> <foreach collection="ids" item="item" index="index" separator="," open="(" close=")"> #{item} </foreach> </select>
測試代碼
public static void main(String[] args) { SqlSession session = null; try { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); session = sqlSessionFactory.openSession(); MyUserMapper mapper = session.getMapper(MyUserMapper.class); Map<String,Object> ids = new HashMap<>(10); ids.put("ids",Arrays.asList(7,8,9,10)); ids.put("b",8); System.out.println(mapper.selectMyUserByArray(ids)); } catch (IOException e) { e.printStackTrace(); } finally { if (session != null) { session.close(); } } }
List 入參
<!--public List<MyUser> selectMyUserByArray(List<Integer> ids);--> <select id="selectMyUserByArray" resultType="myUser"> select * from myuser where id in <foreach collection="list" item="item" index="index" separator="," open="(" close=")"> #{item} </foreach> </select>
Array 入參
<!--public List<MyUser> selectMyUserByArray(Integer[] ids);--> <select id="selectMyUserByArray" resultType="myUser"> select * from myuser <foreach collection="array" item="item" index="index" separator="," open="where id in (" close=",20)"> #{item} </foreach> </select>
七、內置參數
<!-- 不只是方法傳遞過來的參數可以被用來判斷和取值,mybatis 默認還有兩個內置參數。 _parameter:代表整個參數 單個參數:_parameter 就是這個參數 多個參數:參數會被封裝為一個 map,_parameter 就代表這個 map _databaseId:如果配置了 databaseIdProvider 標簽,_databaseId 代表當前數據庫的別名 --> <select id="selectMyUserById" resultType="myUser"> <if test="_databaseId == 'mysql'"> select * from myuser <if test="_parameter != null"> where id = #{_parameter} </if> </if> <if test="_databaseId == 'oracle'"> select * from oracle_myuser <if test="_parameter != null"> where name = #{_parameter.name} </if> </if> </select>
八、BIND
<select id="selectMyUserByNameLike" resultType="myUser" parameterType="string"> select * from myuser where name like #{name} </select>
例 SQL 映射想變為模糊查詢有幾種方式
1.傳入參數時加上 %
2.改用 ${name} 來取值。name 取值會報錯,用 _parameter 取值
<select id="selectMyUserByNameLike" resultType="myUser"> select * from myuser where name like '%${_parameter}%' </select>
3.使用 bind 標簽
<select id="selectMyUserByNameLike" resultType="myUser"> <!-- bind:可以將OGNL表達式的值綁定到一個變量中,方便后來引用這個變量的值 --> <bind name="_name" value="'%'+_parameter+'%'"/> select * from myuser where name like #{_name} </select>
九、SQL 復用
<!-- 抽取可重用的sql片段。方便后面引用,使用 include 標簽來引用已經抽取的 sql include 中可以自定義一些 property,sql 標簽內部就能使用自定義的屬性 include-property:取值用 ${prop}, 使用 #{prop} 不能取出,無法預編譯 --> <sql id="columnNames"> <if test="_databaseId=='mysql'"> ${id},name,age </if> <if test="_databaseId=='oracle'"> xxx,xxx,xxx </if> </sql> <select id="selectMyUserByNameLike" resultType="myUser" parameterType="string"> select <include refid="columnNames"> <property name="id" value="id"/> </include> from myuser where name like #{name} </select>
可以使用其他語言來寫動態 SQL:MyBatis-Velocity、MyBatis-FreeMarker 和自帶的 XML
http://www.mybatis.org/velocity-scripting/
http://www.mybatis.org/freemarker-scripting/