zoukankan      html  css  js  c++  java
  • 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>
    
  • 相关阅读:
    常见字符编码扫盲(UTF,Unicode, GB2312) 四
    Ogre 实用技巧 四
    CEGUI中文显示问题的解决方法 四
    大幅革新 AMD下一代图形产品前瞻 四
    力争上游 ——我眼中的“计算机产业链” 四
    养成 SQL SERVER 的好习惯 四
    说说 Windows 中的中文字体 四
    Unicode字符集和多字节字符集关系 四
    各种电影 四
    [projectEuler.net]12
  • 原文地址:https://www.cnblogs.com/godles/p/12343537.html
Copyright © 2011-2022 走看看