文章目录
2.0、注解2.1、动态sql2.1.1、where2.1.2、set2.1.3、trim2.1.3.1、trim的where2.1.3.2、trim的set 2.1.4.1、choose2.1.5.1、foreach2.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 元素来定制where和set元素的功能。
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种方法
$符号拼接
name like '%${name}' or name like '${name}%' or name like '%${name}%'
concat拼接
name like concat('%',#{name}) or name like concat(#{name},'%') or name like concat('%',#{name},'%')
查询的时候写死
game.setName("%lol");name like #{name}
2.1.7、特殊符号处理
在 mybatis 中的 xml 文件中,存在一些特殊的符号,比如:<、>、"、&、<>
等,正常书写 mybatis 会报错,需要对这些符号进行转义。具体转义如下所示:
特殊字符 转义字符
< <
> >
" "
’ '
& &
除了可以使用上述转义字符外,还可以使用<![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>
@Testpublic 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] -04-10 17:43:07,069 ==> Preparing: select * from game where id = ?
[DEBUG] -04-10 17:43:07,137 ==> Parameters: 1(Integer)
[DEBUG] -04-10 17:43:07,192 <== Total: 1
Game(id=1, name=lol, gameDesc=塔防)
Game(id=1, name=lol, gameDesc=塔防)
[DEBUG] -04-10 17:43:07,199 ==> Preparing: select * from game where id = ?
[DEBUG] -04-10 17:43:07,200 ==> Parameters: 1(Integer)
[DEBUG] -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 提交后会清空缓存区 域,防止脏读。
配置二级缓存配置
启用二级缓存
在 SqlMapperConfig.xml 中启用二级缓存,如下代码所示,当 cacheEnabled 设置为 true 时启用二级缓存,设置为 false 时禁用二级缓存。 <setting name=“cacheEnabled” value=“true”/>
POJO 序列化
将所有的 POJO 类实现序列化接口 Java.io. Serializable。
配置映射文件
在 Mapper 映射文件中添加<cache />,表示此 mapper 开启二 级缓存。
详情见 : 缓存cache
SSM—mybatis框架-注解开发-动态sql(where set trim choose when foreach)-模糊查询写法-特殊符号处理-缓存
如果觉得《SSM—mybatis框架-注解开发-动态sql(where set trim choose when foreach)-模》对你有帮助,请点赞、收藏,并留下你的观点哦!