我有一个连接到 SQL Server 数据库的 Spring boot 应用程序。我需要一些帮助来在我的应用程序中使用缓存。我有一个 CodeCategory 表,其中包含许多代码的代码列表。该表将每月加载一次,并且数据每月仅更改一次。 我想在应用程序启动时缓存整个表。在对表的任何后续调用中,都应该从此缓存中获取值,而不是调用数据库。
例如,
List<CodeCategory> findAll();
我想在应用程序启动期间缓存上述数据库查询值。如果有像
List<CodeCategory> findByCodeValue(String code)
这样的数据库调用,应该从已经缓存的数据中获取代码结果,而不是调用数据库。
请让我知道如何使用 spring boot 和 ehcache 来实现这一点。
正如所指出的,ehcache 需要一些时间来设置,并且它不能完全与
@PostConstruct
一起工作。在这种情况下,请使用 ApplicationStartedEvent
加载缓存。
GitHub 存储库:spring-ehcache-demo
@Service
class CodeCategoryService{
@EventListener(classes = ApplicationStartedEvent.class )
public void listenToStart(ApplicationStartedEvent event) {
this.repo.findByCodeValue("100");
}
}
interface CodeCategoryRepository extends JpaRepository<CodeCategory, Long>{
@Cacheable(value = "codeValues")
List<CodeCategory> findByCodeValue(String code);
}
注意:其他人指出有多种方法。您可以根据您的需要进行选择。
我的方法是定义一个通用的缓存处理程序
@FunctionalInterface
public interface GenericCacheHandler {
List<CodeCategory> findAll();
}
其实现如下
@Component
@EnableScheduling // Important
public class GenericCacheHandlerImpl implements GenericCacheHandler {
@Autowired
private CodeRepository codeRepo;
private List<CodeCategory> codes = new ArrayList<>();
@PostConstruct
private void intializeBudgetState() {
List<CodeCategory> codeList = codeRepo.findAll();
// Any customization goes here
codes = codeList;
}
@Override
public List<CodeCategory> getCodes() {
return codes;
}
}
在Service层调用如下
@Service
public class CodeServiceImpl implements CodeService {
@Autowired
private GenericCacheHandler genericCacheHandler;
@Override
public CodeDTO anyMethod() {
return genericCacheHandler.getCodes();
}
}
使用二级休眠缓存来缓存所有需要的数据库查询。
为了在应用程序启动时进行缓存,我们可以在任何 Service 类中使用@PostContruct。
语法为:-
@Service
public class anyService{
@PostConstruct
public void init(){
//call any method
}
}
使用 CommandLineRunner 界面。 基本上,您可以创建一个 Spring @Component 并实现 CommandLineRunner 接口。您必须重写它的 run 方法。 run 方法将在应用程序启动时调用。
@Component
public class DatabaseLoader implements
CommandLineRunner {
@override
Public void run(.... string){
// Any code here gets called at the start of the app.
}}
此方法主要用于使用一些初始数据引导应用程序。
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
public List<Product> getAllProducts() {
return productRepository.findAll();
}
@Cacheable(cacheNames = "product", key = "#id")
public ProductDto findById(Long id) {
Product savedProduct = productRepository.findById(id).orElseThrow(() -> new RuntimeException("Product not found"));
ProductDto productDto = new ProductDto();
BeanUtils.copyProperties(savedProduct, productDto);
return productDto;
}
}