How to use Java to query cache first and then query database
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>
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);
}
}
Copy after login
Goods.javapackage 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); } }
package 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 +
'}';
}
}
Copy after login
CacheSelector.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 + '}'; } }
Custom functional interface:
package com.example.springbootquery.function; @FunctionalInterface public interface CacheSelector<T> { T select() throws Exception; }
package com.example.springbootquery.service;
import com.example.springbootquery.entity.Goods;
public interface CacheService {
/**
* 从缓存中获取商品
*
* @param goodsName 商品名称
* @return goods
*/
Goods getGoodsByName(String goodsName) throws Exception;
}
Copy after login
CacheServiceImpl.javapackage com.example.springbootquery.service; import com.example.springbootquery.entity.Goods; public interface CacheService { /** * 从缓存中获取商品 * * @param goodsName 商品名称 * @return goods */ Goods getGoodsByName(String goodsName) throws Exception; }
package 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);
}
}
Copy after login
GoodsService. 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); } }
package com.example.springbootquery.service;
import com.example.springbootquery.entity.Goods;
public interface GoodsService {
Goods getGoodsByName(String goodsName);
}
Copy after login
GoodsServiceImpl.javapackage com.example.springbootquery.service; import com.example.springbootquery.entity.Goods; public interface GoodsService { Goods getGoodsByName(String goodsName); }
I will not connect to the database here, but simulate a returnBaseUtil.java (core class)package 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; } }Copy after login
Because I don't care about the parameters and only need a return value, Supplier is used here.Usagepackage 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(); } } }Copy after login
package 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);
}
}
Copy after loginQuery from the data for the first time
package 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); } }
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

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics











Java 8 introduces the Stream API, providing a powerful and expressive way to process data collections. However, a common question when using Stream is: How to break or return from a forEach operation? Traditional loops allow for early interruption or return, but Stream's forEach method does not directly support this method. This article will explain the reasons and explore alternative methods for implementing premature termination in Stream processing systems. Further reading: Java Stream API improvements Understand Stream forEach The forEach method is a terminal operation that performs one operation on each element in the Stream. Its design intention is

MySQL is an open source relational database management system. 1) Create database and tables: Use the CREATEDATABASE and CREATETABLE commands. 2) Basic operations: INSERT, UPDATE, DELETE and SELECT. 3) Advanced operations: JOIN, subquery and transaction processing. 4) Debugging skills: Check syntax, data type and permissions. 5) Optimization suggestions: Use indexes, avoid SELECT* and use transactions.

PHP is a scripting language widely used on the server side, especially suitable for web development. 1.PHP can embed HTML, process HTTP requests and responses, and supports a variety of databases. 2.PHP is used to generate dynamic web content, process form data, access databases, etc., with strong community support and open source resources. 3. PHP is an interpreted language, and the execution process includes lexical analysis, grammatical analysis, compilation and execution. 4.PHP can be combined with MySQL for advanced applications such as user registration systems. 5. When debugging PHP, you can use functions such as error_reporting() and var_dump(). 6. Optimize PHP code to use caching mechanisms, optimize database queries and use built-in functions. 7

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHP is suitable for web development, with simple syntax and high execution efficiency. 2. Python is suitable for data science and machine learning, with concise syntax and rich libraries.

PHP is suitable for web development, especially in rapid development and processing dynamic content, but is not good at data science and enterprise-level applications. Compared with Python, PHP has more advantages in web development, but is not as good as Python in the field of data science; compared with Java, PHP performs worse in enterprise-level applications, but is more flexible in web development; compared with JavaScript, PHP is more concise in back-end development, but is not as good as JavaScript in front-end development.

PHP and Python each have their own advantages and are suitable for different scenarios. 1.PHP is suitable for web development and provides built-in web servers and rich function libraries. 2. Python is suitable for data science and machine learning, with concise syntax and a powerful standard library. When choosing, it should be decided based on project requirements.

MySQL is an open source relational database management system, mainly used to store and retrieve data quickly and reliably. Its working principle includes client requests, query resolution, execution of queries and return results. Examples of usage include creating tables, inserting and querying data, and advanced features such as JOIN operations. Common errors involve SQL syntax, data types, and permissions, and optimization suggestions include the use of indexes, optimized queries, and partitioning of tables.

The reasons why PHP is the preferred technology stack for many websites include its ease of use, strong community support, and widespread use. 1) Easy to learn and use, suitable for beginners. 2) Have a huge developer community and rich resources. 3) Widely used in WordPress, Drupal and other platforms. 4) Integrate tightly with web servers to simplify development deployment.
