什么是动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句。
利用动态SQL这一特性可以彻底摆脱这种痛苦。
动态SQL元素和JSTL或基于类似XML的文本处理器相似。
在MyBatis之前的版本中,有很多元素需要花时间了解。
MyBatis3大大精简了元素种类,现在只需学习原来一半的元素便可。
MyBatis 采用功能强大的基于OGNL的表达式来淘汰其它大部分元素。
动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了。
建议:
if choose(when,otherwise) trim(where,set) foreach
SQL语句
CREATE TABLE `blog` ( `id` varchar(50) NOT NULL COMMENT '博客ID', `title` varchar(100) NOT NULL COMMENT '博客标题', `author` varchar(30) NOT NULL COMMENT '博客作者', `create_time` datetime NOT NULL COMMENT '创建时间', `views` int(30) NOT NULL COMMENT '浏览量' ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
创建一个基础工程
导包。
编写配置文件。
编写实体类。
public class Blog { private String id; private String title; private String author; private Date createTime;//属性名和字段名不一致 private int views; }
编写实体类对应Mapper接口和Mapper.xml文件。
//插入数据 int addBlog(Blog blog);
<insert id="addBlog" parameterType="blog"> insert into blog (id, title, author, create_time, views) values (#{id},#{title},#{author},#{createTime},#{views}) </insert>
IDUtils工具类
@SuppressWarnings("all") //抑制警告 public class IDUtils { public static String getId(){ return UUID.randomUUID().toString().replaceAll("-",""); } @Test public void test(){ System.out.println(IDUtils.getId()); System.out.println(IDUtils.getId()); System.out.println(IDUtils.getId()); } }
抑制警告
测试
@Test public void testAddBlog() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); Blog blog = new Blog(); blog.setId(IDUtils.getId()); blog.setTitle("Mybatis如此简单"); blog.setAuthor("Jcooling"); blog.setCreateTime(new Date()); blog.setViews(9999); mapper.addBlog(blog); blog.setId(IDUtils.getId()); blog.setTitle("Java如此简单"); mapper.addBlog(blog); blog.setId(IDUtils.getId()); blog.setTitle("Spring如此简单"); mapper.addBlog(blog); blog.setId(IDUtils.getId()); blog.setTitle("Linux如此简单"); mapper.addBlog(blog); sqlSession.commit(); sqlSession.close(); }
接口类
//查询博客 List<Blog> queryBlogIf(Map map);
对应xml
<select id="queryBlogIf" 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>
测试
@Test public void testQueryBlogIf() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap map = new HashMap(); // map.put("title","Linux如此简单"); map.put("author","JCooling"); List<Blog> blogs = mapper.queryBlogIf(map); for (Blog blog : blogs) { System.out.println(blog); } sqlSession.close(); }
接口类
//查询 List<Blog> queryBlogChoose(Map map);
对应xml
<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 testQueryBlogChoose() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap map = new HashMap(); map.put("title","Linux如此简单"); // map.put("author","JCooling"); map.put("views","9999"); List<Blog> blogs = mapper.queryBlogChoose(map); for (Blog blog : blogs) { System.out.println(blog); } sqlSession.close(); }
接口类
//查询博客 List<Blog> queryBlogIf(Map map); //更新博客 int updateBlogSet(Map map);
对应xml
<select id="queryBlogIf" parameterType="map" resultType="blog"> select * from blog <where> <if test="title!=null"> title=#{title} </if> <if test="author!=null"> and author=#{author} </if> </where> </select> <update id="updateBlogSet" 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 testQueryBlogIf() { //同前 } @Test public void testUpdateBlogSet() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap map = new HashMap(); map.put("title","Linux如此简单2"); //map.put("author","JCooling"); map.put("id","66c94df75eb34c8eab1a82c415b28dc2"); int i = mapper.updateBlogSet(map); if (i==1) { System.out.println("更新成功"); }else { System.out.println("更新失败"); } sqlSession.commit(); sqlSession.close(); }
set元素会动态前置set关键字,同时也会删掉无关的逗号。
trim
//prefixOverrides 前缀 //suffixOverrides 后缀 <trim prefix="where" prefixOverrides="and|or" suffixOverrides=""></trim>
所谓的动态SQL,本质还是SQL语句,只是我们可以在SQL层面,去执行一个逻辑代码。
动态SQL的另外一个常用的操作需求是对一个集合进行遍历,|通常是在构建IN条件语句的时候。
foreach元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。
它也允许你指定开头与结尾的字符串以及迭代结果之间放置分隔符。不会偶然地附加多余的分隔符。
注意
接口类
//查询第1、2、3号记录的博客 List<Blog> queryBlogForeach(Map map);
对应xml
<!--我们现在传递一个万能的map,这map中可以存在一个集合!--> <select id="queryBlogForeach" parameterType="map" resultType="blog"> select * from blog_1 <where> <foreach collection="ids" item="id" open="and (" close=")" separator="or"> id=#{id} </foreach> </where> </select>
测试
@Test public void testQueryBlogForeach() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap map = new HashMap(); ArrayList<Integer> ids = new ArrayList<Integer>(); ids.add(1); ids.add(2); map.put("ids",ids); List<Blog> blogs = mapper.queryBlogForeach(map); for (Blog blog : blogs) { System.out.println(blog); } sqlSession.close(); }
有的时候,我们可能会将一些功能的部分抽取出来,方便复用。
接口类
//查询博客 List<Blog> queryBlogIf1(Map map);
对应xml
//使用SQL标签抽取公共的部分 <sql id="if-title-author"> <if test="title!=null"> title=#{title} </if> <if test="author!=null"> and author=#{author} </if> </sql> //在需要使用的地方使用include标签引用即可 <select id="queryBlogIf1" parameterType="map" resultType="blog"> select * from blog <where> <include refid="if-title-author"></include> </where> </select>
测试
@Test public void testQueryBlogIf1() { //同前 }
注意事项