为了账号安全,请及时绑定邮箱和手机立即绑定

Mybatis二级缓存入门:简单教程详解

标签:
Java SSM 数据库
概述

介绍Mybatis一级和二级缓存的基本概念,解释缓存的作用和优势,包括减少数据库访问、提高响应速度和减轻数据库负载。文章详细说明如何配置和使用二级缓存,包括启用方式和使用场景。

Mybatis缓存简介

Mybatis一级缓存与二级缓存的概念

Mybatis缓存分为一级缓存和二级缓存。一级缓存是SqlSession级别的缓存,每个SqlSession都有自己的缓存,当SqlSession执行查询时,会优先检查此缓存,如果存在结果,则直接返回缓存中的数据。一级缓存默认开启,无需额外配置。

二级缓存是Mapper级别的缓存,可以在同一个Mapper中共享。二级缓存可以跨越多个SqlSession,这意味着在一个SqlSession中查询的数据,可以被另一个SqlSession使用,前提是这两个SqlSession共享同一个Mapper。但是,二级缓存默认是关闭的,需要手动开启。

缓存的作用和优势

缓存的主要作用是减少数据库访问次数,提高系统的响应速度和性能。在查询操作频繁且数据不频繁变化的场景下,启用缓存可以显著提升应用性能。

  1. 减少数据库访问:缓存可以避免每次查询都访问数据库,尤其是在数据不频繁变化的情况下。
  2. 提高响应速度:缓存减少了数据库的网络延迟,提高了系统的响应速度。
  3. 减轻数据库负载:缓存可以降低数据库的查询压力,减少数据库的负担。
二级缓存的基本配置

二级缓存的启用方式

要启用二级缓存,需要满足以下条件:

  1. 在 Mybatis 的配置文件(如 mybatis-config.xmlapplication.properties)中,通过以下配置开启二级缓存:
<setting name="cacheEnabled" value="true"/>

或在 Spring Boot 的 application.properties 中:

mybatis.configuration.cache-enabled=true
  1. 在 Mapper 的 XML 文件中,为对应的 Mapper 启用缓存配置:
<mapper namespace="com.example.mapper.UserMapper">
    <cache/>
</mapper>

缓存配置文件的编写

以下是启用缓存的完整配置示例:

  1. mybatis-config.xml 中配置全局缓存启用:
<configuration>
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>
  1. UserMapper.xml 中启用二级缓存:
<mapper namespace="com.example.mapper.UserMapper">
    <cache
        eviction="LRU"
        flushInterval="60000"
        size="512"
        readOnly="true"/>
    <select id="findUserById" resultType="com.example.entity.User">
        SELECT * FROM user WHERE id = #{id}
    </select>
    <select id="findAllUsers" resultType="com.example.entity.User">
        SELECT * FROM user
    </select>
</mapper>
  1. 配置 application.properties 启用缓存:
mybatis.configuration.cache-enabled=true
二级缓存的使用场景

何时开启二级缓存

以下是一些适合开启二级缓存的场景:

  1. 高并发读操作:如果一个数据库表的读操作非常频繁,可以考虑启用二级缓存以减少直接访问数据库的次数。
  2. 低频更新:当数据更新频率较低时,启用二级缓存可以有效地减少数据库压力。
  3. 查询结果不经常变化:如果查询返回的数据内容在较长时间内不会发生变化,启用二级缓存可以提高性能。

常见的使用场景分析

例如,在电子商务网站中,某些商品信息(如商品名称、价格、库存等)在一段时间内可能不会频繁更改。这类数据可以启用二级缓存来提高查询速度。

代码示例

package com.example.service;

import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public User findUserById(int id) {
        return userMapper.findUserById(id);
    }

    public List<User> findAllUsers() {
        return userMapper.findAllUsers();
    }
}

二级缓存的实现机制

缓存数据的存储方式

Mybatis的二级缓存默认使用LRU(Least Recently Used)缓存策略。LRU策略会根据时间来淘汰最近最少使用的数据,以此保证缓存中存储的是较新且常用的查询结果。

Mybatis支持多种缓存实现,包括内置的LRU缓存和自定义的缓存实现。自定义缓存实现需要实现 org.apache.ibatis.cache.Cache 接口。

缓存的数据更新策略

当缓存中的数据发生变化时,Mybatis会根据配置的缓存刷新策略来更新缓存。常见的缓存刷新策略包括:

  1. Scope.ALL:当数据库中的数据发生变化时,会自动刷新缓存。
  2. Scope.STATEMENT:当特定语句执行时,刷新缓存。
  3. Scope.SESSION:在会话结束时刷新缓存。

缓存刷新示例

UserMapper.xml 中可以配置刷新策略:

<mapper namespace="com.example.mapper.UserMapper">
    <cache
        eviction="LRU"
        flushInterval="60000"
        size="512"
        readOnly="true"/>
    <select id="findUserById" resultType="com.example.entity.User">
        SELECT * FROM user WHERE id = #{id}
    </select>
    <select id="findAllUsers" resultType="com.example.entity.User">
        SELECT * FROM user
    </select>
</mapper>
  • eviction:指定缓存淘汰策略,例如 LRU
  • flushInterval:指定刷新缓存的间隔时间(单位:毫秒)。
  • size:指定缓存的最大条目数。
  • readOnly:设置缓存是否为只读模式。

二级缓存的注意事项

常见问题及解决方法

  1. 数据一致性问题:如果数据频繁变化,可能会导致缓存中的数据与数据库中的数据不一致。可以通过设置缓存刷新策略来缓解此问题。
  2. 缓存命中率低:如果缓存的命中率低,说明缓存设置可能不合理。可以调整缓存大小或刷新策略来优化缓存性能。
  3. 缓存击穿:当缓存中某个热点数据失效时,会导致大量的请求直接访问数据库,造成数据库压力过大。可以通过设置适当的缓存过期时间来缓解此问题。

性能优化建议

  1. 合理设置缓存大小和刷新策略:根据实际场景合理设置缓存大小和刷新策略,以提高缓存的命中率。
  2. 使用并发工具:使用并发工具(如 ConcurrentHashMap)来提高缓存的读写性能。
  3. 缓存预热:在应用启动时预先加载一些常用的数据到缓存中,减少初始加载时间。

缓存刷新示例

UserService.java 中可以手动刷新缓存:

package com.example.service;

import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.apache.ibatis.cache.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public User findUserById(int id) {
        return userMapper.findUserById(id);
    }

    public List<User> findAllUsers() {
        return userMapper.findAllUsers();
    }

    public void refreshUserCache() {
        Cache cache = userMapper.getCache();
        cache.clear();
    }
}

通过调用 cache.clear() 方法可以清除缓存中的所有数据,强制重新从数据库中加载数据。

实战演练

二级缓存的代码示例

以下是一个完整的示例,展示了如何在 Mybatis 中启用二级缓存,并通过代码示例来展示二级缓存的使用。

项目结构

src
└── main
    ├── java
    │   └── com
    │       └── example
    │           ├── mapper
    │           │   └── UserMapper.java
    │           ├── service
    │           │   └── UserService.java
    │           └── entity
    │               └── User.java
    ├── resources
    │   ├── mybatis-config.xml
    │   └── mapper
    │       └── UserMapper.xml

UserMapper.java

package com.example.mapper;

import com.example.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface UserMapper {

    @Select("SELECT * FROM user WHERE id = #{id}")
    User findUserById(int id);

    @Select("SELECT * FROM user")
    List<User> findAllUsers();
}

User.java

package com.example.entity;

public class User {
    private int id;
    private String name;
    private String email;
    private int age;

    // Getters and Setters
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
    <cache
        eviction="LRU"
        flushInterval="60000"
        size="512"
        readOnly="true"/>
    <select id="findUserById" resultType="com.example.entity.User">
        SELECT * FROM user WHERE id = #{id}
    </select>
    <select id="findAllUsers" resultType="com.example.entity.User">
        SELECT * FROM user
    </select>
</mapper>

UserService.java

package com.example.service;

import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public User findUserById(int id) {
        return userMapper.findUserById(id);
    }

    public List<User> findAllUsers() {
        return userMapper.findAllUsers();
    }

    public void refreshUserCache() {
        Cache cache = userMapper.getCache();
        cache.clear();
    }
}

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

application.properties

mybatis.configuration.cache-enabled=true

实际项目中的应用案例

假设有一个电子商务网站,需要频繁查询用户的信息(如用户名、邮箱、年龄等)。由于这些信息在一段较长时间内不会频繁变动,因此可以启用二级缓存来提高查询速度。

代码示例

package com.example.service;

import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    /**
     * 根据用户ID查询用户信息
     * @param id 用户ID
     * @return 用户信息
     */
    public User findUserById(int id) {
        return userMapper.findUserById(id);
    }

    /**
     * 查询所有用户信息
     * @return 用户列表
     */
    public List<User> findAllUsers() {
        return userMapper.findAllUsers();
    }
}

使用缓存的查询方法

public User findUserById(int id) {
    return userMapper.findUserById(id);
}

该方法会在首次查询时将查询结果存储到缓存中。后续的相同查询将直接从缓存中获取数据,而不会触发数据库查询。

缓存刷新

如果需要刷新缓存,可以通过以下方式手动刷新缓存:

package com.example.service;

import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.apache.ibatis.cache.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public void refreshUserCache() {
        Cache cache = userMapper.getCache();
        cache.clear();
    }
}

通过调用 cache.clear() 方法可以清除缓存中的所有数据,强制重新从数据库中加载数据。

以上代码展示了如何在实际项目中启用和使用 Mybatis 的二级缓存,以提高系统的查询性能。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消