使用Java优雅的实现先查询缓存再查询数据库

本文介绍了如何使用Java8的新特性,通过Function接口优雅地实现在查询数据时,先从缓存中查找,如果找不到再查询数据库。文章通过一个商品查询的例子,详细阐述了思路分析、原理介绍以及具体的代码实现,展示了如何创建自定义函数式接口并结合Supplier进行操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:strawberry:

在访问量大的时候,为了提高查询效率,我们会将数据先缓存到redis中。先查询redis,查询不到再去查询数据库,实现这个逻辑也不复杂,写一个 if(...)else{...} 也就行了。这种做法也不是不行,就是看起来有点儿粗糙,所以我想换一种更优雅的写法。

举个栗子:chestnut:

现有一个使用商品名称查询商品的需求,要求先查询缓存,查不到则去数据库查询;从数据库查询到之后加入缓存,再查询时继续先查询缓存。

思路分析

可以写一个条件判断,伪代码如下:

//先从缓存中查询
String goodsInfoStr = redis.get(goodsName);
if(StringUtils.isBlank(goodsInfoStr)){
	//如果缓存中查询为空,则去数据库中查询
	Goods goods = goodsMapper.queryByName(goodsName);
	//将查询到的数据存入缓存
	goodsName.set(goodsName,JSONObject.toJSONString(goods));
	//返回商品数据
	return goods;
}else{
	//将查询到的str转换为对象并返回
	return JSON.parseObject(goodsInfoStr, Goods.class);
}
复制代码

上面这串代码也可以实现查询效果,看起来也不是很复杂,但是这串代码是 不可复用的 ,只能用在这个场景。假设在我们的系统中还有很多类似上面商品查询的需求,那么我们需要到处写这样的 if(...)else{...} 。作为一个程序员,不能把类似的或者重复的代码统一起来是一件很难受的事情,所以需要对这种场景的代码进行优化。

上面这串代码的问题在于: 入参不固定、返回值也不固定,如果仅仅是参数不固定,使用泛型即可。但最关键的是查询方法也是不固定的,比如查询商品和查询用户肯定不是一个查询方法吧。

所以如果我们可以把一个方法(即上面的各种查询方法)也能当做一个参数传入一个统一的判断方法就好了,类似于:

/**
 * 这个方法的作用是:先执行method1方法,如果method1查询或执行不成功,再执行method2方法
 */
public static<T> T selectCacheByTemplate(method1,method2)
复制代码

想要实现上面的这种效果,就不得不提到Java8的新特性: 函数式编程

原理介绍

在Java中有一个package: java.util.function ,里面全部是接口,并且都被 @FunctionalInterface 注解所修饰。

Function分类

  • Consumer(消费):接受参数,无返回值
  • Function(函数):接受参数,有返回值
  • Operator(操作):接受参数,返回与参数同类型的值
  • Predicate(断言):接受参数,返回boolean类型
  • Supplier(供应):无参数,有返回值

具体我就不在赘述了,可以参考: blog.youkuaiyun.com/hua226/arti…

代码实现:cake:

那么接下来就来使用Java优雅的实现先查询缓存再查询数据库吧!

项目代码

<
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值