MyBatis使用大全(4)------动态SQL使用
来源:互联网 发布:武汉软件公司 知乎 编辑:程序博客网 时间:2024/05/18 00:26
MyBatis 的强大特性之一便是它的动态 SQL。
如果你用jdbc等等每次拼接sql都需要特别注意空格,未列的逗号。
但是,利用MyBatis动态SQL对于这些问题会有一些改善,用起来会
相对省心。通常使用动态 SQL 不可能是独立的一部分,
MyBatis当然使用一种强大的动态 SQ 语言来改进这种情形,
这种语言可以被用在任意的 SQL 映射语句中。
动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。
在 MyBatis 之前的版本中,有很多的元素需要来了解。
MyBatis 3 大大提升了它们,现在用不到原先一半的元素就可以。
MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。
常用元素如下:
--if
--choose (when, otherwise)
--trim (where, set)
--foreach
接下来对这些元素进行讨论:
(1) if的使用
动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分。比如:
Java代码查询方法封装参数map:
- Map<String,Object> parMap = new HashMap<String, Object>();
- parMap.put("id", 1);
- UserMainMapper userMainMapper = session.getMapper(UserMainMapper.class);
- User user = userMainMapper.queryUserMainById(parMap);
- System.out.println(user.getUsername());
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <!--
- 为这个mapper指定一个唯一的namespace,namespace的值习惯上设置成包名+去掉sql映射文件后缀的文件名,
- 这样就能够保证namespace的值是唯一的,例如namespace="com.lanhuigu.mybatis.map.UserMainMapper"
- 就是com.lanhuigu.mybatis.map(包名)+UserMainMapper(UserMainMapper.xml文件去除后缀)
- -->
- <mapper namespace="com.lanhuigu.mybatis.map.UserMainMapper">
- <!--
- 在select标签中编写查询的SQL语句, 设置select标签的id属性为queryUserMainById,id属性值必须是唯一的,
- 不能够重复使用parameterType属性指明查询时使用的参数类型,resultType属性指明查询返回的结果集类型
- resultType="com.lanhuigu.mybatis.entity.User"就表示将查询结果封装成一个User类的对象返回
- User类就是users表所对应的实体类
- -->
- <select id="queryUserMainById" parameterType="java.util.Map"
- resultType="com.lanhuigu.mybatis.entity.User">
- select
- f_id id,
- f_username username,
- f_age age
- from t_user_main
- where 1=1
- <if test="id != null">
- and f_id = #{id}
- </if>
- </select>
- </mapper>
在where条件后,我们加了一个对id是否为空的判断,如果不为空,则作为查询条件之一,
否则,不做为查询条件。
当然了,我们能判断一个条件,我们也能判断多个条件,比如map多封装几个有用的参数,
查询条件同样可以进行拆分或组合判断。
比如map封装:
- Map<String,Object> parMap = new HashMap<String, Object>();
- parMap.put("id", 1);
- parMap.put("username", "testMyBatis");
- <select id="queryUserMainById" parameterType="java.util.Map"
- resultType="com.lanhuigu.mybatis.entity.User">
- select
- f_id id,
- f_username username,
- f_age age
- from t_user_main
- where 1=1
- <if test="id != null and username!=null">
- and f_id = #{id}
- and f_username = #{username}
- </if>
- </select>
注意:对于if的应用我们可以根据实际情况判断,可以单个判断,可以多个条件判断。
2.choose, when, otherwise的使用
有些时候,我们不想用到所有的条件语句,而只想从中择其一二。
针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
这种处理方式在Oracle,MySQL数据库中条件判断逻辑一样。咱们讲上面例子改改,例如:
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <!--
- 为这个mapper指定一个唯一的namespace,namespace的值习惯上设置成包名+去掉sql映射文件后缀的文件名,
- 这样就能够保证namespace的值是唯一的,例如namespace="com.lanhuigu.mybatis.map.UserMainMapper"
- 就是com.lanhuigu.mybatis.map(包名)+UserMainMapper(UserMainMapper.xml文件去除后缀)
- -->
- <mapper namespace="com.lanhuigu.mybatis.map.UserMainMapper">
- <!--
- 在select标签中编写查询的SQL语句, 设置select标签的id属性为queryUserMainById,id属性值必须是唯一的,
- 不能够重复使用parameterType属性指明查询时使用的参数类型,resultType属性指明查询返回的结果集类型
- resultType="com.lanhuigu.mybatis.entity.User"就表示将查询结果封装成一个User类的对象返回
- User类就是users表所对应的实体类
- -->
- <select id="queryUserMainById" parameterType="java.util.Map"
- resultType="com.lanhuigu.mybatis.entity.User">
- select
- f_id id,
- f_username username,
- f_age age
- from t_user_main
- where 1=1
- <choose>
- <when test="id != null">
- and f_id = #{id}
- </when>
- <when test="username != null">
- and f_username = #{username}
- </when>
- <otherwise>
- and f_id = 10
- </otherwise>
- </choose>
- </select>
- </mapper>
但是如果都为空,强制查询f_id=10的数据。
3.trim, where, set的使用
我在上面的例子中where后面都加1=1,加这个的原因主要是防止生成的sql是这样的,
select
f_id id,
f_username username,
f_age age
from t_user_main
where and f_id = #{id}
这条sql执行的时候必然报错,我在前面加个1=1就可以轻松避免。让sql避免异常:
select
f_id id,
f_username username,
f_age age
from t_user_main
where 1=1 and f_id = #{id}
处理这样的问题还有另外一个方法,使用where元素:
- <select id="queryUserMainById" parameterType="java.util.Map"
- resultType="com.lanhuigu.mybatis.entity.User">
- select
- f_id id,
- f_username username,
- f_age age
- from t_user_main
- <where>
- <choose>
- <when test="id != null">
- f_id = #{id}
- </when>
- <when test="username != null">
- and f_username = #{username}
- </when>
- <otherwise>
- and f_id = 10
- </otherwise>
- </choose>
- </where>
- </select>
select
f_id id,
f_username username,
f_age age
from t_user_main where and f_username = #{username}
这个sql的where后直接跟了个and执行的时候为什么不报错,这都是where元素的功劳。
where知道,有大于等于1个条件时,才会去注入"where"字句,若最后的内容是“AND”或“OR”开头的,
where 元素也知道如何将他们去除。这就是我们为什么肉眼看上去and....,这个语句却能执行的原因。
如果 where 元素没有按正常套路出牌,我们还是可以通过自定义 trim 元素来定制我们想要的功能。
比如,和 where 元素等价的自定义 trim 元素为:
<trim prefix="WHERE"prefixOverrides="AND |OR "> ...</trim>
prefixOverrides 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。
它带来的结果就是所有在 prefixOverrides 属性中指定的内容将被移除,并且插入 prefix 属性中指定的内容。
类似的用于动态更新语句的解决方案叫做 set。set 元素可以被用于动态包含需要更新的列,而舍去其他的。比如:
- <update id="updateUserMain" parameterType="java.util.Map">
- update t_user_main
- <set>
- <if test="username != null">f_username = #{username}</if>
- <if test="age != null">f_age = #{age}</if>
- </set>
- where f_id = #{id}
- bsp;</update>
因为用了条件语句之后很可能就会在生成的赋值语句的后面留下这些逗号。
4.foreach的使用
- <select id="queryUserMainById" resultType="com.lanhuigu.mybatis.entity.User">
- select
- f_id id,
- f_username username,
- f_age age
- from t_user_main
- where f_id in
- <foreach collection="item="item" index="index" collection="list" open="(" separator="," close=")">
- #{item}
- </foreach>
- </select>
它也允许你指定开闭匹配的字符串以及在迭代中间放置分隔符。
这个元素是很智能的,因此它不会偶然地附加多余的分隔符。
可以将任何可迭代对象(如列表、集合等)和任何的字典或者数组对象传递给foreach作为集合参数。
当使用可迭代对象或者数组时,index是当前迭代的次数,item的值是本次迭代获取的元素。
当使用字典(或者Map.Entry对象的集合)时,index是键,item是值。
5.bind的使用
bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:
- <select id="queryUserMainById" resultType="com.lanhuigu.mybatis.entity.User">
- <bind name="pattern" value="'%' + _parameter.getUsername() + '%'" />
- select
- f_id id,
- f_username username,
- f_age age
- from t_user_main
- where f_username like #{pattern}
- </select>
- MyBatis使用大全(4)------动态SQL使用
- MyBatis使用大全(5)------动态SQL使用
- mybatis动态sql使用
- 使用MyBatis(11)动态SQL
- MyBatis使用动态SQL语句
- mybatis使用及动态sql
- Mybatis使用之动态SQL语句
- MyBatis使用动态SQL批量插入数据
- 使用Mybatis动态sql简化开发
- (3).Mybatis动态sql的使用
- 09.Mybatis初级使用-动态sql
- Mybatis 完成CRUD和动态sql使用
- mybatis 动态sql and的使用
- MyBatis动态SQL<choose>标签的使用
- MyBatis动态SQL set标签的使用
- mybatis入门使用6:动态SQL
- mybatis中动态sql的使用
- MyBatis动态SQL中trim的使用
- maven命令
- android 任务栏Translucent System Bar 设置
- Java如何动态生成BasicDataSource数据源
- 超级灵活的 Java JSON 库
- C++之STL和Boost
- MyBatis使用大全(4)------动态SQL使用
- Jmeter之五:监听器(二)
- 调试EXC_BAD_ACCESS 对象释放
- docker 使用centos 镜像 运行 javaweb ,并重新生成镜像
- android共享元素
- C++ 静态编译
- Shell运算符:Shell算数运算符、关系运算符、布尔运算符、字符串运算符等
- MyBatis使用大全(5)------映射器类
- hibernate注解(一)