6、MyBatis的动态SQL
来源:互联网 发布:手机成绩统计软件 编辑:程序博客网 时间:2024/06/10 14:44
MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦。拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中。
动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多的元素需要来了解。MyBatis 3 大大提升了它们,现在用不到原先一半的元素就可以了。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。
mybatis 的动态sql语句是基于OGNL表达式的。可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类:
- if 语句 (简单的条件判断)
- where (主要是用来简化sql语句中where条件判断的,能智能的处理 and or ,不必担心多余导致语法错误)
- set (主要用于更新时)
- trim (对包含的内容加上 prefix,或者 suffix 等,前缀,后缀)
- choose (when,otherwize) ,相当于java 语言中的 switch ,与 jstl 中的choose 很类似.
- foreach (在实现 mybatis in 语句查询时特别有用)
if标签
目标:通过传入User对象查询符合条件的user
<select id="queryByUser" parameterType="cn.xpu.hcp.bean.User" resultType="cn.xpu.hcp.bean.User"> select * from user where id=#{id} and username like "%"#{username}"%" and sex=#{sex} and address=#{address}</select>
这是未使用if标签前。设想一下,如果传入的User对象并没有对应的值,那么这条SQL语句就什么也查不出。
这时就需要用if标签对各个属性值进行判断。
<select id="queryByUser" parameterType="cn.xpu.hcp.bean.User" resultType="cn.xpu.hcp.bean.User"> select * from user where 1=1 <if test="id>=1"> id=#{id} </if> <if test="username!=null and username!=''"> and username like "%"#{username}"%" </if> <if test="sex!=null and sex!=''"> and sex=#{sex} </if> <if test="address!=null and address!=''"> and address=#{address} </if></select>
where后面的1=1一定不能丢失。
这是为了防止两种SQL语句:
①:select * from user where②:select * from user where and username like '张'
一个是where后无条件,一个是紧跟一个and。
测试:
public void MapperTest(){ SqlSession session = sqlSessionFactory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); User user = new User(); user.setSex("m"); user.setUsername("张"); List<User> list = mapper.queryByUser(user); for (User u : list) { System.out.println(u); } session.commit(); session.close();}
where标签
在上述if标签使用后有不满意的地方,即where后一定要有一个条件(譬如:1=1)。不让会产生SQL语句的错误。
这时可以使用 where 动态语句来解决。“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以 AND 或OR 开头的,则它会剔除掉。
使用where标签:
<select id="queryByUser" parameterType="cn.xpu.hcp.bean.User" resultType="cn.xpu.hcp.bean.User"> select * from user <where> <if test="id>=1"> id=#{id} </if> <if test="username!=null and username!=''"> and username like "%"#{username}"%" </if> <if test="sex!=null and sex!=''"> and sex=#{sex} </if> <if test="address!=null and address!=''"> and address=#{address} </if> </where></select>
使用了where标签后在SQL语句中不需要写where了,会自动生成。
我们也不需要担心出现类似select * from user where and username like ‘张’ 这样的SQL语句了,MyBatis会自动将第一个and(或or)剔除。自动变为:select * from user where username like ‘张’
set标签
未使用set标签前:
<update id="updateByUser" parameterType="cn.xpu.hcp.bean.User"> update user set <if test="birthday!=null"> birthday = #{birthday}, </if> <if test="username!=null and username!=''"> username = #{username}, </if> <if test="sex!=null and sex!=''"> sex=#{sex}, </if> <if test="address!=null and address!=''"> address=#{address}, </if> where id=#{id}</update>
一大问题,“,”的取舍问题,最后一个的“,”怎么办?
这也是使用set标签的好处了,set标签可以帮我们处理最后一个逗号:
<update id="updateByUser" parameterType="cn.xpu.hcp.bean.User"> update user <set> <if test="birthday!=null"> birthday = #{birthday}, </if> <if test="username!=null and username!=''"> username = #{username}, </if> <if test="sex!=null and sex!=''"> sex=#{sex}, </if> <if test="address!=null and address!=''"> address=#{address}, </if> </set> where id=#{id}</update>
同样,使用set标签后sql语句中不要写set了。
测试:
public void MapperTest(){ SqlSession session = sqlSessionFactory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); User user = new User(); user.setId(2); user.setSex("f"); user.setUsername("孙尚香"); mapper.updateByUser(user); session.commit(); session.close();}
trim标签
trim 标签的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是 prefix 和 suffix;可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是 prefixOverrides 和 suffixOverrides;正因为 trim 有这样的功能,所以我们也可以非常简单的利用 trim 来代替 where /set标签的功能。
代替where标签:
select * from user <trim prefix="where" suffixOverrides="and"><!--如果是要去除or就写or--> <if test="id>=1"> id=#{id} </if> <if test="username!=null and username!=''"> and username LIKE "%"#{username}"%" </if> <if test="sex!=null and sex!=''"> and sex=#{sex} </if> <if test="address!=null and address!=''"> and address=#{address} </if></trim>
代替set标签:
update user<trim prefix="set" suffixOverrides=","> <if test="birthday!=null"> birthday = #{birthday}, </if> <if test="username!=null and username!=''"> username = #{username}, </if> <if test="sex!=null and sex!=''"> sex=#{sex}, </if> <if test="address!=null and address!=''"> address=#{address}, </if> where id=#{id}</trim>
choose标签
choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。类似于Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。
<select id="testChoose" parameterType="cn.xpu.hcp.bean.User" resultType="cn.xpu.hcp.bean.User"> select * from user <where> <choose> <when test="id>=1"> id=#{id} </when> <when test="username!=null and username!=''"> and username LIKE "%"#{username}"%" </when> <when test="sex!=null and sex!=''"> and sex=#{sex} </when> <when test="address!=null and address!=''"> and address=#{address} </when> <otherwise> </otherwise> </choose> </where></select>
测试:
public void MapperTest(){ SqlSession session = sqlSessionFactory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); User user = new User(); user.setSex("f"); user.setUsername("张"); List<User> list = mapper.testChoose(user); for (User u : list) { System.out.println(u); } session.commit(); session.close(); }
如果使用if标签则会查出有”张”字并且性别为“f”的人,使用了choose标签后,由于已经满足了有“张”字这一条件,就不会进行下面的性别判断了。
foreach标签
向SQL语句传递数组或集合,MyBatis使用foreach进行解析。
比如:
select * from user where id in (1,5,6)
解析包装类中的集合/数组
在包装类中声明集合ids,并且添加getter/setter方法:
public class UserWrapper { private List<Integer> ids; public List<Integer> getIds() { return ids; } public void setIds(List<Integer> ids) { this.ids = ids; }}
在UserMapper.xml中:
<select id="testForeach" parameterType="cn.xpu.hcp.bean.UserWrapper" resultType="cn.xpu.hcp.bean.User"> select * from user <!-- collection:遍历的集合 item:遍历的项目,名字任意,只需要与下面#{}中的相同即可 open:在前面添加的sql片段 close:在结尾添加的sql片段 separator:以什么为分割符,这里选择"," 如此组成sql语句:select * from user where id in (#{item},...) --> <where> <foreach collection="ids" item="item" open="id in(" close=")" separator=","> #{item} </foreach> </where></select>
测试:
public void MapperTest(){ SqlSession session = sqlSessionFactory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); UserWrapper wrapper = new UserWrapper(); List<Integer> ids = new ArrayList<>(); ids.add(2); ids.add(3); ids.add(10); ids.add(13); wrapper.setIds(ids); List<User> list = mapper.testForeach(wrapper); for (User u : list) { System.out.println(u); } session.commit(); session.close();}
解析直接传递的数组/集合
测试类:
public void MapperTest(){ SqlSession session = sqlSessionFactory.openSession(); UserMapper mapper = session.getMapper(UserMapper.class); Integer[] ids = {1,3,10,15}; List<User> list = mapper.testForeach(ids);//直接传递数组 for (User u : list) { System.out.println(u); } session.commit(); session.close();}
此时的foreach中:
<foreach collection="array" item="item" open="id in(" close=")" separator=","> ......</foreach>
注意collection的变化,此时的值不应该为ids,而是array,所以如果传递集合就为list。
- 6、MyBatis的动态SQL
- MyBatis的动态SQL
- MyBatis的动态SQL
- MyBatis的动态SQL
- Mybatis的动态Sql
- MyBatis的动态SQL
- Mybatis的动态SQL
- MyBatis的动态SQL
- mybatis的动态sql
- MyBatis的动态SQL
- Mybatis 的 动态sql
- mybatis的动态sql
- mybatis的动态SQL
- MyBatis的动态SQL
- myBatis的动态SQL
- Mybatis的动态sql
- mybatis的动态SQL
- mybatis的动态sql
- Servlet3.0的注解支持
- 数据结构之堆排序(java)
- bpython:界面丰富的Python解析器
- 文件映射实现对文件信息的增删改查
- IE/FIREFOX/CHROME等浏览器保存COOKIE的位置
- 6、MyBatis的动态SQL
- SSL_2289 庆功会
- VMware 开机黑屏
- 微信小程序—contact-button(客服)
- 详解LinkedList实现类
- MySQL排序内部原理探秘
- 最常用的排序:快速排序算法
- solr与中文分词器的安装配置
- 6-2 多态性与虚函数