[英]Spring Boot Redis Cache remove cache with multiple key
我有一種保存緩存的方法。
@GetMapping("/orders")
@Cacheable(value = "List<Order>", key = "{#customerName+'s orders', #page, #size}")
public List<Order> findOrders(@RequestParam("customerName") String customerName,
@RequestParam(name = "page") int page,
@RequestParam(name = "size") int size) {
...
我想在調用這個方法后刪除這個緩存。
@PostMapping("/order")
@CacheEvict(value = "*",key="{#makeOrderDTO.customerDTO.name+'s orders', '', 'regex:*'}")
public Order makeOrder(@RequestBody MakeOrderDTO makeOrderDTO) {
我有一個問題,我想刪除客戶的所有緩存頁面,但我不能只刪除一種類型的頁面。 所以我需要刪除所有頁面大小和數量的客戶。 也許有某種功能,例如
@PostMapping("/order")
@CacheEvict(value = "*",key="{#makeOrderDTO.customerDTO.name+'s orders', 'regex:*', 'regex:*'}")
public Order makeOrder(@RequestBody MakeOrderDTO makeOrderDTO) {
或者
@PostMapping("/order")
@CacheEvict(value = "*",key="{#makeOrderDTO.customerDTO.name+'s orders', 'any', 'any'}")
public Order makeOrder(@RequestBody MakeOrderDTO makeOrderDTO) {
提前致謝。
你不能這樣做,因為所有緩存技術都使用鍵值存儲。 因此,如果您對鍵使用多個參數,如下所示:
key = "{#customerName+'s orders', #page, #size}"
Spring 創建一個 hash 作為密鑰,例如:-172893112。
我建議您將緩存名稱更改為使用“'List' + #customerName+'s orders'”,但至少使用 CacheResolver 時不支持使用注釋。 見這里。
@GetMapping("/orders")
@Cacheable(value = "List<Order>", key = "{#customerName+'s orders', #page, #size}")
public List<Order> findOrders(@RequestParam("customerName") String customerName, @RequestParam(name = "page") int page, @RequestParam(name = "size") int size) {
//...
List<Order> result = //...Do the operation
String cacheName = "List<Order>" + customerName + "s orders";
redisTemplate
.opsForHash()
.put(cacheName, Objects.hash(customerName, page, size), result);
}
之后,驅逐方法應該是:
@PostMapping("/order")
public Order makeOrder(@RequestBody MakeOrderDTO makeOrderDTO) {
String cacheName = "List<Order>" + makeOrderDTO.getCustomerDTO().getName() + "s orders";
redisTemplate
.opsForHash()
.keys(cacheName)
.forEach(x -> redisTemplate.opsForHash().delete(cacheName, x));
//...Do operations
}
您可以查看另一個帖子: Cache evict on one of multiple keys
查看您的初始方法:
@GetMapping("/orders")
@Cacheable(value = "List<Order>", key = "{#customerName+'s orders', #page, #size}")
public List<Order> findOrders(@RequestParam("customerName") String customerName,
@RequestParam(name = "page") int page,
@RequestParam(name = "size") int size) {
...
從簽名猜測,該方法做了很多事情:
如果分頁參數不同,您可能會多次檢索和緩存相同的訂單。 下新訂單后,您需要重新閱讀未更改的先前訂單。 那是次優的。
我建議將數據訪問和緩存數據的關注點分開,並在兩個類或層中為 web 請求提供服務,因為 web 層位於數據訪問層之上。
此外,始終使用 id 而不是客戶名稱作為鍵,因為名稱可能有重復並且也會發生變化(是的,錯字。婚姻和公司合並)。
對於緩存查詢結果,我總是建議分別緩存查詢結果和數據。 例如,在您的數據訪問層中:
public List<Integer> findOrders(int customerId);
public Order retrieveOrder(int orderId);
為它使用兩個單獨的緩存。
然后,您可以在 REST 層中實現分頁。
public Order makeOrder(MakeOrderDTO makeOrderDTO)
下新訂單時,訂單列表查詢結果無效。 您可以添加 ID,也可以使用 evict 使查詢結果緩存無效。 但是,這不會影響帶有實際訂單數據的緩存。
我省略了實際的 Spring 緩存注釋。 一旦您對界面進行了排序,這些界面就應該簡單明了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.