数据库实体缓存工具类样板代码优化的最佳实践咨询
最优解决方案:消除样板代码+规范缓存实现
方案一:使用Spring Cache(推荐的最佳实践)
你提到不确定Spring能否处理缓存,其实Spring Cache是Spring官方提供的缓存抽象,完全可以替代你手动编写的静态缓存,而且能自动处理缓存的命中、更新、过期等逻辑,彻底消除样板代码。
实现步骤:
引入依赖(Spring Boot项目):
如果用默认的内存缓存,只需要引入spring-boot-starter-cache;如果想用高性能的本地缓存(比如Caffeine),再加上com.github.ben-manes.caffeine:caffeine依赖。开启缓存功能:
在Spring Boot启动类上添加@EnableCaching注解:@SpringBootApplication @EnableCaching public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }给数据查询方法添加缓存注解:
在你的DAO/Service层的查询方法上,用@Cacheable指定缓存名称和缓存Key,Spring会自动缓存查询结果:@Repository public interface ProductRepository extends JpaRepository<Product, Integer> { // 缓存key为传入的id,缓存名称为"products" @Cacheable(value = "products", key = "#id") Optional<Product> findByIdProduct(Integer id); } @Repository public interface CustomerRepository extends JpaRepository<Customer, Integer> { @Cacheable(value = "customers", key = "#id") Optional<Customer> findById(Integer id); }缓存更新与清理:
当数据发生修改时,用@CachePut更新缓存,@CacheEvict清理缓存:// 更新Product缓存 @CachePut(value = "products", key = "#product.idProduct") Product save(Product product); // 删除Product缓存 @CacheEvict(value = "products", key = "#id") void deleteByIdProduct(Integer id);
这种方式完全不需要你手动维护静态列表和重复的查找方法,Spring会自动处理所有缓存逻辑,还支持切换不同的缓存实现(比如Redis用于分布式场景)。
方案二:手动实现通用缓存(适合不想用Spring Cache的场景)
如果坚持自己实现缓存,可以用泛型+函数式接口封装重复的查找逻辑,避免编写大量样板代码:
实现通用缓存管理器:
import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; @Component // 交给Spring管理,单例使用 public class GenericCacheManager { // 用Map存储不同类型的实体缓存,key为实体类的Class对象 private final Map<Class<?>, List<?>> entityCache = new ConcurrentHashMap<>(); // 初始化缓存:从数据库加载数据存入缓存 public <T> void loadCache(Class<T> entityClass, List<T> dataList) { entityCache.put(entityClass, dataList); } // 通用根据ID查找方法:传入实体类、目标ID、获取实体ID的函数 @SuppressWarnings("unchecked") public <T, ID> T findById(Class<T> entityClass, ID targetId, Function<T, ID> idGetter) { List<T> dataList = (List<T>) entityCache.get(entityClass); if (dataList == null) { return null; } return dataList.stream() .filter(entity -> targetId.equals(idGetter.apply(entity))) .findFirst() .orElse(null); } }
使用方式:
初始化缓存(比如在项目启动时):
// 加载Product缓存 genericCacheManager.loadCache(Product.class, productRepository.findAll()); // 加载Customer缓存 genericCacheManager.loadCache(Customer.class, customerRepository.findAll());查找实体:
// 查找ID为1的Product Product product = genericCacheManager.findById(Product.class, 1, Product::getIdProduct); // 查找ID为2的Customer Customer customer = genericCacheManager.findById(Customer.class, 2, Customer::getId);
这种方式不管新增多少实体,都不需要编写新的查找方法,只需要调用通用方法即可,但需要注意:数据更新时要手动调用loadCache刷新缓存列表,否则会出现缓存不一致的问题。
内容的提问来源于stack exchange,提问作者user7303261
相关产品推荐
相关产品推荐

