Mybatis动态SQL

  • 动态SQL是指根据不同的条件生成不同的SQL语句
  • 所谓的动态SQL,本质还是SQL语句,只是可以在SQL层面去执行一个逻辑代码
  • 动态SQL就是在拼接SQL语句,只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了
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
    
  • 创建一个基础工程

    1. 导包

    2. 编写配置文件

      <?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="STDOUT_LOGGING"/>
              <!--是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。-->
              <setting name="mapUnderscoreToCamelCase" value="true"/>
          </settings>
      
          <!--可以给实体类起别名-->
          <typeAliases>
              <package name="com.ping.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="${password}"/>
                  </dataSource>
              </environment>
          </environments>
      
          <mappers>
              <mapper class="com.ping.dao.BlogMapper"/>
          </mappers>
      
      </configuration
      
    3. 编写工具类

      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();
              }
          }
      
          //既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
          //SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
      
          public static SqlSession getSqlSession() {
              return sqlSessionFactory.openSession(true);
          }
      }
      
      //获取随机ID
      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());
          }
      
      }
      
      
    4. 编写实体类

      @Data
      public class Blog {
          private String id;
          private String title;
          private String author;
          private Date createTime; //属性名和字段名不一致
          private int views;
      }
      
    5. 编写实体类对应Mapper接口

      public interface BlogMapper {
          //插入数据
          int addBlog(Blog blog);
      }
      
    6. Mapper.xml文件

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <mapper namespace="com.ping.dao.BlogMapper">
          <insert id="addBlog" parameterType="Blog">
              insert into blog (id, title, author, create_time, views)
              values(#{id}, #{title}, #{author},#{createTime}, #{views});
          </insert>
      
      </mapper>
      
    7. 测试类插入数据

      public class MyTest {
          @Test
          public void testaddBlog(){
              SqlSession sqlSession = MybatisUtils.getSqlSession();
              BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
      
              Blog blog = new Blog();
              blog.setId(IDUtils.getId());
              blog.setTitle("学习JavaEE");
              blog.setAuthor("张三");
              blog.setCreateTime(new Date());
              blog.setViews(9999);
      
              mapper.addBlog(blog);
      
              blog.setId(IDUtils.getId());
              blog.setTitle("学习Mybatis");
              blog.setViews(1111);
              mapper.addBlog(blog);
      
              blog.setId(IDUtils.getId());
              blog.setTitle("学习Spring");
              blog.setViews(5555);
              mapper.addBlog(blog);
      
              blog.setId(IDUtils.getId());
              blog.setTitle("学习Springboot");
              blog.setViews(7777);
              mapper.addBlog(blog);
      
              sqlSession.close();
          }
      }
      

2、IF的使用
  • BlogMapper接口

    public interface BlogMapper {
        //查询Blog
        List<Blog> queryBlogIF(Map map);
    }
    
  • BlogMapper.xml文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.ping.dao.BlogMapper">
        <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>
    </mapper>
    
  • 测试类

    public class MyTest {
        @Test
        public void testqueryBlogIF(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
            HashMap map = new HashMap();
            map.put("title","学习Mybatis");
            map.put("author","张三");
            List<Blog> blogs = mapper.queryBlogIF(map);
            for (Blog blog : blogs) {
                System.out.println(blog);
            }
            sqlSession.close();
        }
    }
    
3、choose(when,otherwise)的使用
  • 不使用所有的条件,而只是从多个条件中选择一个使用
<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>
4、trim、where、set的使用
  • where标签

    • where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
    • 使用where标签修改12.2中BlogMapper.xml文件
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.ping.dao.BlogMapper">
        <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>
    </mapper>
    
  • set标签

    • set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)
    <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>
    
  • trim标签

    • 自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:

      <trim prefix="WHERE" prefixOverrides="AND |OR ">
        ...
      </trim>
      <!--prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。-->
      
    • 与 set 元素等价的自定义 trim 元素

      <trim prefix="SET" suffixOverrides=",">
        ...
      </trim>
      <!--覆盖了后缀值设置,并且自定义了前缀值。 -->
      
5、SQL片段
  • 有的时候,可能会将一些功能的SQL语句抽取出来,方便复用

    • 使用SQL标签抽取公共的部分
    • 在需要使用的地方使用include标签引用即可
  • 使用SOL片段修改12.2中BlogMapper.xml文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.ping.dao.BlogMapper">
        
         <!--使用SQL标签抽取公共的部分-->
        <sql id="if-title-author">
            <if test="title != null">
                and title = #{title}
            </if>
            <if test="author != null">
                and author = #{author}
            </if>
        </sql>
        
        <!--在需要使用的地方使用**include**标签引用即可-->
        <select id="queryBlogIF" parameterType="map" resultType="blog">
            select * from blog
            <where>
    
                <include refid="if-title-author" />
            </where>
        </select>
    </mapper>
    
  • 注意事项

    • 最好基于单表来定义SQL片段
    • 不要存在where标签
6、foreach
  • 数据

  • Mapper接口

    public interface BlogMapper {
        //查询1,2,3号记录的Blog
        List<Blog> queryBlogForeach(Map map);
    }
    
  • Mapper.xml文件

    <!--实现sql语句:select * from blog where 1=1 and (id=1 or id = 2 or id=3)-->
    <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>
    </select>
    <!--foreach 指定一个集合【collection="ids"】,声明可以在元素体内使用的集合项【item="id"】和索引(index)变量。也允许指定开头 【open="and ("】 与结尾 【close=")"】 的字符串以及集合项迭代之间的分隔符 【separator="or"】。 -->
    
  • 测试类

    @Test
    public void testqueryBlogForeach(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        
        HashMap map = new HashMap();
        ArrayList<Integer> ids = new ArrayList<>();
        ids.add(1);
        ids.add(2);
        ids.add(3);
        
        map.put("ids",ids);
        
        List<Blog> blogs = mapper.queryBlogForeach(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }
    
  • 测试查询结果

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fly-ping

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值