Mybatis一级缓存和结合Spring Framework后失效的源码探究

下面是“Mybatis一级缓存和结合Spring Framework后失效的源码探究”的攻略:

Mybatis一级缓存

Mybatis自身提供了一级缓存的支持,即在同一次会话中多次查询同一条记录时,第一次查询时会将该数据缓存下来,后续再次查询时直接从缓存中取出,避免了重复的数据库查询操作,提升了性能。

对于一级缓存的使用,需要注意以下几点:

  1. 一级缓存的作用域是SqlSession,在同一个SqlSession中查询到的数据可以直接从缓存中获取。

  2. 默认情况下SqlSession开启一级缓存,即开启自动提交(autoCommit=false)情况下,每次执行查询语句后,查询结果都会被缓存起来。

  3. 如果缓存的数据被修改或删除,那么缓存数据会被清空。

Mybatis一级缓存与Spring Framework结合后失效的原因及解决方法

结合Spring Framework后,每个Mapper接口都会被Spring所代理,即每次调用Mapper接口时会生成一个新的代理类,因此Mapper接口的代理类是不同的,即使两个Mapper接口里的方法名和参数都一样。

这样导致了两个问题:

  1. 每个Mapper接口的代理类都有自己的SqlSession实例,不属于同一个SqlSession,因此会有多个缓存实例。

  2. 不同的Mapper接口的代理类中可能涉及同一个数据库表的数据,但这两个代理类实际上是不同的,因此可能出现一级缓存污染的现象。

解决以上问题,有3种方案:

  1. 方案一:使用Spring的事务管理机制,每次操作,保证只使用一个SqlSession。在Spring的配置文件中开启事务,使用@Transactional注解对需要使用SqlSession的方法进行标注。

  2. 方案二:使用Mybatis-Spring,Mybatis-Spring是Mybatis官方提供的与Spring集成的插件包,其中包含了SqlSessionTemplate,它提供统一的SqlSession操作入口,保证在同一事务中所有的操作只使用同一SqlSession实例。

  3. 方案三:关闭一级缓存。如果不想开启一级缓存,可以在配置文件中将localCacheScope设置为SESSION,即关闭一级缓存。

示例1

接下来的示例展示了如何基于Spring Framework和Mybatis-Spring来实现上述第二种方案中的解决方法。

  1. 首先,在applicationContext.xml中引入Mybatis-Spring。
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
  1. 在Spring的配置文件中加入事务管理器的配置,使用tx:annotation-driven开启Spring事务注解支持。将SqlSessionFactory注入到事务管理器中。
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    ...
</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>
  1. 在Mapper接口中使用SqlSessionTemplate操作数据库。
@Repository
public class UserMapper {
    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;

    public User findUserById(int id) {
        return sqlSessionTemplate.selectOne("com.example.UserMapper.findUserById", id);
    }
}
  1. 在Service实现类中使用@Transactional注解实现事务的控制。
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public User findUserById(int id) {
        return userMapper.findUserById(id);
    }
}

示例2

下面的示例演示了开启自动提交的情况下,Mybatis一级缓存如何生效。

  1. 在SqlSessionFactory中开启自动提交(autoCommit=true)功能,设置缓存类型(cacheEnabled=true)。
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="typeAliasesPackage" value="com.example.po"/>
    <property name="mapperLocations" value="classpath*:com/example/mapper/*.xml"/>
    <property name="configuration">
        <bean class="org.apache.ibatis.session.Configuration">
            <property name="cacheEnabled" value="true"/>
        </bean>
    </property>
    <property name="plugins">
        <array>
            <bean class="com.github.pagehelper.PageInterceptor">
                <property name="properties">
                    <value>
                        helperDialect=mysql
                    </value>
                </property>
            </bean>
        </array>
    </property>
    <property name="autoCommit" value="true"/>
</bean>
  1. 在Mapper接口中使用@Select注解进行查询操作。
public interface UserMapper {
    @Select("SELECT * FROM tb_user WHERE id = #{id}")
    User findUserById(int id);
}
  1. 在Service中进行测试。
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public User findUserById(int id) {
        User user = userMapper.findUserById(id);
        User user2 = userMapper.findUserById(id);
        return user;
    }
}

在这个示例中,第一次查询后,查询结果被缓存在了一级缓存中,第二次查询时直接从缓存中取出,而不是再次查询数据库。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Mybatis一级缓存和结合Spring Framework后失效的源码探究 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 详解Java的Spring框架中的事务管理方式

    详解Java的Spring框架中的事务管理方式 什么是事务管理 事务管理是指对于需要具有原子性和一致性的业务流程操作,保证其执行结果要么全部成功执行完成,要么全部回滚到最初状态,异常情况下,业务操作要么完全执行成功,要么完全执行失败。 Spring框架中的事务管理 在Spring框架中,主要有三种方式进行事务管理:编程式事务、声明式事务、注解式事务。 编程式…

    Java 2023年5月19日
    00
  • JSP 开发之servlet中调用注入spring管理的dao

    下面是关于 JSP 开发中在 Servlet 中调用注入 Spring 管理的 DAO 的完整攻略: 1. Maven 依赖 首先,在 pom.xml 文件中添加以下依赖: <!– Spring Framework –> <dependency> <groupId>org.springframework</gro…

    Java 2023年6月16日
    00
  • hibernate-validator改进校验框架validator v0.4使用

    来讲一下“hibernate-validator改进校验框架validator v0.4使用”的完整攻略。 什么是Hibernate-Validator? Hibernate-Validator 是一款校验框架。这个框架的初衷是为了在 JavaBean 层面上提供一套统一、可重用的验证机制,使得我们在对 JavaBean 进行数据验证时能够更加方便、快捷、灵…

    Java 2023年5月20日
    00
  • Spark JDBC操作MySQL方式详细讲解

    Spark JDBC操作MySQL方式详细讲解 简介 Spark可以使用JDBC访问关系型数据库,包括MySQL,Oracle,PostgreSQL等等。Spark的JDBC操作支持读写功能,本篇文章将为大家详细讲解如何使用Spark JDBC操作MySQL数据库。 步骤 1. 导入MySQL JDBC驱动 在使用Spark JDBC操作MySQL之前,需要…

    Java 2023年6月2日
    00
  • Java如何实现读取txt文件内容并生成Word文档

    要实现Java读取txt文件内容并生成Word文档,你需要以下步骤: 步骤一:读取txt文件内容 创建一个File对象,用于表示要读取的txt文件; 创建一个BufferedReader对象,用于读取文件内容; 使用BufferedReader的readLine()方法逐行读取文件内容,把每一行的文本保存到一个字符串变量中。 以下是示例代码: File fi…

    Java 2023年5月19日
    00
  • 一文详解Tomcat下载安装以及配置

    一文详解Tomcat下载安装以及配置 Apache Tomcat(简称Tomcat)是一个流行的开源Web服务器和Java Servlet容器,可运行于各种操作系统上。本文将提供完整的Tomcat下载、安装和配置教程。 步骤一:下载Tomcat 首先,访问官方网站,进入Tomcat下载页面。选择最新版本的Tomcat,然后在下载页面中选择“Core”板块中的…

    Java 2023年6月2日
    00
  • 剖析Java中的事件处理与异常处理机制

    剖析Java中的事件处理与异常处理机制 事件处理机制 Java中的事件处理机制是一种将某些动作(例如按钮点击、鼠标移动等)与一些代码相结合的机制。具体来说,Java使用了一种称为“观察者设计模式”的方法来实现事件处理。在这种模式中,一个对象(称为“主题”)维护了一组观察者,这些观察者都希望跟踪主题的状态。当主题状态发生变化时,它将会通知所有的观察者,使得它们…

    Java 2023年5月27日
    00
  • 微信小程序如何连接Java后台

    要将微信小程序连接到Java后台,需要进行以下步骤: 创建Java后台API 首先,需要在Java后台创建RESTful API来与小程序通信。 选取一种Java框架来创建API,如Spring Boot或Spring MVC。 在API中编写业务逻辑,其中包括数据库连接、业务计算、数据加工等。 将API暴露在公网上,可使用云服务器等服务。 测试API是否可…

    Java 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部