Mybatis强制查询问题

Mybatis强制查询缓存问题

1、对于经常用Mybatis框架的开发人员来说,都知道Mybatis进行数据库查询时的一个特性:

Mybatis连续执行两次相同的查询,Mybatis是不会去数据库中查询,而是直接从sqlsession中取,返回的对象也是同一个对象。简单来说就是不会再发出sql查询而是使用缓存的数据。这对于经常使用查询的系统无疑是一个非常好的特性,对于大量数据查询来说就是节约大量资源,降低开发成本。

但是我们有时候有特殊需要,那些数据一定要进行查询再能得到的,否则就会得到数据不一致的情况,这时候我们如何处理?

2、解决方案:

若是想要每次查询都返回新的对象,只需在xml文件select标签里添加属性 flushCache="true"。


3、MyBatis的缓存机制(分为一级缓存和二级缓存)

3.1一级缓存:

MyBatis的一级缓存指的是在一个Session域内,session为关闭的时候执行的查询会根据SQL为key,数据为value被缓存。

1)单独使用MyBatis而不继承Spring,使用原生的MyBatis的SqlSessionFactory来构造sqlSession查询,是可以使用以及缓存的,示例代码如下

public class Test {
    public static void main(String[] args) throws IOException {
        String config = "mybatis-config.xml";
        InputStream is = Resources.getResourceAsStream(config);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession session = factory.openSession();
        System.out.println(session.selectOne("selectUserByID", 1));
        // 同一个session的相同sql查询,将会使用一级缓存 
        System.out.println(session.selectOne("selectUserByID", 1));
        // 参数改变,需要重新查询
        System.out.println(session.selectOne("selectUserByID", 2));
        // 清空缓存后需要重新查询
        session.clearCache();
        System.out.println(session.selectOne("selectUserByID", 1));
        // session close以后,仍然使用同一个db connection
        session.close();
        session = factory.openSession();
        System.out.println(session.selectOne("selectUserByID", 1));
    }
}
当参数不变的时候只进行了一次查询,参数变更以后,则需要重新进行查询,而清空缓存以后,参数相同的查询过的SQL也需要重新查询。
2) 和Spring集成的时候

@Repository
public class UserDao extends SqlSessionDaoSupport {
    public User selectUserById(int id) {
        SqlSession session = getSqlSession();
        session.selectOne("dao.userdao.selectUserByID", id);
        // 由于session的实现是SqlSessionTemplate的动态代理实现
        // 它已经在代理类内执行了session.close(),所以无需手动关闭session
        return session.selectOne("dao.userdao.selectUserByID", id);
    }
}
这里执行了2次sql查询,看似我们使用了同一个sqlSession,但是实际上因为我们的dao继承了SqlSessionDaoSupport,而SqlSessionDaoSupport内部sqlSession的实现是使用用动态代理实现的,这个动态代理sqlSessionProxy使用一个模板方法封装了select()等操作,每一次select()查询都会自动先执行openSession(),执行完close()以后调用close()方法,相当于生成了一个新的session实例,所以 我们无需手动的去关闭这个session(),当然也无法使用mybatis的一级缓存,也就是说mybatis的一级缓存在spring中是没有作用的。


3.2二级缓存

二级缓存就是global caching,它超出session范围之外,可以被所有sqlSession共享,它的实现机制和mysql的缓存一样,开启它只需要在mybatis的配置文件开启settings里的。

<setting name="cacheEnabled" value="true"/>
以及在相应的Mapper文件里开启。

<mapper namespace="dao.userdao">
   ...  select statement ...
       <!-- Cache 配置 -->
    <cache
        eviction="FIFO"
        flushInterval="60000"
        size="512"
        readOnly="true" />
</mapper>
需要注意的是global caching的作用域是针对Mapper的Namespace而言的,也就是说只在有在这个Namespace内的查询才能共享这个cache。


每天努力一点,每天都在进步。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Mybatis是一款优秀的Java持久层框架,它可以让开发者轻松地与数据库交互。在实际的开发过程中,我们有时需要强制Mybatis走索引来提高查询效率,减少不必要的全表扫描。要想让Mybatis强制走索引,我们需要做以下几个步骤: 首先,我们需要在Mapper.xml文件中编写查询语句,并在该语句中使用强制索引的语法。例如,我们有一张名为user的表,该表有一个名为name的索引,我们可以编写以下语句: <select id="getUserByName" resultType="User"> select * from user use index(name) where name=#{name} </select> 在这个语句中,我们使用了use index(name)语法来强制Mybatis走name索引进行查询。 其次,我们需要在Mybatis配置文件中启用参数useCache。该参数默认为true,如果不手动修改,Mybatis会默认使用缓存,而缓存会屏蔽强制走索引的语法。我们需要将useCache的值改为false,例如: <configuration> ... <settings> <setting name="useCache" value="false"/> </settings> ... </configuration> 最后,我们需要注意可能存在的优化器改写。当MySQL优化器认为一个语句的全表扫描更快时,Mybatis强制走索引的语法就会失效。我们可以使用FORCE INDEX语法或者将MySQL优化器的cost参数调小来规避这个问题。 总之,Mybatis强制走索引需要在Mapper.xml中使用use index语法、在Mybatis配置文件中关闭缓存、在查询语句中注意可能存在的优化器改写。在遵循这些步骤的前提下,Mybatis强制走索引可以有效地提高查询效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

powerfuler

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

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值