MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
动态SQL元素和JSTL或基于类似XML的文本处理器相似。在MyBatis之前的版本中,有很多元素需要花时间了解。MyBatis 3大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于OGNL的表达式来淘汰其它大部分元素。
if元素
使用test属性来判断,如果结果true,把这部分内容拼接sql中,如果结果false,去除这个部分内容。
<select id="selectBySex" parameterType="map" resultType="user">
select * from user where 1=1
<if test="sex != null and sex != ''">
and sex = #{sex}
</if>
</select>
测试代码:
@Test
public void test09() {
SqlSession sqlSession = SqlSessionFactoryUtils.openSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
Map map = new HashMap();
map.put("sex",1);
List<User> users = userDao.selectBySex(map);
System.out.println(users);
sqlSession.commit();
sqlSession.close();
}
choose、when、otherwise元素
相当于java中的switch、case、default。
<select id="selectUserListByWhen" resultType="user" parameterType="user">
SELECT * FROM user WHERE 1=1
<choose>
<when test="username !=null and username!=''">
AND username like '%${username}%'
</when>
<when test="sex !=null and sex!=''">
AND sex = #{sex}
</when>
<otherwise>
AND age = #{age}
</otherwise>
</choose>
</select>
测试代码:
@Test
public void test10() {
SqlSession sqlSession = SqlSessionFactoryUtils.openSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
User user = new User();
user.setSex("1");
List<User> users = userDao.selectUserListByWhen(user);
System.out.println(users);
sqlSession.commit();
sqlSession.close();
}
以上例子中:
<1> 当sex和username 都不为null的时候, 那么选择二选一(前者优先),
<2> 如果都为null, 那么就选择 otherwise中的,
<3> 如果sex和username 只有一个不为null, 那么就选择不为null的那个。
注:无论是if和 when中的判断,如果需要写and,则必须小写。
where、set元素
在前面if和choose元素中,where后面跟有1=1,如果没有1=1这个条件的话,就可能会产生错误:
select * from user where and sex = #{sex}
当然我们可以改成:
<select id="selectBySex" parameterType="map" resultType="user">
select * from user where
<if test="sex != null and sex != ''">
and sex = #{sex}
</if>
</select>
但是若if中test为false时,就变成了:
select * from user where
这个时候,我们可以使用where元素:
<select id="selectBySex" parameterType="map" resultType="user">
select * from user
<where>
<if test="sex != null and sex != ''">
and sex = #{sex}
</if>
</where>
</select>
一般在修改某条记录的时候,我们希望只修改有值传入的字段:
<update id="updateUserById" parameterType="user">
update user set
<if test="username != null and username !=’’"> username = #{username}, </if>
<if test="sex != null and sex !=’’"> sex = #{sex}, </if>
<if test="password != null and password !=’’"> password = #{password} </if>
<where>
<if test="id != null"> id = #{id}</if>
</where>
</update>
测试代码:
@Test
public void test11() {
SqlSession sqlSession = SqlSessionFactoryUtils.openSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
User user = new User();
user.setId(1);
user.setSex("1");
user.setUsername("小明");
int num = userDao.updateUserById(user);
System.out.println(num);
sqlSession.commit();
sqlSession.close();
}
运行时,发现报错了。。。原来最后执行的SQL语句:where前面多了一个逗号。
update user set username = '小明', sex = '1', where id = 1
添加元素:
<update id="updateUserById" parameterType="user">
update user
<set>
<if test="username != null and username !=’’"> username = #{username}, </if>
<if test="sex != null and sex !=’’"> sex = #{sex}, </if>
<if test="password != null and password !=’’"> password = #{password} </if>
</set>
<where>
<if test="id != null"> id = #{id}</if>
</where>
</update>
update语句,set语句中存在不合适的逗号,会自动删除。
foreach元素
在MySQL中可以使用in来查询多条符合要求的记录,比如:
select * from user where id in (1,2,3)
如果将1,2,3封装在集合或者数组中,可以使用进行遍历并查询,如下:
<select id="selectUserListInId" resultType="user">
SELECT * FROM user WHERE id IN
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
测试代码:
@Test
public void test12() {
SqlSession sqlSession = SqlSessionFactoryUtils.openSqlSession();
UserDao userDao = sqlSession.getMapper(UserDao.class);
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
List<User> users = userDao.selectUserListInId(list);
System.out.println(users);
sqlSession.commit();
sqlSession.close();
}
属性介绍(这里只考虑 List和数组):
collection :传的参数 只有list、array两值,不能写错
item :每次遍历的值赋值给变量item
open :表示该语句以什么开始
close :表示该语句以什么结束
separator :表示该语句以什么隔开
index :元素的序号