动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
CREATE TABLE `blog` (
`id` varchar(50) NOT NULL COMMENT '博客id',
`title` varchar(100) NOT NULL COMMENT '博客标题',
`author` varchar(30) NOT NULL COMMENT '博客作者',
`create_time` date NOT NULL COMMENT '创建时间',
`views` int(30) NOT NULL COMMENT '浏览量'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Blog {
private int id;
private String title;
private String author;
private Date createTime;
private int views;
}
public interface BlogMapper {
// 插入数据
int addBlog(Blog blog);
}
insert into blog(id,title,author,create_time,views)
values (#{id},#{title},#{author},#{createTime},#{views})
@Test
public void addBlog(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
Blog blog = new Blog();
blog.setId(IDutils.getId());
blog.setTitle("鲁班学java");
blog.setAuthor("小鲁班");
blog.setCreateTime(new Date());
blogMapper.addBlog(blog);
blog.setId(IDutils.getId());
blog.setTitle("妲己学java");
blog.setAuthor("妲己");
blog.setCreateTime(new Date());
blogMapper.addBlog(blog);
blog.setId(IDutils.getId());
blog.setTitle("李白学java");
blog.setAuthor("李白");
blog.setCreateTime(new Date());
blogMapper.addBlog(blog);
blog.setId(IDutils.getId());
blog.setTitle("孙尚香学java");
blog.setAuthor("孙尚香");
blog.setCreateTime(new Date());
sqlSession.close();
}
// 查询博客
List
select * from blog where 1=1
and title=#{title}
and author=#{author}
@Test
public void queryBlogIf(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
map.put("author","小鲁班");
List
for (Blog blog:blogs) {
System.out.println(blog);
}
sqlSession.close();
}
List<Blog> queryBlogChoose(Map map);
<select id="queryBlogChoose" parameterType="map" resultType="blog">
select* from blog
<where>
<choose>
<when test="title!=null">
title=#{title}
when>
<when test="author!=null">
And author=#{author}
when>
<otherwise>
And views=#{views}
otherwise>
choose>
where>
select>
@Test
Public void queryBlogIfChoose(){
SqlSession sqlSession=MybatisUtils.getSqlSession();
BlogMapper blogMapper=sqlSession.getMapper(BlogMapper.class);
HashMap map=new HashMap();
map.put("title","鲁班学java");
List<Blog> blogs=blogMapper.queryBlogChoose(map);
System.out.println(blogs);
sqlSession.close();
}
//更新博客
Int updateBlog(Map map);
<update id="updateBlog" parameterType="map">
Update blog
<set>
<if test="title!=null">
title=#{title},
if>
<if test="author!=null">
author=#{author}
if>
set>
Where id=#{id}
update>
@Test
Public void updateBlog(){
SqlSession sqlSession=MybatisUtils.getSqlSession();
BlogMapper blogMapper=sqlSession.getMapper(BlogMapper.class);
HashMap map=new HashMap();
map.put("title","猪八戒学java");
map.put("author","猪八戒");
map.put("id","74f4408b6c634a019bd23825768082a5");
blogMapper.updateBlog(map);
sqlSession.close();
}
set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。
//查询第1-2-3
List<Blog> queryBlogForeach(Mapmap);
<select id="queryBlogForeach" parameterType="map" resultType="blog">
select* from blog
<where>
<foreach collection="ids"
item="id"
open="and("
close=")"
separator="or">
id=#{id}
foreach>
where>
@Test
Public void queryBlogForeach(){
SqlSession sqlSession=MybatisUtils.getSqlSession();
BlogMapper blogMapper=sqlSession.getMapper(BlogMapper.class);
HashMap map=new HashMap();
ArrayList<Integer> ids=new ArrayList<Integer>();
ids.add(1);
ids.add(2);
ids.add(3);
map.put("ids",ids);
List<Blog> blogs=blogMapper.queryBlogForeach(map);
for(Blogblog:blogs){
System.out.println(blog);
}
sqlSession.close();
}
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!
提示 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。