不能吧,你不能这样,都最后了-------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。实现通用。


相关文章
|
3月前
|
缓存 Java 数据库连接
mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)
文章介绍了MyBatis的缓存机制,包括一级缓存和二级缓存的配置和使用,以及如何整合第三方缓存EHCache。详细解释了一级缓存的生命周期、二级缓存的开启条件和配置属性,以及如何通过ehcache.xml配置文件和logback.xml日志配置文件来实现EHCache的整合。
mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)
|
8天前
|
SQL XML Java
mybatis实现动态sql
MyBatis的动态SQL功能为开发人员提供了强大的工具来应对复杂的查询需求。通过使用 `<if>`、`<choose>`、`<foreach>`等标签,可以根据不同的条件动态生成SQL语句,从而提高代码的灵活性和可维护性。本文详细介绍了动态SQL的基本用法和实际应用示例,希望对您在实际项目中使用MyBatis有所帮助。
28 11
|
22天前
|
缓存 Java 数据库连接
MyBatis缓存机制
MyBatis提供两级缓存机制:一级缓存(Local Cache)默认开启,作用范围为SqlSession,重复查询时直接从缓存读取;二级缓存(Second Level Cache)需手动开启,作用于Mapper级别,支持跨SqlSession共享数据,减少数据库访问,提升性能。
27 1
|
25天前
|
缓存 Java 数据库连接
深入探讨:Spring与MyBatis中的连接池与缓存机制
Spring 与 MyBatis 提供了强大的连接池和缓存机制,通过合理配置和使用这些机制,可以显著提升应用的性能和可扩展性。连接池通过复用数据库连接减少了连接创建和销毁的开销,而 MyBatis 的一级缓存和二级缓存则通过缓存查询结果减少了数据库访问次数。在实际应用中,结合具体的业务需求和系统架构,优化连接池和缓存的配置,是提升系统性能的重要手段。
41 4
|
1月前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
1月前
|
SQL 缓存 Java
MyBatis如何关闭一级缓存(分注解和xml两种方式)
MyBatis如何关闭一级缓存(分注解和xml两种方式)
82 5
|
2月前
|
SQL Java 数据库连接
mybatis使用四:dao接口参数与mapper 接口中SQL的对应和对应方式的总结,MyBatis的parameterType传入参数类型
这篇文章是关于MyBatis中DAO接口参数与Mapper接口中SQL的对应关系,以及如何使用parameterType传入参数类型的详细总结。
55 10
|
2月前
|
缓存 Java 数据库连接
使用MyBatis缓存的简单案例
MyBatis 是一种流行的持久层框架,支持自定义 SQL 执行、映射及复杂查询。本文介绍了如何在 Spring Boot 项目中集成 MyBatis 并实现一级和二级缓存,以提高查询性能,减少数据库访问。通过具体的电商系统案例,详细讲解了项目搭建、缓存配置、实体类创建、Mapper 编写、Service 层实现及缓存测试等步骤。
|
3月前
|
SQL XML Java
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
文章介绍了MyBatis中动态SQL的用法,包括if、choose、where、set和trim标签,以及foreach标签的详细使用。通过实际代码示例,展示了如何根据条件动态构建查询、更新和批量插入操作的SQL语句。
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
|
2月前
|
SQL 缓存 Java
JVM知识体系学习三:class文件初始化过程、硬件层数据一致性(硬件层)、缓存行、指令乱序执行问题、如何保证不乱序(volatile等)
这篇文章详细介绍了JVM中类文件的初始化过程、硬件层面的数据一致性问题、缓存行和伪共享、指令乱序执行问题,以及如何通过`volatile`关键字和`synchronized`关键字来保证数据的有序性和可见性。
36 3