文章目录

  • 2.0、注解
  • 2.1、动态sql
    • 2.1.1、where
    • 2.1.2、set
    • 2.1.3、trim
      • 2.1.3.1、trim的where
      • 2.1.3.2、trim的set
    • 2.1.4.1、choose
    • 2.1.5.1、foreach
    • 2.1.6、模糊查询3种方法
    • 2.1.7、特殊符号处理
  • 2.2、缓存
    • 2.2.0、缓存简述
    • 2.2.1、一级缓存
    • 2.2.2、二级缓存

2.0、注解

简单的sql语句可以用注解,

但是复杂sql语句推荐使用xml文件来写

  • @Insert : 插入 sql , 和 xml insert sql 语法完全一样

  • @Select : 查询 sql, 和 xml select sql 语法完全一样

  • @Update : 更新 sql, 和 xml update sql 语法完全一样

  • @Delete : 删除 sql, 和 xml delete sql 语法完全一样

  • @Param : 入参

  • @Results : 设置结果集合

  • @Result : 结果

想这个简单的sql语句,我们用注解写

@Select("select status from article where id = #{id}")

但是这个,你如果回车,他会拼接字符串,对我们后期维护很不友好,所以还是推荐使用xml文件编写sql文件

@Select("SELECT article.id,title,author,content,type.name as type_id,STATUS,admin.account as admin_id,opertime FROM book.article INNER JOIN TYPE ON article.type_id = type.id INNER JOIN admin ON article.admin_id = admin.id where article.status = 1")
@Update("update article set title = #{title},author = #{author},content = #{content},type_id = #{type_id},status = #{status},admin_id = #{admin_id},opertime = #{opertime} where id=#{id}")@Delete("delete from article where id = #{id}")@Insert("insert into book.article(title,author,content,type_id,status,admin_id,opertime) value(#{title},#{author},#{content},#{type_id},#{status},#{admin_id},#{opertime})")

2.1、动态sql

当我们进行条件查询、修改的时候,可能有些信息用户没勾选,所以传过来是空,那么我们在进行对应的操作的时候,需要考虑到这些情况,如果没有信息的话, 默认是null,那我们总部能修改信息为null

那么这个时候就很需要动态sql

2.1.1、where

where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

List<Game> queryGameInfoByTrodition(Game game);
  <resultMap id="toList" type="Game"><id column="id" property="id"/><id column="name" property="name"/><id column="game_desc" property="gameDesc"/></resultMap><!-- 动态sql问题 --><select id="queryGameInfoByTrodition" parameterType="Game" resultMap="toList">select*fromgame<<where><if test="id != null">id = #{id}</if><if test="name != null">and name like concat('%',#{name}) or name like concat(#{name},'%') or name like concat('%',#{name},'%')</if><if test="gameDesc != null">and game_desc = #{gameDesc}</if></where></select>

2.1.2、set

set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。

int updateGameInfo(Game game);
<update id="updateGameInfo">updategame<set><if test="name != null">name = #{name},</if><if test="gameDesc != null">geme_desc = #{gameDesc}</if></set>where id = #{id}</update>

2.1.3、trim

通过自定义 trim 元素来定制 whereset元素的功能。

  • prefix:前缀
  • prefixOverrides : 前缀重写/覆盖
  • suffix:后缀
  • suffixOverrides : 后缀重写/覆盖

2.1.3.1、trim的where

List<Game> queryGameInfoByTrodition(Game game);
    <resultMap id="toList" type="Game"><id column="id" property="id"/><id column="name" property="name"/><id column="game_desc" property="gameDesc"/></resultMap><!-- 动态sql问题 --><select id="queryGameInfoByTrodition" parameterType="Game" resultMap="toList">select*fromgame<trim prefix="where" prefixOverrides="and | or"><if test="id != null">id = #{id}</if><if test="name != null">and name like concat('%',#{name}) or name like concat(#{name},'%') or name like concat('%',#{name},'%')</if><if test="gameDesc != null">and game_desc = #{gameDesc}</if></trim></select>

2.1.3.2、trim的set

 int updateGameInfo(Game game);
 <update id="updateGameInfo">updategame<trim prefix="set" suffixOverrides=","><if test="name != null">name = #{name},</if><if test="gameDesc != null">geme_desc = #{gameDesc}</if></trim>where id = #{id}</update>

2.1.4.1、choose

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

<select id="findActiveBlogLike"resultType="Blog">SELECT * FROM BLOG WHERE state = ‘ACTIVE’<choose><when test="title != null">AND title like #{title}</when><when test="author != null and author.name != null">AND author_name like #{author.name}</when><otherwise>AND featured = 1</otherwise></choose>
</select>

2.1.5.1、foreach

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!

提示 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

 int deleteGameInfos(String[] arr);

参数是数组 – 下边 collection=“array” , 是集合 下边是 collection=“list”

<delete id="deleteGameInfos">delete from game where id in<foreach collection="array" item="id" open="(" separator="," close=")">#{id}</foreach>
</delete>

2.1.6、模糊查询3种方法

  1. $ 符号拼接

    name like '%${name}' or name like '${name}%' or name like '%${name}%'
    
  2. concat拼接

    name like concat('%',#{name}) or name like concat(#{name},'%') or name like concat('%',#{name},'%')
    
  3. 查询的时候写死

    game.setName("%lol");name like #{name}
    

2.1.7、特殊符号处理

在 mybatis 中的 xml 文件中,存在一些特殊的符号,比如:<、>、"、&、<>

等,正常书写 mybatis 会报错,需要对这些符号进行转义。具体转义如下所示:

特殊字符 转义字符

< &lt;

> &gt;

" &quot;

’ &apos;

& &amp;

除了可以使用上述转义字符外,还可以使用<![CDATA[]]>来包裹特殊字符。如

下所示:

<if test="id != null"> AND <![CDATA[ id <> #{id} ]]> </if>

2.2、缓存

2.2.0、缓存简述

缓存(也称作 cache)的作用是为了减去数据库的压力,提高数据库的性能。缓存实现的原理是从数据库中查询来的对象在使用完后不要销毁,而是存储在内 存(缓存)中,当再次需要获取该对象时,直接从内存(缓存)中直接获取,不再向数据库执行 select 语句,从而减少了对数据库的查询次数,因此提高了数据库的性能。缓存是使用 Map 集合缓存数据的。

Mybatis 有一级缓存和二级缓存。一级缓存的作用域是同一个 SqlSession, 在同一个 sqlSession 中两次执行相的 sql 语句,第一次执行完毕会将数据库 中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查 询,从而提高查询效率。当一个 sqlSession 结束后该 sqlSession 中的一级缓存 也就不存在了。Mybatis 默认开启一级缓存。 二级缓 存是多个 SqlSession 共 享 的 , 其作用域 是 mapper 的 同 一 个 namespace,同的 sqlSession 两次执行相同 namespace 下的 sql 语句且向 sql 中传递参数也相同即最终执行相同的 sql 语句,第一次执行完毕会将数据库 中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查 询,从而提高查询效率。Mybatis 默认没有开启二级缓存需要在 setting 全局参 数中配置开启二级缓存。

2.2.1、一级缓存

Mybatis 对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓 存,一级缓存只是相对于同一个SqlSession 而言。所以在参数和 SQL 完全一样的情况下,我们使用同一个 SqlSession 对象调用一个 Mapper 方法,往往只执行一次 SQL,因为使用 SelSession 第一次查询后,MyBatis 会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,SqlSession 都会取出当前缓存的数据,而不会再次发送 SQL 到数据库。

一级缓存的生命周期

  • MyBatis 在开启一个数据库会话时,会创建一个新的 SqlSession 对象, SqlSession 对象中会有一个新的 Executor 对象。Executor 对象中持有一个新 的 PerpetualCache 对象;当会话结束时,SqlSession 对象及其内部的 Executor 对象还有 PerpetualCache 对象也一并释放掉。

  • 如果 SqlSession 调用了 close()方法,会释放掉一级缓存 PerpetualCache 对象,一级缓存将不可用。

  • 如果 SqlSession 调用了 clearCache(),会清空 PerpetualCache 对象 中的数据,但是该对象仍可使用。

  • SqlSession 中执行了任何一个 update 操作(update()、delete()、insert()) ,都会清空 PerpetualCache 对像的数据,但是该对象可以继续使用

Game queryGameInfoById(Integer id);
<select id="queryGameInfoById" resultMap="toList">select * from game where id = #{id}
</select><resultMap id="toList" type="Game"><id column="id" property="id"/><id column="name" property="name"/><id column="game_desc" property="gameDesc"/>
</resultMap>
@Test
public void queryGameInfoById(){// 从数据库查的数据System.out.println(gameMapper.queryGameInfoById(1));// 从缓存中查询的数据System.out.println(gameMapper.queryGameInfoById(1));// 清空缓存sqlSession.clearCache();// 从数据库查的数据System.out.println(gameMapper.queryGameInfoById(1));
}

第二次查询就是从缓存中查的数据,只执行了 1 次sql语句,清空缓存,再次查询是从数据库查询的数据

[DEBUG] 2021-04-10 17:43:07,069 ==> Preparing: select * from game where id = ?
[DEBUG] 2021-04-10 17:43:07,137 ==> Parameters: 1(Integer)
[DEBUG] 2021-04-10 17:43:07,192 <== Total: 1
Game(id=1, name=lol, gameDesc=塔防)
Game(id=1, name=lol, gameDesc=塔防)
[DEBUG] 2021-04-10 17:43:07,199 ==> Preparing: select * from game where id = ?
[DEBUG] 2021-04-10 17:43:07,200 ==> Parameters: 1(Integer)
[DEBUG] 2021-04-10 17:43:07,202 <== Total: 1
Game(id=1, name=lol, gameDesc=塔防)

2.2.2、二级缓存

二级缓存区域是根据 mapper 的 namespace 划分的,相同 namespace 的mapper 查询的数据缓存在同一个区域,如果使用 mapper 代理方法每个mapper 的 namespace 都不同,此时可以理解为二级缓存区域是根据mapper 划分。

每次查询会先从缓存区域查找,如果找不到则从数据库查询,并将查询到数据写入缓存。Mybatis 内部存储缓存用一个 HashMap,key 为 hashCode+sqlId+Sql 语句。value 为从查询出来映射生成的 java 对象。 sqlSession 执行 insert、update、delete 等操作 commit 提交后会清空缓存区 域,防止脏读。

配置二级缓存配置

  1. 启用二级缓存

    • 在 SqlMapperConfig.xml 中启用二级缓存,如下代码所示,当 cacheEnabled 设置为 true 时启用二级缓存,设置为 false 时禁用二级缓存。 <setting name=“cacheEnabled” value=“true”/>
  2. POJO 序列化

    • 将所有的 POJO 类实现序列化接口 Java.io. Serializable。
  3. 配置映射文件

    • 在 Mapper 映射文件中添加<cache />,表示此 mapper 开启二 级缓存。

详情见 : 缓存cache

SSM—mybatis框架-注解开发-动态sql(where,set,trim,choose,when,foreach)-模糊查询写法-特殊符号处理-缓存相关推荐

  1. mybatis注解开发动态sql

    mybatis注解开发动态sql 本篇来讲一下如何使用mybatis注解模式中的动态sql 先来讲一下什么是动态sql 在我们实际开发的时候可能会出现很多方法需要一条很相似的sql语句来进行增删改查, ...

  2. Mybatis 注解开发 + 动态SQL

    Hello 大家好我是橙子同学,今天分享注解Mybatis注解开发+动态sql 目录 每文一铺垫(今天有小插曲哦) 注解开发 添加 @Insert 删除 @Delete 查询 @Select 修改 @ ...

  3. Mybatis中XML的文件SQL语句与动态sql标签(trim|where|set|foreach|if|choose|when|otherwise|bind)

    在xml中写sql语句有很多的规范.标准,有时候想要找对应的例子还得翻一翻以前的代码,这里干脆对遇到的情况做个记录. 一,新建XML文件 <?xml version="1.0" ...

  4. Mybatis框架(复杂动态SQL),一对一,一对多,多对多

    复合条件查询(动态SQL) MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦.例如拼接时要确保不能忘记 ...

  5. mybatis通过注解使用动态sql

    @Select({"<script>","sql语句"+"</script> "})回车会自动拼接 代码⬇️ @Se ...

  6. mybaitis动态sql利用bind标签代替%拼接完成模糊查询

    Oracle中使用bind的写法 <select id="selectUser" resultType="user" parameterType=&quo ...

  7. mybatis之注解开发与逆向工程

    注解开发 MyBatis 最初是一个 XML 驱动的框架.配置信息是基于 XML 的,而且映射语句也是定义在 XML 中的.随着技术的更新发展,对于开发效率要求也原来越高,特别是一些小型项目;越来越多 ...

  8. mybatis使用注解开发

    mybatis使用注解开发 面向接口编程 在之前我们是通过面向对象编程,但是在真正开发的时候我们会选择面向接口编程. 根本原因 : 解耦 , 可拓展 , 提高复用 , 分层开发中 , 上层不用管具体的 ...

  9. MyBatis:学习笔记(4)——动态SQL

    MyBatis:学习笔记(4)--动态SQL 转载于:https://www.cnblogs.com/MrSaver/p/7453949.html

最新文章

  1. mysql占用cpu_Mysql占用过高CPU时的优化手段(必看)
  2. linux命令之添加系统搜索动态库目录-ldconfig
  3. 数据挖掘:基于朴素贝叶斯分类算法的文本分类实践
  4. navicat使用触发器
  5. Maven学习(三)————Maven核心概念(二)
  6. 数字电路中的建立时间与保持时间
  7. 三星CEO承认:可折叠智能手机Galaxy Fold开卖得太着急
  8. 吴恩达神经网络和深度学习-学习笔记-44-交并比IoU + 非极大值抑制
  9. Mysql 数据库/表 备份 与 还原
  10. VOIP Codec 三剑客之 ISAC/ILBC -- ISAC (3) High Band Encode 模块
  11. 微信公众平台的开发流程及其要点
  12. z3求解器(SMT)解各类方程各种逻辑题非常简单直观
  13. 邮箱密码忘了怎么找回
  14. C++从txt文本中输入和读取字符串
  15. bilibili封面
  16. Linux常用命令(penguin)
  17. 关于单边账的解释及解决(收单行业)
  18. c语言字母杨辉三角,用C语言编写杨辉三角(示例代码)
  19. OneNote 2007简体中文官方单独安装版
  20. 华硕 您的计算机无法启动,华硕电脑无法开机怎么办

热门文章

  1. 全面详细的英语音标干货
  2. Aneka:从企业网格到面向市场的云计算
  3. python游戏代码怎么运行_bpython运行
  4. FSCapture - 长截图工具
  5. 《C语言参悟之旅》新鲜试读(连载4)
  6. 史上最全Java面试题(带全部答案,你可能要收藏!)
  7. 第三十章 光照及贴图总结
  8. string 实现字符串分割
  9. 港科大教授权龙:三维视觉重新定义人工智能安防
  10. oracle 动态行转成列,Oracle 行转列 动态出转换的列