Mybatis 动态sql的编写|开启二级缓存

❤️作者主页:微凉秋意
✅作者简介:后端领域优质创作者🏆,CSDN内容合伙人🏆,阿里云专家博主🏆
✨精品专栏:数据结构与课程设计
🔥系列专栏:javaweb

前言

上篇博文把表连接查询和三种对应关系的写法记录总结了,本篇要把 mybatis 中的动态sql 的使用以及缓存知识记录下来。

动态SQL

在解释 where if 标签之前先进行一个模糊查询的操作。

模糊查询

如下面一张表:

在这里插入图片描述
查询所有 姓人员的信息:

mapper接口中定义方法:

List<Person> selectName(String name);

xml 中编写 sql 语句:

<select id="selectName" resultMap="personMap">
        select *
        from t_person
        where person_name like concat('%', #{name}, '%');
    </select>

这里的 concat('%', #{name}, '%') 写法使用了字符串拼接的技巧,这样在查询语句里就是 %name% 的模糊查询了。
如果这样写:'%#{name}%' 是不行的,#{}会失效。

编写测试类:

在这里插入图片描述
测试结果:
在这里插入图片描述
可以看到所有 姓的人信息被查询到了。

where if 标签

姓李的太多,那么我们可以加一个年龄范围,于是需要增加两个参数:

在这里插入图片描述

这里要注意,参数在两个以上需要使用 注解 来绑定。

重点来看 xml中的 sql 语句

<select id="selectContent" resultMap="personMap">
        select * from t_person
        <where>
            <if test="name != null and name !=''">
                person_name like concat('%',#{name},'%')
            </if>
            <if test="ageMin > 0">
                and age &gt;= #{ageMin}
            </if>
            <if test="ageMax > ageMin">
                and age &lt;= #{ageMax}
            </if>
        </where>

    </select>
  • 可以看到这里的 where 关键字变成了一个标签 <where>,这是因为:
    • 如果这三个参数都不填写的话,where 下的条件就不会起作用,
      此条 sql 就变成了查询所有。
    • 显然,查询所有的语法里是没有 where 关键字的,因此使用标签代替。
    • 除了使用 <where> 标签之外,也可以使用类似 1=1and 的方法拼接。
      • 比如: select * from t_person where 1=1 and ...
  • 此外,where 标签还可以去除多余的 and 前缀。
  • if 标签用来做判断,test 里写判断的条件,标签内写判断成功后的 sql 语句:
    • 这里就是判断名字是否为空以及年龄的取值范围是否合理:
      • test 里面的符号正常写,andor 代表并且和或者。
      • sql 语句里,&gt; 是大于的意思,&lt; 是小于的意思。

编写测试类:

在这里插入图片描述

测试结果:
在这里插入图片描述
很明显,年龄在 20~28 且姓李的只有 “李白” 自己。

update set 标签

以往的修改操作都是将对象的所有属性都修改或者重写一遍,这样是不合逻辑的,因此可以在修改的 sql 语句里使用 if 标签来优化。

mapper 接口中写方法:

void update(Person person);

xml 中编写 sql:

	<update id="update">
        update t_person
        <set>
            <if test="personName !=null and personName !=''">
                person_name = #{personName},
            </if>
            <if test="age !=null">
                age         = #{age},
            </if>
            <if test="birthday != null and birthday!= ''">
                birthday    = #{birthday},
            </if>
            <if test=" sex !=null and sex !=''">
                sex = #{sex},
            </if>
            <if test="mobile != null and mobile !=''">
                mobile = #{mobile},
            </if>
            <if test="address !=null and address!=''">
                address = #{address}
            </if>
        </set>
        where person_id = #{personId}
    </update>
  • if 标签想必好理解,但是set 标签是做什么的呢?原因是:
    • 假如只修改名字,那么 sql 语句将变为:
      update t_person set person_name = ?, where ...
      
    • 可以发现?占位符后面会有多余的逗号导致 sql 语法错误
    • <set> 标签会自动去除多余的逗号后缀。

值得注意的是:set 标签去除,后缀,where 标签去除and前缀。

foreach 标签

相信大家都知道foreach 跟循环有关系,没错,我们可以利用此标签来完成 批量删除 操作。

从 sql 的语句来看,批量删除应该这样写:

delete from t_person where person_id in (?,?,?,...)

那么 in 后的形式该怎么用 mybatis 表达出来呢,有括号,不定数量的逗号…

不急,一步步来,先写 mapper接口:

void deleteMany(@Param("myIds") int[] ids);

再编写 sql 语句:

	<delete id="deleteMany">
        delete from t_person where person_id in
        <foreach collection="myIds" open="(" close=")" separator="," item="id">
            #{id}
        </foreach>
    </delete>

利用 foreach 就可以将参数集合中的值依次放入到 in 后的括号内:(id,id,id...)

foreach 标签相关解释:

  • collection:被循环的数组或者集合,注意如果是参数必须使用@Param 起名
  • open : 循环以什么开始
  • close :循环以什么结束
  • separator: 循环以什么分割
  • item : 每次循环的元素

编写测试类(不要忘记手动提交事务):

在这里插入图片描述

测试结果:

在这里插入图片描述
可以看到数组里的元素依次放入了括号内,并成功做到了批量删除。

useGeneratedKeys 获取插入数据的主键值

一般我们习惯将表中的主键设为自增长,那么在使用 insert 插入数据时,主键是不用赋值的,而是用 null 代替。那怎么才能在插入后直接得到该数据的主键值呢?那就使用 useGeneratedKeys

来看具体的使用:

<insert id="insert" useGeneratedKeys="true" keyProperty="personId" keyColumn="person_id">
    insert into t_person
    values (null, #{personName}, #{age}, #{sex}, #{birthday}, #{mobile}, #{address})
</insert>

将值设为 true 后,keyPropetry 的值填写属性名,keyColumn 的值填写表的字段名。

编写测试类:

	@Test
    public void insert(){
    	SqlSession sqlSession = MybatisUtil.getSqlSession();
    	PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
        Person person = new Person(null,"微凉",21,"1",new Date(),"1359356123","爱琴海");
        mapper.insert(person);
        sqlSession.commit();
        MybatisUtil.closeSqlSession(sqlSession);
        System.out.println(person);
    }

测试结果:

在这里插入图片描述
可以看到插入数据后的主键值为 240,这便是自动获取的结果。

Mybatis 缓存

有关 IO 操作一般都会很耗时,在一个 javaweb 项目中,页面到 tomcat 与 tomcat 到数据库都属于IO操作。因此 mybatis 在 tomcat 中创建了一块叫做缓存的空间,在缓存中保存比如查询操作的数据,以后进行重复操作时,就不必到数据库中获取了,而是直接在 tomcat 内部获取。

如果对数据库进行修改,缓存中的数据跟数据库中的对应不上,那么此时缓存中的就变成了脏数据

一级缓存

特点:

  • 默认开启
  • 作用在同一个 SqlSession
  • 脏数据的处理: 一旦执行增删改,立刻清空缓存

但是一级缓存并没有什么意义,因为作用范围的缘故,它只能在一个 SqlSession ,也就是一个事务内,一旦提交事务,缓存就会被清空,没有实战意义。

二级缓存

二级缓存的作用范围大,符合实战的需求,该如何开启:

  1. 实体类需要实现可序列化接口:implements Serializable
  2. mybatis-config.xml 文件中添加<settings> 标签:
    <!--开启二级缓存 settings 写在 properties 和 typeAliases 之间-->
    <settings>
       <setting name="cacheEnabled" value="true"/>
    </settings>
    
  3. 在对应 mapperxml 文件中添加 <cache> 标签:
    <cache size="1024" eviction="LRU" flushInterval="60000"/>
    
    • size:定义二级缓存空间大小 (单位是 M)
    • eviction:定义缓存到达上限时的淘汰策略,常使用LRU算法:
      • 叫做最近最久未使用算法,即清空最近使用次数最少的缓存
    • flushInterval:定义清空缓存的间隔时间 (单位 ms)

作用范围:

  • 同一个sqlSessionFactory内,而且必须提交事务。

脏数据的处理:

  1. 一旦执行增删改,默认清空同一个 namespace 下的二级缓存。
  2. 自定义清空缓存的策略:
    • flushCache属性,值为 true 时执行清空缓存,为 false 则不清空。
    • insertdeleteupdate 标签里默认为 true
    • select 标签里默认为 false

脏数据并不都是一定要清空,因此在增删改查标签内可以自由的设定缓存清空的策略。


mybatis 框架的记录到此结束,一共三篇,感兴趣的小伙伴可以订阅此专栏。

  • 81
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 70
    评论
目录 1 Mybatis入门 1 1.1 单独使用jdbc编程问题总结 1 1.1.1 jdbc程序 1 1.1.2 jdbc编程步骤: 2 1.1.3 jdbc问题总结如下: 3 1.2 MyBatis介绍 3 1.3 Mybatis架构 3 1.4 mybatis下载 4 1.5 创建mysql数据库 5 1.6 Mybatis入门程序 5 1.6.1 需求 5 1.6.2 第一步:创建java工程 6 1.6.3 第二步:加入jar包 6 1.6.4 第三步:log4j.properties 6 1.6.5 第四步:SqlMapConfig.xml 6 1.6.6 第五步:po类 7 1.6.7 第六步:程序编写 8 1.6.8 Mybatis解决jdbc编程的问题 15 1.6.9 与hibernate不同 16 2 Dao开发方法 16 2.1 需求 16 2.2 SqlSession的使用范围 17 2.2.1 SqlSessionFactoryBuilder 17 2.2.2 SqlSessionFactory 17 2.2.3 SqlSession 17 2.3 原始Dao开发方式 18 2.3.1 映射文件 18 2.3.2 Dao接口 19 2.3.3 问题 20 2.4 Mapper动态代理方式 20 2.4.1 实现原理 20 2.4.2 Mapper.xml(映射文件) 20 2.4.3 Mapper.java(接口文件) 21 2.4.4 加载UserMapper.xml文件 22 2.4.5 测试 22 2.4.6 总结 23 3 SqlMapConfig.xml配置文件 24 3.1 配置内容 24 3.2 properties(属性) 24 3.3 settings(配置) 25 3.4 typeAliases(类型别名) 26 3.4.1 mybatis支持别名: 26 3.4.2 自定义别名: 27 3.5 typeHandlers(类型处理器) 27 3.6 mappers(映射器) 28 3.6.1 <mapper resource=" " /> 28 3.6.2 <mapper url=" " /> 28 3.6.3 <mapper class=" " /> 29 3.6.4 <package name=""/> 29 4 Mapper.xml映射文件 29 4.1 parameterType(输入类型) 29 4.1.1 #{}与${} 29 4.1.2 传递简单类型 30 4.1.3 传递pojo对象 30 4.1.4 传递pojo包装对象 31 4.1.5 传递hashmap 32 4.2 resultType(输出类型) 33 4.2.1 输出简单类型 33 4.2.2 输出pojo对象 34 4.2.3 输出pojo列表 34 4.2.4 resultType总结: 35 4.2.5 输出hashmap 35 4.3 resultMap 36 4.3.1 Mapper.xml定义 36 4.3.2 定义resultMap 36 4.3.3 Mapper接口定义 37 4.4 动态sql(重点) 37 4.4.1 If 37 4.4.2 Where 38 4.4.3 foreach 38 4.4.4 Sql片段 43 5 关联查询 44 5.1 商品订单数据模型 45 5.2 一对一查询 45 5.2.1 方法一: 46 5.2.2 方法二: 48 5.3 一对多查询 50 5.3.1 Sql语句: 50 5.3.2 定义po类 50 5.3.3 Mapper.xml 51 5.3.4 定义resultMap 51 5.3.5 Mapper接口: 52 5.3.6 测试: 52 5.3.7 小结 53 5.4 多对多查询 53 5.4.1 查询用户购买的商品信息 53 5.4.2 小结 55 5.5 resultMap小结 55 5.6 延迟加载 56 5.6.1 打开延迟加载开关 56 5.6.2 一对一查询延迟加载 56 5.6.3 一对多延迟加载 59 5.6.4 延迟加载小结 59 6 查询缓存 59 6.1 mybatis缓存介绍 59 6.2 一级缓存 60 6.2.1 原理 60 6.2.2 测试1 61 6.2.3 测试2 61 6.3 二级缓存 62 6.3.1 原理 62 6.3.2 开启二级缓存: 62 6.3.3 实现序列化 63 6.3.4 测试 63 6.3.5 禁用二级缓存 63 6.3.6 刷新缓存 64 6.3.7 Mybatis Cache参数 64 6.3.8 mybatis整合ehcache 64 6.3.9 应用场景 67 6.3.10 局限性 67 7 与spring整合 68 7.1 mybatis与spring整合jar 68 7.2 Mybatis配置文件 68 7.3 Spring配置文件: 69 7.4 Mapper编写的三种方法 70 7.4.1 Dao接口实现类继承SqlSessionDaoSupport 70 7.4.2 使用org.mybatis.spring.mapper.MapperFactoryBean 71 7.4.3 使用mapper扫描器 71 8 Mybatis逆向工程 72 8.1 第一步:mapper生成配置文件: 72 8.2 第二步:使用java类生成mapper文件: 72 8.3 第三步:拷贝生成的mapper文件到工程中指定的目录中 73 8.3.1 Mapper.xml 73 8.3.2 Mapper.java 73 8.3.3 第四步Mapper接口测试 73 8.4 逆向工程注意事项 74 8.4.1 Mapper文件内容不覆盖而是追加 74 8.4.2 Table schema问题 74

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 70
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

微凉秋意

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值