Java本地缓存的使用

在项目开发中,经常会碰到一些数据量小、但使用频率极高的数据。比如,团队到BU的映射表。此类数据通常不会变动,使用频率高且数据量较小,如果每次使用都去数据库查询,代价比较大,可以考虑在项目启动时将此类数据加载到缓存中,并定时进行增量更新

项目中本身没有用redis,也没必要上,java的本地缓存完全可以满足需求。当然,数据量较大的情况下,还是不推荐这样使用的,可能会造成OOM。

下面是一个缓存的抽象类,子类继承并实现toHandler()方法后,相关数据就会在项目启动时被加载到缓存中,然后通过getEntityById()方法获取。

java 复制代码
public abstract class BaseCache<T> {
    // 用于定时执行更新任务
    ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor();
    // map存储数据
    Map<Object, T> cacheMap = new HashMap<>();
    BaseMapper<T> baseDao;
    // 用于记录上一次缓存更新的时间
    protected Date currentTime = DateUtil.getDate(2000, 1, 1);

    public BaseCache() {
        this.baseDao = baseDao;

        //定时获取缓存
        timer.scheduleAtFixedRate(() -> {
            List<T> results = getList();
            if (results.size() > 0) {
                T result = results.get(results.size() - 1);
                if (result instanceof Map) {
                    currentTime = (Date) ((Map) result).get("DataChange_LastTime");
                } else {
                    currentTime = (Date) ReflectionUtils.getFieldValue(result, "datachangeLasttime");
                }
                toHandler(results);
            }

        }, 1000, 1000, TimeUnit.MILLISECONDS);   // 时间可以根据业务需要进行变更
    }

    // 根据数据变更时间,获取增量数据
    protected List<T> getList() {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.gt("DataChange_LastTime", currentTime);
        queryWrapper.orderByAsc("DataChange_LastTime");
        return baseDao.selectList(queryWrapper);
    }

    // 此抽象方法由子类实现,往缓存中(cacheMap)存放所需要的值
    protected abstract void toHandler(List<T> results);

    // 从缓存中获取数据
    public T getEntityById(Object id) {
        return cacheMap.get(id);
    }
}

下面是一个BaseCache的子类,功能是将userid和username放入内存进行映射,并提供【根据id获取name】和【根据name获取id】两个get方法。

ps: 实际业务代码肯定不是这种鸡肋的内容啦,数据脱敏。

UserCache类被@Repository@Lazy注解修饰,在第一次被用到的时候会被注入到IOC容器中,此时会调用其(父类BaseCache)构造函数,开始执行定时任务,调用toHandler()方法,将数据存入idCacheMap中。

因为业务的需要,既要通过key获取到value,又要通过value获取到key,因此我在这里没有复用父类中的map,而是添加了一个BiMap

java 复制代码
@Lazy
@Repository
public class UserCache extends BaseCache<User>{

    // Map<userid, username>
    private BiMap<Long, String> idCacheMap = HashBiMap.create();

    @Autowired
    public void setDao(UserDao entityDao) {
        this.baseDao = entityDao;
    }

    @Override
    protected void toHandler(List<User> results) {
        results.stream().forEach(p -> {
            this.idCacheMap.put(p.getUserid(), p.getUserName());
        });
    }

    public Long getUsername(Long userid) {
        return idCacheMap.get(userid);
    }

    public Long getUserid(String username) {
        return idCacheMap.inverse().get(username);
    }
}
相关推荐
Ai财富密码2 分钟前
【Linux教程】Linux 生存指南:掌握常用命令,避开致命误操作
java·服务器·前端
LUCIAZZZ8 分钟前
项目拓展-Jol分析本地对象or缓存的内存占用
java·开发语言·jvm·数据库·缓存·springboot
GalaxyPokemon29 分钟前
LeetCode - 69. x 的平方根
java·数据结构·算法
在未来等你39 分钟前
设计模式精讲 Day 1:单例模式(Singleton Pattern)
java·设计模式·面向对象·软件架构
heart000_11 小时前
基于 WebWorker 的 WebAssembly 图像处理吞吐量分析
java·图像处理·wasm
菜鸟阿达1 小时前
Idea 2025 commit 关闭侧边栏 开启探框
java·ide·intellij-idea
雨果talk1 小时前
【一文看懂多模块Bean初始化难题】Spring Boot多模块项目中的Bean初始化难题:包名不一致的优雅解决方案
java·spring boot·后端·spring·springboot
xiaowu0801 小时前
C# 中的Async 和 Await 的用法详解
java·开发语言·c#
范纹杉想快点毕业1 小时前
初探Qt信号与槽机制
java·c语言·开发语言·c++·qt·visualstudio·visual studio
哈喽姥爷1 小时前
苍穹外卖--缓存菜品Spring Cache
java·缓存·spring cache·苍穹外卖·黑马