什么是动态SQL:动态SQL就是根据不同的条件生成不同的SQL语句
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
if choose (when, otherwise) trim (where, set) foreach创建一个基础工程
导包
编写配置文件
编写实体类
@Data public class Blog { private String id; private String title; private String author; private Date createTime;//属性名与字段名不一致 private int views; }解决实体类中属性名与字段名不一致问题,在核心配置文件中配置 mapUnderscoreToCamelCase
<settings> <!--标准的日志工厂实现--> <setting name="logImpl" value="STDOUT_LOGGING"/> <!--名字必须和官网一样,不能有有空格--> <!--是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>编写实体类对应的Mapper接口和Mapper.xml文件
在BlogMapper接口中写方法
//查询博客 List<Blog> getBlogIF(Map map);在对应的BlogMapper.xml中写sql语句
<!--动态SQL if使用--> <select id="getBlogIF" resultType="Blog" parameterType="map"> select * from mybatis.blog where 1=1 <if test="title !=null"> and title=#{title} </if> <if test="author!=null"> and author=#{author} </if> </select>测试
@Test public void getBlogIF(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap map = new HashMap(); map.put("title","好看的"); map.put("author","春雪恒"); List<Blog> blog = mapper.getBlogIF(map); for (Blog blog1 : blog) { System.out.println(blog1); } sqlSession.close(); }BlogMapper.xml
<!--动态语句 set用法--> <update id="updateBlog" parameterType="map"> update mybatis.blog <set> <if test="title !=null"> title=#{title}, </if> <if test="author !=null"> author=#{author} </if> </set> where id =#{id} </update> <!--动态SOL where使用 where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。 而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。 --> <select id="getBlogChoose" parameterType="map" resultType="Blog"> select * from mybatis.blog <where> <if test="title !=null"> title=#{title} </if> <if test="author!=null"> and author=#{author} </if> </where> </select>BlogMapper.xml
<!--动态SQL语句 choose使用 choose相当于switch只能选择执行一个条件 条件按顺序 --> <select id="getBlogChoose" parameterType="map" resultType="Blog"> select * from mybatis.blog <where> <choose> <when test="title !=null"> title=#{title} </when> <when test="author!=null"> author=#{author} </when> <otherwise> views=#{views} </otherwise> </choose> </where> </select>所谓的动态语句SQL,本质还是SQL语句,只是我们可以再SQL层面,去执行一个逻辑代码
有时候,我们可能会将一些功能的部分抽取出来,方便重复使用
使用sql标签抽取公共部分
<!--使用sql标签抽取公共部分--> <sql id="if-title-author"> <if test="title !=null"> and title=#{title} </if> <if test="author!=null"> and author=#{author} </if> </sql>在需要使用的地方用include标签调用
<!--使用include调用sql片段--> <select id="getBlogIF" resultType="Blog" parameterType="map"> select * from mybatis.blog where 1=1 <include refid="if-title-author"></include> </select>注意事项:
最好基于单表来定义SQL片段!sql片段中不要存在where标签!foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。
select *from blog where 1=1 and <foreach item="id" collection="ids" open="(" separator="or" close=")"> id =#{id} </foreach> (id=1 or id=2 or id=3) <!-- select *from blog where 1=1 and (id=1 or id=2 or id=3) 我们现在传一个map,这个map中存在一个集合! --> <select id="getBlogForEach" parameterType="map" resultType="Blog"> select * from mybatis.blog <where> <foreach collection="ids" item="id" open="and (" close=")" separator="or"> id = #{id} </foreach> </where> </select>测试:
@Test public void getBlogForEach(){ 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); ids.add(3); for (Integer id : ids) { System.out.println(id); } map.put("ids",ids); List<Blog> blog = mapper.getBlogForEach(map); for (Blog blog1 : blog) { System.out.println(blog1); } sqlSession.close(); }动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了!
建议:
先在mysql中写出完整的SQL,在去对应的去修改成为我们的动态SQL实现通用即可!