Mybatis—动态SQL

  • MyBatis 的强大特性之一便是它的动态 SQL。
  • 动态SQL就是根据不同的条件生成不同的SQL语句。
  • 动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。
  • MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。

1、搭建环境

最完整的包结构图示:

  1. 创建博客表

    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
    
  2. 创建基础工程
    1. pom.xml导包

      <dependencies>
              <!--mysql驱动-->
              <dependency>
                  <groupId>mysql</groupId>
                  <artifactId>mysql-connector-java</artifactId>
                  <version>5.1.47</version>
              </dependency>
              <!--mybatis-->
      
              <dependency>
                  <groupId>org.mybatis</groupId>
                  <artifactId>mybatis</artifactId>
                  <version>3.5.4</version>
              </dependency>
              <!--junit-->
              <dependency>
                  <groupId>junit</groupId>
                  <artifactId>junit</artifactId>
                  <version>4.12</version>
              </dependency>
             <!--lombok-->
              <dependency>
                  <groupId>org.projectlombok</groupId>
                  <artifactId>lombok</artifactId>
                  <version>1.18.10</version>
              </dependency>
          </dependencies>
      
    2. resources下编写配置文件mybatis-config.xml
      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE configuration
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-config.dtd">
      <!--configuration核心配置文件-->
      <configuration>
      
          <!--引入外部配置文件-->
          <properties resource="db.properties"/>
      
          <settings>
      
              <setting name="logImpl" value="LOG4J"/>
              <!--是否开启自动驼峰命名规则(camel case)映射-->
              <setting name="mapUnderscoreToCamelCase" value="true"/>
          </settings>
      
          <!--可以给实体类起别名-->
          <typeAliases>
              <package name="com.jiang.pojo"/>
          </typeAliases>
      
          <environments default="development">
              <environment id="development">
                  <transactionManager type="JDBC"/>
                  <dataSource type="POOLED">
                      <property name="driver" value="${driver}"/>
                      <property name="url" value="${url}"/>
                      <property name="username" value="${username}"/>
                      <property name="password" value="${pwd}"/>
                  </dataSource>
              </environment>
          </environments>
      
          <mappers>
              <mapper class="com.jiang.dao.BlogMapper"/>
          </mappers>
      
      </configuration>
    3. resources下编写配置文件db.properties
      driver=com.mysql.jdbc.Driver
      url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
      username=root
      pwd=123456
    4. resources下编写配置文件log4j.properties
      ### 设置###
      log4j.rootLogger = debug,stdout,D,E
      
      ### 输出信息到控制抬 ###
      log4j.appender.stdout = org.apache.log4j.ConsoleAppender
      log4j.appender.stdout.Target = System.out
      log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
      log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
      
      ### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
      log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
      log4j.appender.D.File = ./log/log.log
      log4j.appender.D.Append = true
      log4j.appender.D.Threshold = DEBUG
      log4j.appender.D.layout = org.apache.log4j.PatternLayout
      log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
      
      ### 输出ERROR 级别以上的日志到=E://logs/error.log ###
      log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
      log4j.appender.E.File =./log/error.log
      log4j.appender.E.Append = true
      log4j.appender.E.Threshold = ERROR
      log4j.appender.E.layout = org.apache.log4j.PatternLayout
    5. java包下创建com.jiang.pojo包,在此包下编写Blog实体类
      package com.jiang.pojo;
      
      import lombok.Data;
      
      import java.util.Date;
      
      @Data
      public class Blog {
      
          private String id;
          private String title;
          private String author;
          private Date createTime;  //属性名和字段名不一致,
          private int views;
      
      }
      
    6. java包下创建com.jiang.dao包,在此包下编写实体类对应的
      • BlogMapper接口
      • BlogMapper.XML文件
        <?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE mapper
                PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
                "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        <mapper namespace="com.jiang.dao.BlogMapper">
        </mapper>
    7. java包下创建com.jiang.utils包编写MybatisUtils工具类
      package com.jiang.utils;
      
      import org.apache.ibatis.io.Resources;
      import org.apache.ibatis.session.SqlSession;
      import org.apache.ibatis.session.SqlSessionFactory;
      import org.apache.ibatis.session.SqlSessionFactoryBuilder;
      
      import java.io.IOException;
      import java.io.InputStream;
      
      //sqlSessionFactory --> sqlSession
      public class MybatisUtils {
      
          private static SqlSessionFactory sqlSessionFactory;
      
          static{
              try {
                  //使用Mybatis第一步:获取sqlSessionFactory对象
                  String resource = "mybatis-config.xml";
                  InputStream inputStream = Resources.getResourceAsStream(resource);
                  sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
              } catch (IOException e) {
                  e.printStackTrace();
              }
      
          }
      
          public static SqlSession  getSqlSession(){
              return sqlSessionFactory.openSession(true);
          }
      
      }
      
    8. java包下创建com.jiang.utils包编写UUID工具类
      //这个帮助我们等会生成随机数
      package com.jiang.utils;
      
      import org.junit.Test;
      
      import java.util.UUID;
      
      @SuppressWarnings("all") //抑制警告
      public class IDutils {
      
          public static String getId(){
              return UUID.randomUUID().toString().replaceAll("-","");
          }
      }
      
    9. 添加表中的数据
      • 接口

         //插入数据
            int addBlog(Blog blog);
      • 接口配置
         <insert id="addBlog" parameterType="blog">
                insert into mybatis.blog (id, title, author, create_time, views)
                values (#{id},#{title}, #{author}, #{createTime}, #{views});
            </insert>
      • test.java包中编写测试类MyTest
        @Test
            public void addInitBlog() {
                SqlSession session = MybatisUtils.getSqlSession();
                BlogMapper mapper = session.getMapper(BlogMapper.class);
                for (int i = 0; i < 4; i++) {
                    Blog blog = new Blog();
                    blog.setId(IDutils.getId());
                    blog.setTitle("Mybatis So easy");
                    blog.setAuthor("姜嘉航");
                    blog.setCreateTime(new Date());
                    blog.setViews(9999);
                    mapper.addBlog(blog);
                }
        
                Blog blog1 = new Blog();
                blog1.setId(IDutils.getId());
                blog1.setTitle("Java So easy");
                blog1.setAuthor("姜嘉航");
                blog1.setCreateTime(new Date());
                blog1.setViews(9999);
                mapper.addBlog(blog1);
        
                Blog blog2 = new Blog();
                blog2.setId(IDutils.getId());
                blog2.setTitle("Spring So easy");
                blog2.setAuthor("姜嘉航");
                blog2.setCreateTime(new Date());
                blog2.setViews(9999);
                mapper.addBlog(blog2);
        
                Blog blog3 = new Blog();
                blog3.setId(IDutils.getId());
                blog3.setTitle("微服务 So easy");
                blog3.setAuthor("姜嘉航");
                blog3.setCreateTime(new Date());
                blog3.setViews(9999);
                mapper.addBlog(blog3);
        
                Blog blog4 = new Blog();
                blog4.setId(IDutils.getId());
                blog4.setTitle("微服务 So easy");
                blog4.setAuthor("姜嘉航");
                blog4.setCreateTime(new Date());
                blog4.setViews(9999);
                mapper.addBlog(blog4);
        
                session.close();
            }
        

      插入成功!

2、If

要求:

通过作者名,和博客名字来查询博客

如果作者名字为null,则根据博客名字来查询

  1. 编写BlogMapper接口

      //查询博客
        List<Blog> getBlogByIF(Map map);
  2. 编写BlogMapper.xml
    <!--如果我们需要拼接where条件,又不希望客户端传递错误信息,需要更加智能的where标签,如果后面的语句有逗号,就自动添加where,如果后面语句开头是and或者or,它可以自动去掉-->
    <select id="getBlogByIF" parameterType="map" resultType="Blog">
            select * from mybatis.blog
                <if test="title != null">
                    title = #{title}
                </if>
                <if test="author != null">
                    and author = #{author}
                </if>
        </select>
  3. 测试不同参数结果运行
      @Test
        public void testGetBlogIf() {
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    
            HashMap<String, String> map = new HashMap<String, String>();
            map.put("title","Mybatis So easy");
            map.put("author","姜小姜");
            List<Blog> blogByIF = mapper.getBlogByIF(map);
    
            for (Blog blog : blogByIF) {
                System.out.println(blog);
            }
            sqlSession.close();
        }

3、trim(where,set)

3.1、set

要求:更新博客

  1. 编写BlogMapper接口

    //更新博客
        int updateBlog(Map map);
  2. 编写BlogMapper.xml
     <!--set标签,这里,set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的 SQL 语句的后面留下这些逗号-->
    <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>

    set元素等价于自定义的trim元素:

    <trim prefix="SET" suffixOverrides=",">
      ...
    </trim>
  3. 测试
     @Test
        public void upadateBlog() {
            SqlSession session = MybatisUtils.getSqlSession();
            BlogMapper mapper = session.getMapper(BlogMapper.class);
            HashMap<String, String> map = new HashMap<String, String>();
    
            map.put("id", "c4cab03768a34dcbaafa36731e680b3e");
            map.put("author","姜小帅");
    
            mapper.updateBlog(map);
    
        }
    

3.2、where

  select * from mybatis.blog
        <where>
            <if test="title != null">
                title = #{title}
            </if>
            <if test="author != null">
                and author = #{author}
            </if>
        </where>

where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。

where元素等价于自定义trim元素

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>

4、SQL片段

有的时候,我们可能会将一些功能的部分抽取出来,方便复用!

  1. 使用SQL标签抽取公共的部分

    <sql id="if-title-author">
        <if test="title != null">
            title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </sql>
  2. 在需要使用的地方使用Include标签引用即可
    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <include refid="if-title-author"></include>
        </where>
    </select>

注意事项:

  • 最好基于单表来定义SQL片段!
  • 不要存在where标签

5、foreach

collection传递的参数:你要给他传递的集合对象

item:遍历出来集合的每一项,可以再foreach中使用

open:用什么字符串打开

close:用什么字符串结束

separator:分隔符

  1. 编写BlogMapper接口

    List<Blog> queryBlogForeach(Map map);
  2. 编写BlogMapper.xml
      <!--相当于sql语句:
          select * from mybatis.blog where and(id=1 or id=2 or id=3 or...)
    -->
    <select id="queryBlogForeach" parameterType="map" resultType="blog">
            select * from mybatis.blog
    
            <where>
               <foreach collection="ids" item="id" open="and (" close=")" separator="or">
                   id = #{id}
               </foreach>
            </where>
    
        </select>
  3. 测试
     @Test
        public void queryBlogForEach() {
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    
            HashMap map = new HashMap();
    
            ArrayList<String> ids = new ArrayList<String>();
            ids.add("c4cab03768a34dcbaafa36731e680b3e");
            ids.add("372b3c3a0ce54cb19675e2f703afb310");
            ids.add("523b2881f4d34682956b1ede6214daba");
    
            map.put("ids", ids);
            List<Blog> blogs = mapper.queryBlogForeach(map);
    
            System.out.println(blogs);
    
            sqlSession.close();
        }

6、choose,when,otherwise

有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句

还是上面的例子

 select * from mybatis.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>

原文地址:https://www.cnblogs.com/godles/p/12343537.html

时间: 2024-11-12 22:47:07

Mybatis—动态SQL的相关文章

MyBatis动态SQL小结

p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-bottom: .0001pt; text-align: justify; font-size: 10.5pt; font-family: 等线 } .MsoChpDefault { font-family: 等线 } div.WordSection1 { } ol { margin-bottom: 0cm } ul { margin-bottom: 0cm } Mybati

MyBatis动态SQL————MyBatis动态SQL标签的用法

1.MyBatis动态SQL MyBatis 的强大特性之一便是它的动态 SQL,即拼接SQL字符串.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦.拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号.利用动态 SQL 这一特性可以彻底摆脱这种痛苦. 通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中. 动态 SQL 元素和

mybatis实战教程(mybatis in action)之八:mybatis 动态sql语句

mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类:1. if 语句 (简单的条件判断)2. choose (when,otherwize) ,相当于java 语言中的 switch ,与 jstl 中的choose 很类似.3. trim (对包含的内容加上 prefix,或者 suffix 等,前缀,后缀)4. where (主要是用来简化sql语句中where条件判断的,能智能的处理 a

用Groovy模板写MyBatis动态SQL

MyBatis动态SQL简介 MyBatis有个强大的功能,动态SQL.有了这个功能,定义在Mapper里的SQL语句,就不必是静止不变的了,而是可以根据传入的参数,动态调整.下面是MyBatis官方文档里的一个if语句的例子: <select id="findActiveBlogWithTitleLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = 'ACTIVE' <if test=

Mybatis 动态sql(转载)

原文地址:http://www.cnblogs.com/dongying/p/4092662.html 传统的使用JDBC的方法,相信大家在组合复杂的的SQL语句的时候,需要去拼接,稍不注意哪怕少了个空格,都会导致错误.Mybatis的动态SQL功能正是为了解决这种问题, 其通过 if, choose, when, otherwise, trim, where, set, foreach标签,可组合成非常灵活的SQL语句,从而提高开发人员的效率.下面就去感受Mybatis动态SQL的魅力吧: 1

mybatis 动态sql语句

mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类: 1. if 语句 (简单的条件判断) 2. choose (when,otherwize) ,相当于java 语言中的 switch ,与 jstl 中的choose 很类似. 3. trim (对包含的内容加上 prefix,或者 suffix 等,前缀,后缀) 4. where (主要是用来简化sql语句中where条件判断的,能智能的

mybatis 动态sql和参数

mybatis 动态sql 名词解析 OGNL表达式 OGNL,全称为Object-Graph Navigation Language,它是一个功能强大的表达式语言,用来获取和设置Java对象的属性,它旨在提供一个更高的更抽象的层次来对Java对象图进行导航. OGNL表达式的基本单位是"导航链",一般导航链由如下几个部分组成: 属性名称(property) 方法调用(method invoke) 数组元素 所有的OGNL表达式都基于当前对象的上下文来完成求值运算,链的前面部分的结果将

4.mybatis动态SQL拼接/取值/OGNL

4.mybatis动态SQL拼接/取值 一.mybatis框架的SQL拼接是采用OGNL表达式进行的,以下我会列出常用的取值方法. 图片来源:慕课网 1.1常用的取值方法: 1.2特殊的取值方法: mod为取余数

MyBatis动态SQL之一使用 if 标签和 choose标签

bootstrap react https://segmentfault.com/a/1190000010383464 xml 中 < 转义 to thi tha <if test="pricehigh!=null"> and price < #{pricehigh,jdbcType=INTEGER} </if> MyBatis动态SQL之一使用 if 标签和 choose标签 <select id="getItems" p

mybatis动态sql中的两个内置参数(_parameter和_databaseId)

<!-- mybatis动态sql的两个内置参数           不只是方法传递过来的参数可以被用来判断,取值       mybatis默认还有两个内置参数           _parameter:代表整个参数                                      单个参数:_parameter就是这个参数                                      多个参数:参数会被封装为一个map:_parameter就是代表这个map