不能吧,你不能这样,都最后了-------sql和缓存(“最易懂得MyBatis学习”)(中)

简介: 4. trim(where,set)4.1 where4.2 set5. choose(when,otherwise)6. foreach使用7. SQL片段8. 总结

4. trim(where,set)

4.1 where

<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>

微信图片_20211230122330.png


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


  • 我们很容易看到,之前提到的if是用了一个where 1=1.其实这个是不合适的。但是现在加了个标签,它可以自动识别是不是第一个where,然后在判断是否加上and。


  • where的存在会判断and是不是需要,第二个前面及以后要加上and。


如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:

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


prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。


4.2 set


  • set元素会动态前置SET关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的SQL语句的后面留下这些逗号
<!--基本类型不需要resultType-->
<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>
@Test
public void updateBlog(){
  SqlSession sqlSession = MybatisUtils.getSqlSession();
  BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
  HashMap map = new HashMap();
  map.put("id","ac040b29e3b047a09a4fe78797193597");
  map.put("author","王木木");
  map.put("title","Java1");
  mapper.updateBlog(map);
  sqlSession.close();
}

来看看与 set 元素等价的自定义 trim 元素吧:

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>


注意,我们覆盖了后缀值设置,并且自定义了前缀值。


5. 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">
                author = #{author}
            </when>
            <otherwise>
                and views = #{views}
            </otherwise>
        </choose>
    </where>
</select>
select * from user where 1=1 and
<foreach item="id" collection="ids"
  open="(" separator="or" close=")">
</foreach>
(id=1 or id=2 or id=3)

这个choose有点像switch,case。他只能运行一个。比如说前面的都不符合,那他必须有一个views要符合,否则会报错。前面的按照顺序有一个符合了,那他就跳出去了。


6. foreach


微信图片_20211230122650.png

select * from user where 1=1 and
<foreach item="id" collection="ids"
  open="(" separator="or" close=")">
</foreach>
(id=1 or id=2 or id=3)

使用

//查询第1-2-3号记录的博客
List<Blog> queryBlogForeach(Map map);
<!--传递一个万能的map,这个map可以存在一个集合-->
<select id="queryBlogForeach" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <foreach item="id" collection="ids" open="and (" separator="or" close=")">
            id = #{id}
        </foreach>
    </where>
</select>
@Test
public void queryBlogForeach(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    HashMap map = new HashMap();
    //这里因为是uuid是String,如果是1,2这种就用Integer
    ArrayList<String> ids = new ArrayList<String>();
    map.put("ids",ids);
    List<Blog> blogs = mapper.queryBlogForeach(map);
    for (Blog blog : blogs) {
        System.out.println(blog);
    }
    sqlSession.close();
}

微信图片_20211230122807.png


我们还可以进行下面的测试

@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("ac040b29e3b047a09a4fe78797193597");
    map.put("ids",ids);
    List<Blog> blogs = mapper.queryBlogForeach(map);
    for (Blog blog : blogs) {
        System.out.println(blog);
    }
    sqlSession.close();
}

微信图片_20211230122842.png

@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("ac040b29e3b047a09a4fe78797193597");
    ids.add("a46a7874d69f4d69b9572816d8f30ab7");
    map.put("ids",ids);
    List<Blog> blogs = mapper.queryBlogForeach(map);
    for (Blog blog : blogs) {
        System.out.println(blog);
    }
    sqlSession.close();
}

微信图片_20211230122909.png


7. SQL片段


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


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


微信图片_20211230122946.png


2.在需要使用的地方使用include标签引用即可


我们可以加一个sql标签,id可以随意取,然后下面来一个include refid是引用id,和上面的id是一个。这样就可以实现复用。

<sql id="if-title-author">
    <if test="title != null">
        title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</sql>
<select id="queryBlogIF" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <include refid="if-title-author"/>
    </where>
</select>


3.注意事项:


  • 最好基于单表来定义SQL片段


  • 不要存在where标签


8. 总结


所谓的动态SQL,本质还是SQL语句,只是我们可以在sql层面,去执行一个逻辑代码。

if,where,set,choose,when


动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就ok了


建议:


  • 先在Mysql中写出完整的SQL,再对应的去修改成为我们的动态SQL。实现通用。


相关文章
|
2天前
|
SQL XML Java
mybatis 调用修改SQL时 出现了一个问题 没有修改成功也没有报错
mybatis 调用修改SQL时 出现了一个问题 没有修改成功也没有报错
13 0
|
13天前
|
XML 缓存 Java
MyBatis二级缓存解密:深入探究缓存机制与应用场景
MyBatis二级缓存解密:深入探究缓存机制与应用场景
49 2
MyBatis二级缓存解密:深入探究缓存机制与应用场景
|
1月前
|
SQL 存储 Kubernetes
Seata常见问题之mybatisplus的批量插入方法报SQL错误如何解决
Seata 是一个开源的分布式事务解决方案,旨在提供高效且简单的事务协调机制,以解决微服务架构下跨服务调用(分布式场景)的一致性问题。以下是Seata常见问题的一个合集
26 0
|
1月前
|
SQL XML Java
学习Mybatis相关知识
一、什么是Mybatis? 1、Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。开发人员直接编写原生态sql,即可严格控制sql执行性能、且灵活度高。
13 0
|
1月前
|
SQL Java 关系型数据库
MyBatis的动态SQL之OGNL(Object-Graph Navigation Language)表达式以及各种标签的用法
MyBatis的动态SQL之OGNL(Object-Graph Navigation Language)表达式以及各种标签的用法
18 0
|
1月前
|
SQL Java 关系型数据库
MyBatis中的9种常用动态sql标签精妙用法
MyBatis中的9种常用动态sql标签精妙用法
64 0
|
1月前
|
XML Java 数据库连接
Mybatis-Plus学习小项目及详细教程
Mybatis-Plus学习小项目及详细教程
|
1月前
|
SQL Java 数据库连接
Mybatis拦截器实现带参数SQL语句打印
Mybatis拦截器实现带参数SQL语句打印
|
1月前
|
存储 缓存 Java
什么!?实战项目竟然撞到阿里面试的原题!???关于MyBatis Plus的缓存机制
什么!?实战项目竟然撞到阿里面试的原题!???关于MyBatis Plus的缓存机制
|
1月前
|
缓存 Java 数据库连接
mybatis 数据库缓存的原理
MyBatis 是一个流行的 Java 持久层框架,它封装了 JDBC,使数据库交互变得更简单、直观。MyBatis 支持两级缓存:一级缓存(Local Cache)和二级缓存(Global Cache),通过这两级缓存可以有效地减少数据库的访问次数,提高应用性能。
282 1