动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
<select id="queryBlogsIF" parameterType="map" resultType="blog">
select * from blog
<where>
<if test="title !=null">
and title=#{title}
if>
<if test="author != null">
and author=#{author}
if>
where>
select>
//接口,用于动态更新字段信息
int updateBlog(Blog blog);
//mapper.xml
<update id="updateBlog" parameterType="blog">
update blog
<set>
<if test="title != null">
title=#{title},
</if>
<if test="author != null">
author=#{author},
</if>
<if test="createTime != null">
create_time=#{createTime},
</if>
<if test="views != null">
views=#{views},
</if>
</set>
where id=#{id}
</update>
//测试
@Test
public void updataBlog(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
mapper.updateBlog(new Blog("1","helloMybatis","德抑窒",new Date(),10000));
}
判断语句,这里举例需求是先根据博客title查询,如果title为空,则根据author查询;相反根据title查询。
public List<Blog> queryBlogsIF(Map map);
<select id="queryBlogsIF" parameterType="map" resultType="blog">
select * from blog where 1=1
<if test="title !=null">
and title=#{title}
if>
<if test="author != null">
and author=#{author}
if>
select>
where标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。
/*注意,其中的1=1用来保证sql语句的正确性,防止and的多余,可以用<where>where>来代替*/
<select id="queryBlogsIF" parameterType="map" resultType="blog">
select * from blog
<where>
<if test="title !=null">
and title=#{title}
if>
<if test="author != null">
and author=#{author}
if>
where>
select>
@Test
public void queryBlogsIF(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap ();
map.put("title","mybatis");
//map.put("author","德抑窒");
List<Blog> blogs = mapper.queryBlogsIF(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
}
//chooose查询
public List<Blog> queryBlogChoose(Map map);
有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句。
<select id="queryBlogChoose" parameterType="map" resultType="blog">
select * from blog
<choose>
<when test="title != null">
title =#{title}
when>
<when test="author != null">
author=#{author}
when>
<otherwise>
views =#{views}
otherwise>
choose>
select>
@Test
public void queryBlogsChoose(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap ();
map.put("title","mybatis");
map.put("author","德抑窒");
//map.put("views",100);
List<Blog> blogs = mapper.queryBlogChoose(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
}
为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。
<sql id="if-title-author">
<if test="title != null">
title = #{title}
if>
<if test="author != null">
and author = #{author}
if>
sql>
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog
<where>
<!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
<include refid="if-title-author"></include>
<!-- 在这里还可以引用其他的 sql 片段 -->
</where>
</select>
foreach通过collection属性获取一个列表,可从而实现遍历。
想要遍历数据库前5个人的信息
//foreach查询
public List<Blog> queryBlogForeach(Map map);
collection:指定输入对象中的集合属性
item:每次遍历生成的对象
open:开始遍历时的拼接字符串
close:结束时拼接的字符串
separator:遍历对象之间需要拼接的字符串
sql实现:
select * from blog where 1=1 and (id=1 or id=2 or id=3)
<select id="queryBlogForeach" resultType="blog" parameterType="map">
select * from blog
<where>
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
id=#{id}
foreach>
where>
select>
@Test
public void queryBlogForeach(){
SqlSession sqlSession = MyBatisUtil.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
List<String> ids = new ArrayList<>();
ids.add("1");
ids.add("2");
ids.add("3");
ids.add("4");
ids.add("5");
Map map = new HashMap ();
map.put("ids",ids);
//map.put("views",100);
List<Blog> blogs = mapper.queryBlogForeach(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
}