8.动态sql
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
8.1 If
使用if根据条件动态拼接sql,常用语where条件
xml
<select id="selectListofEntity" resultMap="resultMap" parameterType="com.neuedu.entity.UploadFile">
select * from upload_files
where 1=1
<if test="originName!=null and originName != ''">
and origin_name = #{originName}
</if>
</select>
8.2 where
where
元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where
元素也会将它们去除。
xml
<select id="selectListofEntity" resultMap="resultMap" parameterType="com.neuedu.entity.UploadFile">
select * from upload_files
<where >
<if test="originName!=null and originName != ''">
and origin_name = #{originName}
</if>
<if test="size!=null">
and size > #{size}
</if>
</where>
</select>
8.2.1 单元测试的情况
java
@Test
public void selectListofEntity() {
SqlSession session = sqlSessionFactory.openSession();
UploadFilesMapper uploadFilesMapper = session.getMapper(UploadFilesMapper.class); //通过mybatis产生一个 代理对象
UploadFile param = new UploadFile();
//通过控制参数达到动态拼接sql的目的
param.setOriginName("314.png");
param.setSize(500L);
List<UploadFile> list = uploadFilesMapper.selectListofEntity(param);
for (UploadFile o : list) {
System.out.println(o);
}
session.close();
}
8.2.2 等价的trim标签
xml
<select id="selectListofEntity" resultMap="resultMap" parameterType="com.neuedu.entity.UploadFile">
select * from upload_files
<trim prefix="where" prefixOverrides="and|or">
<if test="originName!=null and originName != ''">
or origin_name = #{originName}
</if>
<if test="size!=null">
or size > #{size}
</if>
</trim>
</select>
8.3 set标签
set
元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。
xml
<update id="update" parameterType="com.neuedu.entity.UploadFile">
UPDATE
upload_files
<set>
<if test="originName!=null and originName!='' ">
origin_name= #{originName},
</if>
<if test="path!=null and path!='' ">
path= #{path},
</if>
<if test="uploadTime!=null ">
upload_time= #{uploadTime},
</if>
<if test="size!=null ">
size= #{size},
</if>
<if test="ip!=null and ip != ''">
ip= #{ip},
</if>
</set>
WHERE id= #{id}
</update>
8.3.1单元测试
java
@Test
public void update() {
SqlSession session = sqlSessionFactory.openSession();
UploadFilesMapper UploadFilesMapper = session.getMapper(UploadFilesMapper.class); //通过mybatis产生一个 代理对象
Integer id = 24;
UploadFile uploadFile = UploadFilesMapper.selectById(id);
System.out.println("update before : "+uploadFile);
uploadFile.setOriginName(uploadFile.getOriginName()+"-2021年3月22日16:19:14");
int count = UploadFilesMapper.update(uploadFile);
session.commit();
uploadFile = UploadFilesMapper.selectById(id);
System.out.println("count = " + count);
System.out.println("update after : "+uploadFile);
}
8.3.2 等价的trim标签
xml
<update id="update" parameterType="com.neuedu.entity.UploadFile">
UPDATE
upload_files
<trim prefix="set" suffixOverrides=",">
<if test="originName!=null and originName!='' ">
origin_name= #{originName},
</if>
<if test="path!=null and path!='' ">
path= #{path},
</if>
<if test="uploadTime!=null ">
upload_time= #{uploadTime},
</if>
<if test="size!=null ">
size= #{size},
</if>
<if test="ip!=null and ip != ''">
ip= #{ip},
</if>
</trim>
WHERE id= #{id}
</update>
8.4 choose (when ,otherwise)
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
当第一个when条件成立则第一个条件作为sql的一部分,否则继续后面 when 判断,所有的when 都不满,则拼接otherwise的条件
xml
<select id="selectCount" resultType="int">
select count(1) from upload_files
where 1=1
<choose>
<when test="originName!=null and originName != ''">
and origin_name = #{originName}
</when>
<otherwise>
and size > #{size}
</otherwise>
</choose>
</select>
8.5 trim
属性名 | 属性解释 |
---|---|
prefix | 要添加的前缀。比如这里因为没有使用WHERE,按照语法格式条件必须要有WHERE。此时就可以使用prefix属性给整个条件语句块前面添加一个WHERE 关键字。 |
prefixOverrides | 要删除的前缀。如果多出来指定的前缀,则将这些多出来的前缀修剪去除。比如:如果在整个语句中需要修剪去AND |
suffix | 要添加的后缀。使用方式与prefix类似,只是prefix是增加前缀,而suffix是添加一个后缀在被包裹的语句块中。 |
suffixOverrides | 要删除的后缀。使用方式与prefixOverrides类似,只是一个是去除前面多余的关键字,suffixOverrides是删除多余后面的。 |
8.6 foreach
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)
8.6.1 Statement写法
xml
<delete id="deleteBatch">
DELETE FROM upload_files WHERE id IN
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</delete>
<delete id="deleteBatch2">
DELETE FROM upload_files WHERE id IN
<foreach item="item" index="index" collection="array" open="(" separator="," close=")">
#{item}
</foreach>
</delete>
8.6.12 Mapper接口
java
public int deleteBatch( List list);
public int deleteBatch2(Integer[] ids);
8.7 bind
用于在ongl上下文中定义变量
8.7.1 Statement语句
xml
<select id="selectListofEntityWithBind" resultMap="resultMap" parameterType="com.neuedu.entity.UploadFile">
select * from upload_files
<where >
<if test="originName!=null and originName != ''">
<bind name="originNameAlias" value=" '%'+originName+'%' "/>
and origin_name like '${originNameAlias}'
</if>
</where>
</select>
8.7.2 Mapper声明
java
public List<UploadFile> selectListofEntityWithBind(UploadFile uploadFile)
8.7.3 单元测试
java
@Test
public void selectListofEntityWithBind() {
SqlSession session = sqlSessionFactory.openSession();
UploadFilesMapper uploadFilesMapper = session.getMapper(UploadFilesMapper.class); //通过mybatis产生一个 代理对象
UploadFile param = new UploadFile();
param.setOriginName("314");
List<UploadFile> list = uploadFilesMapper.selectListofEntityWithBind(param);
for (UploadFile o : list) {
System.out.println(o);
}
session.close();
}
