spring-projects / spring-data-redis

Provides support to increase developer productivity in Java when using Redis, a key-value store. Uses familiar Spring concepts such as a template classes for core API usage and lightweight repository style data access.
https://spring.io/projects/spring-data-redis/
Apache License 2.0
1.77k stars 1.17k forks source link

Do not sync cache when @CachePut #2977

Closed 1995mars closed 2 months ago

1995mars commented 3 months ago

``I'm trying to integrate Spring cache within my project. I've set up a Redis cache manager and it indeed works. However, this is my scenario: I have a Product entity. I want to make a findAll method that can return all of the products .

@Service
@CacheConfig(cacheNames = "product")
public class ProductServiceImpl implements ProductService {
    @Autowired
    private ProductRepository productRepository;

    @Override
    @CachePut(value = "product")
    public Product save(Product product) {
        return productRepository.save(product);
    }

    @Override
    @CachePut(value = "product", key = "#product.productCode")
    public Product updateProduct(Product product) {
        Product prd = productRepository.findById(product.getProductCode())
                .orElseThrow(() -> new ProductNotFoundException("Product Not Found"));
        prd.setQuantityInStock(product.getQuantityInStock() - 10);
        return productRepository.save(prd);
    }

    @Override
    @CacheEvict(value = "product", key = "#productCode")
    public void deleteProduct(String productCode) {
        Product prd = productRepository.findById(productCode)
                .orElseThrow(() -> new ProductNotFoundException("Product Not Found"));
        productRepository.delete(prd);
    }

    @Override
    @Cacheable(value = "product", key = "#productCode")
    public Product getOneProduct(String productCode) {
        Product prd = productRepository.findById(productCode)
                .orElseThrow(() -> new ProductNotFoundException("Product Not Found"));
        return prd;
    }

    @Override
    @Cacheable(value = "product")
    public List<Product> getAllProducts() {
        return productRepository.findAll();
    }
}

When I call to getAllProducts I get a product::SimpleKey [] key in my Redis (that's my expected behaviour). However, when I call to updateProduct, because of the extra argument, instead of overrding the product::SimpleKey [] key, I end up with another key in Redis: "product::SimpleKey []"

How do I synchronize data to cache when I update or add new data? So that when I call the getAllProducts method, I can get the data after the change in cache.

I'll appriciate any help!

christophstrobl commented 3 months ago

Thank you for reaching out - Please take the time to provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem.

1995mars commented 3 months ago

Thank you for reaching out - Please take the time to provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem.

I have provided the code, please check it for me

mp911de commented 2 months ago

Each @Cacheable annotation defines a scheme to access the cache along with its cache keys. @CachePut(value = "product") doesn't define a scheme for a cache key so invocations use Product product as the cache key.

This is a Spring Framework topic and Stackoverflow is much better to discuss these questions.