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;
    }
}

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

阅读剩余 67%

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

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

相关文章

  • Java中synchronized正确使用方法解析

    Java中synchronized正确使用方法解析 什么是synchronized synchronized是一个对象级别的锁,也称之为内部锁或者特定对象的锁。Java中提供了三种使用synchronized关键字同步代码块的方法。 修饰实例方法,锁的是当前实例对象(this)。 修饰静态方法,锁的是类对象(Class对象)。 修饰代码块,锁的是代码块中的对…

    Java 2023年5月26日
    00
  • 深入理解Java中包的定义与使用

    我来为您详细讲解“深入理解Java中包的定义与使用”的完整攻略。 什么是Java包? Java包是一种将类组织在一起的机制。它们用于避免命名冲突,使类更加可维护,并提供了更好的封装和安全性。Java包是Java的基本组成部分之一,几乎所有的Java程序都使用了它们。 Java包的定义 Java包的定义非常简单 —— 它是一个具有唯一名称的目录,其中包含Jav…

    Java 2023年5月26日
    00
  • 精通Java接口的使用与原理

    精通Java接口的使用与原理 什么是接口 Java接口是一个抽象编程结构,定义了类或对象应该实现的一组方法及其签名。接口在Java中为多态性提供了一种体系结构和模板。它仅仅定义了方法的名称、参数和返回类型,而没有方法的实现。接口可以看做是一种“契约”,规定了实现接口的类或者对象需要满足的“协议”。 接口可以在Java中起到以下几个作用: 接口帮助我们定义一套…

    Java 2023年5月26日
    00
  • Java Swing组件文件选择器JFileChooser简单用法示例

    下面我就详细为您讲解“Java Swing组件文件选择器JFileChooser简单用法示例”的完整攻略。 什么是JFileChooser? JFileChooser是Java Swing组件库中的一个组件,它提供了一个通用的、可自定义的对话框,用于允许用户选择文件或目录。用户可以通过对话框打开或者保存文件或目录,并进行其他一些相关操作。 如何使用JFile…

    Java 2023年5月20日
    00
  • Maven入门之使用Nexus搭建Maven私服及上传下载jar包

    这里是“Maven入门之使用Nexus搭建Maven私服及上传下载jar包”的完整攻略。 准备工作 安装JDK和Maven 下载和安装Nexus 启动Nexus 配置Maven仓库 Nexus默认内置了一个Maven2仓库。如果需要创建自己的仓库,可以按如下步骤操作: 点击页面左侧的“Repositories”选项卡 在页面上方点击“Create Repos…

    Java 2023年5月20日
    00
  • springboot jpa 实现返回结果自定义查询

    下面是详细讲解“springboot jpa 实现返回结果自定义查询”的完整攻略。 1. 什么是 Spring Boot JPA? Spring Boot是Spring项目中的一种用于简化配置和开发的框架。同时,它也是一个类似于Spring Data JPA的持久化框架。Spring Data JPA则是一个封装了JPA的框架,提供了许多便捷的API,使我们…

    Java 2023年5月20日
    00
  • Java+MySQL 图书管理系统

    那我将详细讲解一下“Java+MySQL 图书管理系统”的完整攻略。 1、前期准备 在开发过程中,需要确认以下前期准备: MySQL 数据库的安装并创建数据表 Eclipse 或者其他 Java IDE 的安装设置 在 MySQL 中创建以下表: book表 字段名 类型 描述 book_id int 书籍编号 book_name varchar(50) 书…

    Java 2023年5月19日
    00
  • 基于javaweb+jsp实现个人日记管理系统

    让我来详细解析一下“基于javaweb+jsp实现个人日记管理系统”的攻略吧。首先,我们需要了解这个系统的基本要素:JavaWeb以及JSP。 一、JavaWeb JavaWeb是指基于Java语言所开发的Web应用程序,在软件开发工程中,开发人员可以使用JavaWeb技术,实现分布式系统的实现。JavaWeb技术是建立在Java平台之上的,包含许多组件,例…

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