chestnut
There is a requirement to query the product using the product name. It requires querying the cache first, and if it cannot be found, go to the database to query; after querying from the database, add it to the cache, and continue to query again. Query cache.
Idea analysis
You can write a conditional judgment, the pseudo code is as follows:
//先从缓存中查询
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);
}The above string of codes can also achieve the query effect, It doesn't look very complicated, but this string of code is non-reusable and can only be used in this scenario. Assuming that there are many needs similar to the above product query in our system, then we need to write if(...)else{...} everywhere. As a programmer, it is very uncomfortable to be unable to unify similar or repeated codes, so the code for this scenario needs to be optimized.
The problem with the above code is: The input parameters are not fixed, and the return value is not fixed either. If only the parameters are not fixed, just use generics. But the most important thing is that the query method is not fixed. For example, querying products and querying users are definitely not the same query method.
So it would be great if we could pass a method (i.e. the various query methods above) as a parameter into a unified judgment method, similar to:
/** * 这个方法的作用是:先执行method1方法,如果method1查询或执行不成功,再执行method2方法 */ public static<T> T selectCacheByTemplate(method1,method2)
want To achieve the above effect, we have to mention the new features of Java8: Functional programming
Principle introduction
There is a package in Java: java.util.function , all of them are interfaces, and they are all modified by the @FunctionalInterface annotation.
Function Category
Consumer: Accept parameters, no return value
Function (function): Accepts parameters and returns a value
Operator (operation): Accepts parameters and returns the same type as the parameters The value of
Predicate (assertion): Accepts parameters and returns boolean type
##Supplier (Supply): No parameters, return value
Then let’s use Java to elegantly query the cache first and then the database!Project codeConfiguration file
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>SpringBoot-query</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringBoot-query</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>Project structure

package com.example.springbootquery;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootQueryApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootQueryApplication.class, args);
}
}
Goods.javapackage com.example.springbootquery.entity;
public class Goods {
private String goodsName;
private Integer goodsTotal;
private Double price;
public String getGoodsName() {
return goodsName;
}
public void setGoodsName(String goodsName) {
this.goodsName = goodsName;
}
public Integer getGoodsTotal() {
return goodsTotal;
}
public void setGoodsTotal(Integer goodsTotal) {
this.goodsTotal = goodsTotal;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public String toString() {
return "Goods{" +
"goodsName='" + goodsName + '\'' +
", goodsTotal='" + goodsTotal + '\'' +
", price=" + price +
'}';
}
}
CacheSelector.java
Custom functional interface:
package com.example.springbootquery.function;
@FunctionalInterface
public interface CacheSelector<T> {
T select() throws Exception;
}CacheService.javapackage com.example.springbootquery.service;
import com.example.springbootquery.entity.Goods;
public interface CacheService {
/**
* 从缓存中获取商品
*
* @param goodsName 商品名称
* @return goods
*/
Goods getGoodsByName(String goodsName) throws Exception;
}
CacheServiceImpl.javapackage com.example.springbootquery.service.impl;
import com.alibaba.fastjson.JSON;
import com.example.springbootquery.entity.Goods;
import com.example.springbootquery.service.CacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
@Service("cacheService")
public class CacheServiceImpl implements CacheService {
@Autowired
private StringRedisTemplate redisTemplate;
@Override
public Goods getGoodsByName(String goodsName) throws Exception {
String s = redisTemplate.opsForValue().get(goodsName);
return null == s ? null : JSON.parseObject(s, Goods.class);
}
}
GoodsService. javapackage com.example.springbootquery.service;
import com.example.springbootquery.entity.Goods;
public interface GoodsService {
Goods getGoodsByName(String goodsName);
}
GoodsServiceImpl.java
I will not connect to the database here, but simulate a returnpackage com.example.springbootquery.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.example.springbootquery.entity.Goods;
import com.example.springbootquery.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class GoodsServiceImpl implements GoodsService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Override
public Goods getGoodsByName(String goodsName) {
Goods goods = new Goods();
goods.setGoodsName("商品名1");
goods.setGoodsTotal(20);
goods.setPrice(30.0D);
stringRedisTemplate.opsForValue().set(goodsName, JSONObject.toJSONString(goods));
return goods;
}
}BaseUtil.java (core class)
Because I don't care about the parameters and only need a return value, Supplier is used here. package com.example.springbootquery.util;
import com.example.springbootquery.function.CacheSelector;
import java.util.function.Supplier;
public class BaseUtil {
/**
* 缓存查询模板
*
* @param cacheSelector 查询缓存的方法
* @param databaseSelector 数据库查询方法
* @return T
*/
public static <T> T selectCacheByTemplate(CacheSelector<T> cacheSelector, Supplier<T> databaseSelector) {
try {
System.out.println("query data from redis ······");
// 先查 Redis缓存
T t = cacheSelector.select();
if (t == null) {
// 没有记录再查询数据库
System.err.println("redis 中没有查询到");
System.out.println("query data from database ······");
return databaseSelector.get();
} else {
return t;
}
} catch (Exception e) {
// 缓存查询出错,则去数据库查询
e.printStackTrace();
System.err.println("redis 查询出错");
System.out.println("query data from database ······");
return databaseSelector.get();
}
}
}Usagepackage com.example.springbootquery;
import com.example.springbootquery.entity.Goods;
import com.example.springbootquery.service.CacheService;
import com.example.springbootquery.service.GoodsService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static com.example.springbootquery.util.BaseUtil.selectCacheByTemplate;
@SpringBootTest
class SpringBootQueryApplicationTests {
@Autowired
private CacheService cacheService;
@Autowired
private GoodsService userService;
@Test
void contextLoads() throws Exception {
Goods user = selectCacheByTemplate(
() -> cacheService.getGoodsByName("商品名1"),
() -> userService.getGoodsByName("商品名1")
);
System.out.println(user);
}
}
Query from the data for the first time


The above is the detailed content of How to use Java to query cache first and then query database. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.

SublimeText3 English version
Recommended: Win version, supports code prompts!

Atom editor mac version download
The most popular open source editor

Dreamweaver Mac version
Visual web development tools






