文章目录
- 一、简介
- 二、if标签
- 2.1 if标签的简单使用
- 2.2 where标签
- 2.3 trim标签(了解)
- 三、choose标签 & set标签
- 3.1 choose标签
- 3.2 set标签
- 四、foreach标签
- 4.1 foreach标签的简单使用
- 4.2 批量插入
- 五、内置参数
- 六、bind标签
- 七、sql标签 & include标签
学习地址🔗
- https://www.bilibili.com/video/BV1mW411M737
- https://www.bilibili.com/video/BV1NE411Q7Nx
- 官网文档
一、简介
💬概述:动态SQL——Dynamic SQL,是MyBatis中强大功能之一,可以根据不同条件来拼接SQL语句
🔑实现动态SQL的几个重要标签
- if
- choose(when、otherwise)
- trim(where、set)
- foreach
🔑关于动态SQL中使用到的表达式语言——OGNL
-
全称:Object Graph Navigation Language,对象图导航语言
-
概述:一种强大的表达式语言,使用它可以方便地操作对象属性,类似于EL表达式
-
使用
作用 表达式 访问对象属性 person.name 调用方法 person.getName() 调用静态属性 @java.lang.Math@PI 调用静态方法 @java.util.UUID@randomUUID 调用构造方法 new com.key.mybatis.entity.Person(“Key”).name 算术运算符 +,-,*,/,%等 逻辑运算符 in,not in,and,or,<,>,=,<=,>=,!=,==等 拼接字符串 ‘str1’ + ‘str2’ 💡 在xml文件中,某些敏感字符需要使用其转移字符代替,如逻辑运算符中
<、>等
二、if标签
2.1 if标签的简单使用
💬概述:在SQL映射文件的SQL标签中,可以添加<if>子标签,根据设置的条件动态拼接SQL语句
🔑作用:根据设置的条件动态直接拼接SQL语句,不进行修剪,一般用于动态拼接WHERE子句的查询条件
🔑属性——text(必须设置)
- 作用:使用OGNL表达式来设置条件
- 属性值:OGNL表达式
🔑使用:直接在SQL语句标签内添加<if>,并添加text属性设置条件,<if>标签体内添加动态的语句,当满足text中设置的条件时才会拼上该语句
<!-- id不为null时使用id查询用户信息 -->
<if text="userid != null">
`user_id` = #{userid}
</if>
💡
text的属性值(OGNL表达式)中的userid对应#{Key}中的键Key,即获取参数时的键,需要根据键获取参数值后再来判断是否为null,不是数据库表中的字段名user_id
🔑测试:使用不为null的参数(字段)来查询对应用户信息
-
分析:在书写SQL语句时,不能直接知道传进来的参数值哪一个为null,所以需要对查询的条件进行动态拼接
-
用户持久层接口中添加对应方法
// 根据if标签的条件来查询用户信息 List<User> getUsersByIfCondition(User user); -
用户映射文件
<!-- 根据if标签条件查询 --> <select id="getUsersByIfCondition" resultType="com.key.mybatis.entity.User"> select * from `user` where <!-- 使用if标签动态拼接查询条件 --> <!-- id不为null,用id查询 --> <if test="userid != null"> `user_id` = #{userid} </if> <!-- 姓名不为null,用姓名查询 --> <if test="username != null and username.trim() != ''"> and `user_name` = #{username} </if> <!-- 密码不为null,用密码查询 --> <if test="password != null"> and `password` = #{password}; </if> </select>💡 因为持久层接口的对应方法中形参为
User,即POJO,所以在映射文件中可以直接将User类的属性名作为键Key获取参数值 -
测试方法1.0——只有用户id不为null,则只根据用户id查询
-
方法
// 创建一个用户对象,只有用户id不为null User user = new User(2, null, null); // 调用持久层接口方法 List<User> users = mapper.getUsersByIfCondition(user); users.forEach(System.out :: println); -
打印结果

-
-
测试方法2.0——用户姓名为null,id和密码不为null,则根据id和密码来查询
-
方法
// 创建一个用户对象,用户姓名为null,id和密码不为null User user = new User(2, null, "12444"); // 调用持久层接口方法 List<User> users = mapper.getUsersByIfCondition(user); users.forEach(System.out :: println); -
打印结果

-
-
测试方法3.0——用户id和密码都为null,只有姓名不为null,根据姓名查询
-
方法
// 创建一个用户对象,用户id和密码都为null,只有姓名不为null User user = new User(null, "周慧敏", null); // 调用持久层接口方法 List<User> users = mapper.getUsersByIfCondition(user); users.forEach(System.out :: println); -
打印结果

-
❌报错原因分析:
① 在id为null且姓名不为null情况下,判断id是否为null的
<if>标签体内的查询条件(user_id = #{userid})就不会拼接到SQL语句中,姓名对应的<if>标签体内容会完整拼接到SQL语句中② 姓名对应的
<if>标签体内容是and user_nam = #{username},查询条件前面还多了个and,而它前面已经没有其他查询条件可以拼接,因此最终拼接而成的SQL语句中,where和查询条件之间也会多一个and,该SQL语句很明显不合法,因此报错
🔺 解决方法
① 在每一个
<if>标签体内的查询条件前面都加上and,然后在where子句后加上一个1=1的条件,这样就能保证where子句后面拼上的是条件1=1,而不是多余的and,而且条件1=1恒成立,不会对后面通过and拼起来的查询条件有任何影响,但这种方法仅适用于通过与and连接的查询条件
② 使用<where>标签👇
-
2.2 where标签
❓ 问题引入:在上面对
<if>标签的测试方法3.0中,遇到拼接后的SQL语句不合法的问题,如果只使用<if>标签动态拼接SQL语句中的查询条件,就很难避免这个问题,因此需要使用<where>标签来解决(MyBatis推荐)
💬概述:<where>也是<select>标签的子标签,它能代替查询SQL语句的where子句
🔑作用:代替where子句,将查询条件作为其标签体内容,使查询条件也能动态拼接,即将合法的查询条件前面多余的内容去掉,剩下合法、有用的内容拼接到where子句后
🔑使用限制:<where>只能去掉查询条件前面多余的内容,如果多余的内容在合法查询条件的后面,则无法去掉
🔑测试1.0:传入的用户id和密码都为null,只有姓名不为null,则根据姓名查询用于信息(上面的测试3.0)
-
dao方法不变
List<User> getUsersByIfCondition(User user); -
用户映射文件
<!-- 根据if标签条件查询 --> <select id="getUsersByIfCondition" resultType="com.key.mybatis.entity.User"> select * from `user` <!-- 使用where标签代替where子句 - where标签代替了where子句,因此where就不用再添加 - if标签放在where标签里面 --> <where> <!-- id不为null,用id查询 --> <if test="userid != null"> `user_id` = #{userid} </if> <!-- 姓名不为null,用姓名查询 --> <if test="username != null and username.trim() != ''"> and `user_name` = #{username} </if> <!-- 密码不为null,用密码查询 --> <if test="password != null"> and `password` = #{password}; </if> </where> </select> -
测试方法
// 创建一个用户对象,姓名为null User user = new User(null, "周星驰", null); // 调用持久层接口方法 List<User> users = mapper.getUsersByIfCondition(user); users.forEach(System.out :: println); -
打印结果

🔑测试2.0:修改<if>标签中查询内容的书写,将and放在合法的查询条件后面
-
dao方法与测试方法与上面👆一样
-
映射文件中
<!-- 根据if标签条件查询 --> <select id="getUsersByIfCondition" resultType="com.key.mybatis.entity.User"> select * from `user` <!-- 使用where标签代替where子句 --> <where> <!-- * 注意这里的查询条件中,将'and'放到后面 --> <!-- id不为null,用id查询 --> <if test="userid != null"> `user_id` = #{userid} and </if> <!-- 姓名不为null,用姓名查询 --> <if test="username != null and username.trim() != ''"> `user_name` = #{username} and </if> <!-- 密码不为null,用密码查询 --> <if test="password != null"> `password` = #{password}; </if> </where> </select> -
打印结果

-
分析结果:有打印结果可知,
<where>标签不会将合法的查询条件后面多余的内容去掉,只能去掉前面的,因此最终拼接而成的SQL语句后面还是会有一个多余的and,这也是不合法的SQL语句,因此也报错
2.3 trim标签(了解)
❓ 问题引入:在上面的测试2.0中,可以看到
<where>使用限制——查询条件中多余的内容只能放在前面,如果放在后面就无法去掉,因此最终得到的SQL语句仍然是不合法的,此时可以使用<trim>标签解决
💬概述:<trim>也是SQL语句标签的子标签,与<where>标签使用类似
🔑作用:trim是修剪的意思,也是将查询条件作为其标签体内容,对查询条件中的前缀后缀内容进行修改后再拼接到最终的SQL语句中,因此合法查询条件的前面和后面的多余内容都能去掉
🔑 <trim>中四个属性
| 属性名 | 作用 |
|---|---|
| prefix | 指定拼接后查询条件的前缀 |
| suffix | 指定拼接后查询条件的后缀 |
| prefixOverrides | 指定需要覆盖(去掉)的拼接后查询条件的前缀 |
| suffixOverrides | 指定需要去掉的拼接后查询条件的后缀 |
💡 这里的“拼接后查询条件”是指直接拼接而成、没有被修饰过的拼接结果,可能会带有多余的前缀和后缀
🔑测试:将<if>标签中的and放在合法的查询条件后面,作为后缀,且不添加where子句和<where>标签(在<where>标签测试2.0基础上修改)
-
dao方法和测试方法都与上面👆一样
-
映射文件
<!-- 根据if标签条件查询 --> <select id="getUsersByIfCondition" resultType="com.key.mybatis.entity.User"> select * from `user` <!-- 使用trim标签,修改查询条件的前后缀 - prefix="where":表示在拼接后的查询结果前加上 where - suffixOverrides="and":表示去掉拼接后的查询条件后面的 and --> <trim prefix="where" suffixOverrides="and"> <!-- id不为null,用id查询 --> <if test="userid != null"> `user_id` = #{userid} and </if> <!-- 姓名不为null,用姓名查询 --> <if test="username != null and username.trim() != ''"> `user_name` = #{username} and </if> <!-- 密码不为null,用密码查询 --> <if test="password != null"> `password` = #{password}; </if> </trim> </select> -
打印结果

三、choose标签 & set标签
3.1 choose标签
💬概述:<choose>标签也是SQL语句标签的子标签,表示分支选择的意思,与switch...case使用类似
🔑作用:选择出符合指定条件的唯一内容,即只选择出一种情况
🔑子标签:<choose>标签中无属性,但有两个重要的子标签
| 子标签名 | 属性 | 解释 | 是否必须添加 |
|---|---|---|---|
| when | text:使用OGNL表达式指定选择的条件 | 指定选择的条件,标签体为选择的内容;类似于case;MyBatis会根据<when>标签的添加顺序来匹配条件,一旦有一个满足条件,就不会再匹配后面的<when>标签条件 | 是 |
| otherwise | 无 | 指定默认选择的内容,当所有<when>中指定条件都不满足时就选择<otherwise>标签体中的内容,类似于default | 否 |
🔑使用:直接在SQL语句标签中添加<choose>子标签,然后在<choose>中再添加<when>标签指定选择的条件,根据需要添加<otherwise>标签指定默认选择
<!-- 使用choose根据条件选择其中一种情况 -->
<choose>
<when test="userid != null">
`user_id` = #{userid}
</when>
<when test="username != null">
`user_name` like #{username}
</when>
<!-- 默认选择,如果when条件都不满足,就查询全部信息 -->
<otherwise>
1=1
</otherwise>
</choose>
💡 因为
<choose>标签只会选择出一种情况,因此每一个<when>标签体内的查询条件中不用添加连接词(and、or)
🔑测试:查询用户信息,如果id不为null就只用id查询,如果id为null就只用姓名模糊查询,如果姓名也为空就只用密码查询,如果都为null,则就直接将所有用户信息查出
-
用户dao接口方法
List<User> getUsersByChooseCondition(User user); -
用户映射文件
<!-- 根据choose标签查询 --> <select id="getUsersByChooseCondition" resultType="com.key.mybatis.entity.User"> select * from `user` <!-- 以后都写where标签 --> <where> <!-- 使用choose根据条件选择其中一种情况 --> <choose> <when test="userid != null"> `user_id` = #{userid} </when> <!-- 姓名是模糊查询,用like关键字 --> <when test="username != null and username.trim() != ''"> `user_name` like #{username} </when> <when test="password != null"> `password` = #{password} </when> <!-- 默认选择,如果when条件都不满足,就查询全部信息 --> <otherwise> 1=1 </otherwise> </choose> </where> </select> -
测试方法:id为null,用户姓名带有‘周’字,密码11baa
@Test public void testChooseCondition() { // 获取SqlSession SqlSession sqlSession = MyBatisUtil.getSqlSession(); // 获取mapper对象 UserDao mapper = sqlSession.getMapper(UserDao.class); // 创建一个用户对象,id为null,用户姓名带有‘周’字,密码11baa User user = new User(null, "%周%", "11baa"); // 调用dao方法 List<User> users = mapper.getUsersByChooseCondition(user); users.forEach(System.out :: println); // 关闭sqlSession sqlSession.close(); } -
打印结果

🔺 结果分析:由打印结果可以看出,最终拼出的SQL语句中只有根据姓名模糊查询的条件,即使传入的参数中密码’password’也不为null,但密码对应的
<when>选择条件在姓名后面,因此就不会去匹配密码对应的<when>选择条件
3.2 set标签
💬概述:<set>标签是<update>标签中的子标签,用于代替更新SQL语句中的set子句
🔑作用:代替更新语句中的set子句,选择性拼接set后面的更新内容,可以去掉拼接后的多余内容,一般是,
🔑使用:在<update>标签中添加<set>标签,代替set子句,同时使用<if>根据指定条件动态获取更新内容
<!-- 使用set标签动态拼接更新内容 -->
<set>
<!-- 使用if标签动态获取更新内容 -->
<if test="username != null">
`user_name` = #{username},
</if>
<if test="password != null">
`password` = #{password}
</if>
</set>
❓ 关于去掉拼接后的多余内容
- 如果更新语句中不使用
<set>标签,而是直接使用set子句和<if>标签动态拼接更新内容,则最终拼接的SQL语句有可能在后面多了个,,造成SQL语句不合法。与<where>解决的情况类似- 对于去掉多余的拼接内容,一样能使用
<trim>标签来实现,此时需要添加的前缀prefix="set",需要去掉的后缀suffixOverrides=","(不推荐使用)
🔑测试:修改id为5的用户信息,只修改不为null的字段信息
-
用户dao接口方法
int updateUserBySetCondition(User user); -
用户映射文件
<!-- 使用set标签更新用户信息 --> <update id="updateUserBySetCondition"> update `user` <!-- 使用set标签动态拼接更新内容 --> <set> <!-- 使用if标签动态获取更新内容 --> <if test="username != null"> `user_name` = #{username}, </if> <if test="password != null"> `password` = #{password} </if> </set> <!-- 最后还有查询条件的拼接,使用where --> <where> `user_id` = #{userid} </where> </update> -
测试方法
@Test public void testSetCondition() { // 获取SQlSession SqlSession sqlSession = MyBatisUtil.getSqlSession(); // 获取mapper UserDao mapper = sqlSession.getMapper(UserDao.class); // 创建一个用户对象 User user = new User(5, "周海媚", null); // 调用dao方法 int result = mapper.updateUserBySetCondition(user); if (result == 0) { System.out.println("更新失败!"); } else { System.out.println("更新成功!"); } // 提交事务 sqlSession.commit(); // 关闭sqlSession sqlSession.close(); } -
打印结果

四、foreach标签
4.1 foreach标签的简单使用
💬概述:<foreach>标签也是SQL语句标签的一个子标签,可以实现循环遍历的功能
🔑作用:循环遍历指定的数组或集合,并将遍历后的结果拼接到SQL语句中
🔑属性:<foreach>有下列主要属性
| 属性名 | 属性值 | 解释 | 是否必须添加 |
|---|---|---|---|
| collection | 属性值为需要遍历的集合名称,对应dao接口方法集合类型形参 | 标识出<foreach>中所遍历的集合或数组;如果在dao接口方法中没有为形参命名,则collection属性值只能使用默认键——【argN、collection、list] | 是 |
| item | 自定义的变量名 | 标识当前遍历的元素,通过该属性值能获取每一个元素以及每一个元素的属性 | 否 |
| separator | 自定义的分隔符 | 为遍历的集合或数组的每一项之间添加一个分割符 | 否 |
| open | 自定义字符 | 为循环结束后拼接的语句前面添加一个开始字符 | 否 |
| close | 自定义字符 | 为循环结束后拼接的语句后面添加一个结束字符 | 否 |
| index | 自定义的变量名 | ①如果遍历的是List集合或数组,则该属性就是每一项的索引值;②如果遍历的是Map集合,则该属性就是Map中的键Key | 否 |
🔑使用
- 在SQL语句标签中添加
<foreach>标签,<foreach>标签内添加相关属性 - 使用
#{}或${}获取集合中每一项的值
<foreach collection="ids" item="uId" separator="," open="(" close=")">
#{uId}
</foreach>
🔑测试:查询id为1-4之间的用户信息
-
分析
- 查询不同id的用户信息,可以使用
in ()语句来实现,而()里面的各个id可以封装成一个id集合,然后再SQL语句中遍历出来即可 - dao接口方法中为形参命名,在映射文件取参数时就可以直接通过自定义名来获取
- 因为
()里面的不同参数之间用,隔开,因此在<foreach>遍历时也需要使用separator属性为每一项之间添加分隔符,,不能在循环体中直接写,,因为这样写会使遍历的最后一项后面也有一个,,从而造成SQL语句不合法 - 因为要遍历的集合在
()里面,即<foreach>遍历结束后拼接的内容添加到()里面,有两种实现方式
① 将左括号(写在在<foreach>前面,右括号)写在后面,相当于用()将<foreach>包裹起来
② 使用<foreach>标签中的open和close属性,为循环遍历结束后拼接的内容前面加上开始字符(,后面加上结束字符)(推荐)
- 查询不同id的用户信息,可以使用
-
用户dao接口方法
List<User> getUsersByForeachCondition(@Param("ids") List<Integer> ids); -
用户映射文件
<!-- 根据指定的id集合查询出对应的用户信息 --> <select id="getUsersByForeachCondition" resultType="com.key.mybatis.entity.User"> select * from `user` <where> `user_id` in <foreach collection="ids" item="uId" separator="," open="(" close=")"> #{uId} </foreach> </where> </select> -
测试方法
@Test public void testForeachCondition() { // 获取SqlSession SqlSession sqlSession = MyBatisUtil.getSqlSession(); // 获取mapper UserDao mapper = sqlSession.getMapper(UserDao.class); // 调用dao方法 List<User> users = mapper.getUsersByForeachCondition(Arrays.asList(1, 2, 3, 4)); users.forEach(System.out :: println); // 关闭sqlSession sqlSession.close(); }💡 测试中直接使用工具类的方法创建id集合——
Arrays.asList() -
打印结果

4.2 批量插入
💡 下面只针对MySQL数据库支持的批量插入方式
💬概述:使用<foreach>标签还可以遍历多个对象记录,实现向数据库表中批量插入多条记录
🔑批量插入方式1.0——在插入SQL语句中的values后添加多个(),多个()之间用,分隔开
-
用户dao接口方法
int batchInsertUsersByForeach(@Param("users") List<User> users); -
用户映射文件
<!-- 批量插入多条用户记录1.0 --> <insert id="batchInsertUsersByForeach"> insert into `user`(`user_name`, `password`) values <!-- 使用foreach循环遍历每一条插入数据 --> <foreach collection="users" item="u" separator=","> (#{u.username}, #{u.password}) </foreach> </insert>💡 这里是将
()写在<foreach>标签体(循环体)中,因为要遍历的每一项包含了(),而不是每一项在()中 -
测试方法
@Test public void testBatchInsertByForeach() { // 获取SqlSession SqlSession sqlSession = MyBatisUtil.getSqlSession(); // 获取mapper UserDao mapper = sqlSession.getMapper(UserDao.class); // 创建一个用户集合 List<User> users = new ArrayList<>(); users.add(new User(null, "宋江", "song123")); users.add(new User(null, "武松", "wu123")); users.add(new User(null, "潘金莲", "pan123")); int result = mapper.batchInsertUsersByForeach(users); if (result == 0) { System.out.println("批量插入失败!"); } else { System.out.println("批量插入成功!"); } // 提交事务 sqlSession.commit(); // 关闭 sqlSession.close(); } -
打印结果

🔑批量插入方式2.0——直接执行多次insert语句,每条insert语句之间用;分隔开
-
用户dao接口方法同上
-
用户映射文件
<!-- 批量插入2.0 --> <insert id="batchInsertUsersByForeach"> <!-- 直接使用foreach遍历多次insert语句,每条语句之间用;隔开 --> <foreach collection="users" item="u" separator=";"> insert into `user`(`user_name`, `password`) values(#{u.username}, #{u.password}) </foreach> </insert> -
在jdbc属性文件中添加
allowMultiQueries参数,并设置为trueprop.url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true💡 此操作必不可少,因为参数
allowMultiQueries默认为false,即MySQL默认不支持多条SQL语句通过;分隔开并同时执行 -
测试方法
// 创建一个用户集合 List<User> users = new ArrayList<>(); users.add(new User(null, "吴用", "wu456")); users.add(new User(null, "武大郎", "da123")); users.add(new User(null, "扈三娘", "hu123")); int result = mapper.batchInsertUsersByForeach(users); if (result == 0) { System.out.println("批量插入失败!"); } else { System.out.println("批量插入成功!"); } -
打印结果

五、内置参数
💬概述:MyBatis中不仅可以获取dao接口方法传递过来的参数值,还能使用内置参数来获取值,且在OGNL表达式中可以直接使用内置参数
🔑两个内置参数
-
_parameter
-
概述
① 如果dao接口只传入单个简单类型的形参,则
_parameter就表示这个形参,可以直接根据它来获取对应参数值;② 如果形参中传入多个参数,MyBatis会将dao接口方法中的形参封装成一个Map集合,而内置参数_parameter就表示这个Map集合 -
作用:表示任意传进来的单个参数或参数
Map集合,可以直接获取对应参数值 -
使用:在
<if>标签的text属性中判断传入的形参是否为null,如果不为null才获取对应参数<!-- 直接根据内置参数_parameter判断传入形参是否为null --> <if text="_parameter != null"> where `user_id` = #{userid} </if> -
使用细节
_parameter一般使用在判断条件中(如果<if>标签的text属性里面),即OGNL表达式中,不使用在#{}获取参数- 如果传入单个对象类型的形参,则可以直接使用
_parameter.属性名来获取对象的属性值 - 如果传入多个形参,则可以使用
_parameter.键Key的方式来获取对应参数值,包括默认键——argN和paramN - 如果传入单个普通类型参数,则可以直接使用
_parameter就能获取到参数值,或者使用_parameter.键Key
-
-
_databaseId
-
概述:如果全局配置文件中设置了
<databaseIdProvider>标签,并为各个数据库厂商标识设置了别名,则内置参数_databaseId就表示当前环境下数据库厂商标识的别名 -
作用:可以直接在SQL语句标签体中获取当前环境的数据库厂商标识,并可以根据不同环境下的数据库厂商设置不同的SQL语句
-
使用:在
<if>标签的text属性中判断当前环境的数据库厂商,然后使用对应的SQL语句<!-- 根据数据库厂商标识的别名来选择查询数据库表 --> <if test="_databaseId == 'mysql'"> <!-- mysql下查询user表 --> select * from `user` </if> <if test="_databaseId == 'oracle'"> <!-- oracle下查询employeeb --> select * from `employee` </if>
-
六、bind标签
💬概述:<bind>也是SQL语句标签的子标签,bind是绑定的意思,顾名思义就是用来绑定数据或值
🔑作用:使用<bind>标签,可以为自定义的值绑定一个变量名,根据变量名就能获取到对应的值
🔑<bind>标签的两个属性
| 属性名 | 属性值 | 解释 |
|---|---|---|
| name | 自定义的变量名 | 为自定义的新参数绑定一个变量名,SQL语句中通过#{Key}获取参数值时,就可以直接将该变量名作为键Key来获取新的参数值 |
| value | 自定义的新参数 | 在value属性中可以使用OGNL表达式来自定义新的参数,比如可以直接根据键Key获取传进来的形参对应的参数值,然后将参数值修改成新的参数 |
🔑使用:根据姓名模糊查询用户信息,模糊查询时直接传入关键字,不传入通配符(%或_),在映射文件中再为传入的关键字添加上通配符,形成一个新参数,然后使用<bind>为该新参数绑定一个变量名,SQL语句中根据该变量名来获取对应参数值
-
dao接口方法
List<User> listUsersByBind(String nameKey); -
映射文件
<!-- 根据姓名关键字模糊查询 --> <select id="listUsersByBind" resultType="com.key.mybatis.entity.User"> <!-- 使用bind标签绑定新的参数 - name="newName":为自定义的新参数绑定一个变量名 - value="...":自定义新的参数,也是使用OGNL表达式 --> <bind name="newName" value="'%' + nameKey + '%'"/> select * from `user` where `user_name` like #{newName}; </select> -
测试方法
@Test public void testBind() { // 获取SqlSession SqlSession sqlSession = MyBatisUtil.getSqlSession(); // 获取mapper UserDao mapper = sqlSession.getMapper(UserDao.class); List<User> users = mapper.listUsersByBind("周"); users.forEach(System.out :: println); // 关闭sqlSession sqlSession.close(); }
七、sql标签 & include标签
🔑sql标签
- 概述:
<sql>标签是与其他SQL语句标签同级的标签,在<sql>标签中也能书写SQL语句 - 作用:抽取可重用的SQL语句,一般用于抽取插入语句、更新语句时的数据库表的列名
- 使用细节:
<sql>标签中也可以使用动态SQL语句中各种条件标签,如<if>、<where>等 - 属性——id:唯一标识,根据sql-id可以引用其抽取的SQL语句
🔑include标签
-
概述:
<include>标签是SQL语句标签的子标签,与<sql>标签是合作伙伴 -
作用:引用
<sql>中抽取的可重用SQL语句 -
作用位置:穿插在SQL语句中,取代被抽取的部分SQL语句
-
使用细节:在
<include>标签中还可以通过<property>子标签自定义属性,<sql>标签中就可以使用${}获取对应属性💡
<sql>标签中获取<include>定义的属性时,只能使用${},不能使用#{} -
属性——refid:对应
<sql>标签中的唯一标识sql-id,根据该id标识了对应<sql>标签后,<include>所在的位置就会被<sql>中抽取的SQL语句所代替,最终拼接成完整的SQL语句
🔑sql标签和include标签结合使用
-
使用1.0——使用
<sql>抽取插入语句中的各个数据库表列名,然后在SQL语句标签中使用<include>引用对应SQL<!-- 使用sql标签和include标签 --> <insert id="insertUserBySqlAndInclude"> insert into `user` ( <!-- include标签直接写在SQL语句中,取代抽取的SQL --> <include refid="insertColumn"/> ) values(#{userid}, #{username}, #{password}) </insert> <!-- 抽取可重用SQL语句 --> <sql id="insertColumn"> `user_name`, `password` </sql> -
使用2.0——在
<include>中为密码字段’password’再自定义一个名称,然后在<sql>中使用自定义名来获取对应字段名<!-- 使用sql标签和include标签 --> <insert id="insertUserBySqlAndInclude"> insert into `user` ( <include refid="insertColumn"> <!-- 自定义属性 --> <property name="pwd" value="password"/> </include> ) values(#{userid}, #{username}, #{password}) </insert> <!-- 抽取可重用SQL语句 --> <sql id="insertColumn"> <!-- 使用${}获取include设置的属性值 --> `user_name`, ${pwd} </sql>



















