我正在使用:
我有以下ProductServiceImpl方法:
@Override
@Cacheable(value="products", key="#product.id")
public Product save(Product product) {
return this.productRepository.save(product);
}
@Override
@Cacheable(value="products", key="#id")
public Product findOne(Integer id) {
return this.productRepository.findOne(id);
}
@Override
@CachePut(value="products", key="#product.id")
public Product update(Product product) {
return this.productRepository.save(product);
}
我有一个id为2的产品保存在DB(HSQL)中,库存为1。
根据上面显示的三种方法,键必须相同, 2
通过key="#id"
或key="#product.id"
现在,我知道缓存的工作方式如下,如何一个HashMap。
HashMap products = new HashMap();
products.put(2, product02);
在 Main 类中,我有以下内容(我正在使用注释让您了解我的逻辑):
logger.info("Inserting product02");
// must save the product02 in the cache too
userExecutionService01.executeSaveProduct(product02);
…
logger.info("-----------------");
logger.info("Getting product02");
product02 = null;
//Must retrieve the object from the cache, it has been already saved.
//The Stock must be 1.
product02 = userExecutionService01.executeFindProduct(2);
logger.info("Stock {}:", product02.getStock());
//1 + 100 = 101
product02.setStock(product02.getStock().add(new BigDecimal("100.00")));
//Must update database and the cache with the same product with the new Stock 101.
userExecutionService01.executeUpdateProduct(product02, false);
//Must retrieve the object from the cache, it has been already updated.
//The Stock must be 101.
logger.info("Getting & Printing product02");
userExecutionService01.executePrintProduct(2);
executeFindProduct 方法有
@Override
public Product executeFindProduct(Integer id){
return this.productService.findOne(id);
}
executeUpdateProduct 方法
@Override
public void executeUpdateProduct(Product product, boolean throwException){
logger.info("+++ executeUpdateProduct - start ");
logger.info(" Alfa: {}", this.productService.findOne(product.getId()).getStock());
this.productService.update(product);
logger.info(" Beta: {}", this.productService.findOne(product.getId()).getStock());
logger.info("+++ executeUpdateProduct - end ");
}
使用AOP,如果Cache正在运行,我正在进行控制。
@Before("execution(* *..ProductService.*(..))")
public void beforeServiceLogging(JoinPoint jointPoint){
logger.info(">Before {} called", jointPoint.getSignature().getName());
}
@Before("execution(* *..ProductRepository.*(..))")
public void beforeRepositoryLogging(JoinPoint jointPoint){
logger.info(">>Before {} called", jointPoint.getSignature().getName());
}
来自服务的 >
和来自存储库的>>
该应用有关于缓存的意外行为
如果我使用:
@Override
@Cacheable(value="products", key="#id")
public Product findOne(Integer id) {
return this.productRepository.findOne(id);
}
结果输出显示
- Inserting product02
- >Before save called
- >>Before save called //repository has been called, then: saved in DB and Cache
...
- -----------------
- Getting product02
- >Before findOne called
- Stock 1: //Correct, cache returns the expected value (1)
- +++ executeUpdateProduct - start
- >Before findOne called
- Alfa: 101.00 //Wrong, data has not been neither updated in the DB nor @Cacheput has been executed
- >Before update called
- >>Before save called //Repository, just then DB and Cache are being updated
- >Before findOne called
- Beta: 101.00
- +++ executeUpdateProduct - end
- Getting & Printing product02
- >Before findOne called
- Product [id=2, ... stock=101.00, …]
我很困惑,为什么" alfa"用库存101显示对象? 尚未调用Db,当然@Cacheput尚未执行。
是的,我知道我有这句话:
product02.setStock(product02.getStock().add(new BigDecimal("100.00")));
但是没有任何意义,线路以某种方式更新缓存,因为我使用显式 @CachePut
我只知道:EntityManager应该知道该product02的更新,并等到存储库执行更新/保存方法。
如果我使用
@Override
//@Cacheable(value="products", key="#id")
public Product findOne(Integer id) {
return this.productRepository.findOne(id);
}
所有关于阿尔法的都很好。
发生了什么事?