2017-03-23 25 views
1

我有這樣一個Product模型對象 -緩存與春的Ehcache不工作按預期

class ProductDTO { 
    int id; 
    String code; 
    String description; 

    //getters and setters go here 
} 

我寫一個服務(下面的代碼),通過ID或代碼查找產品並返回其描述。我正在使用Spring 4和ehcache來緩存結果。

我有2個方法 - 一個用於查找id和一個用代碼查找 - 他們是getProductByCodegetProductById。兩者都以字符串的形式返回描述。他們通過致電getAllProducts()返回所有產品的列表。呼叫者然後在列表中搜索與id或代碼匹配的產品並返回描述。

getAllProducts()還會爲每個產品調用2種方法並使用@CachePut - 通過鍵codeid將描述字符串保存在緩存中。

如果將相同參數傳遞給codeidgetProductByCodegetProductById方法,緩存工作正常。但是如果我通過一個不同的參數,再次調用getAllProducts()

我該如何實現預期的行爲 - 每次調用getAllProducts()時,所有描述都被緩存,隨後的調用將查找緩存而不是去存儲庫?

public class ProductServiceImpl implements ProductService { 

    @Autowired 
    ProductsRepository ProductRepo; 

    @Override 
    public List<ProductDTO> getAllProducts() { 
     List<ProductDTO> products = ProductRepo.getAllProducts(); 
     for(ProductDTO prodDTO : products) { 
      String desc = prodDTO.getDescription(); 
      String code = prodDTO.getCode(); 
      int id = prodDTO.getId(); 
      putDescriptionInCache(desc, code); 
      putDescriptionInCache(desc, id); 
     } 
     return products; 
    } 

    @CachePut(value = "products", key = "#id") 
    public String putDescriptionInCache(String description, int id){ 
     return description; 
    } 

    @CachePut(value = "products", key = "#code") 
    public String putDescriptionInCache(String description, String code){ 
     return description; 
    } 

    @Override 
    @Cacheable(value="products", key="#id") 
    public String getProductById(Integer id) throws NullPointerException { 
     String dtoDesc = null; 
     List<ProductDTO> products = getAllProducts(); 
     for(ProductDTO currDTO : products) { 
      int currId = currDTO.getId(); 
      if(id.equals(new Integer(currId))) { 
       dtoDesc = currDTO.getDescription(); 
      } 
     } 
     return dtoDesc; 
    } 

    @Override 
    @Cacheable(value="products", key="#code") 
    public String getProductByCode(String code) throws NullPointerException { 
     String dtoDesc = null; 
     List<ProductDTO> products = getAllProducts(); 
     for(ProductDTO currDTO : products) { 
      String currCode = currDTO.getCode(); 
      if(currCode.equals(code)) { 
       dtoDesc = currDTO.getDescription(); 
      } 
     } 
     return dtoDesc; 
    } 
} 
+2

緩存是使用AOP實現的。 AOP使用代理應用,因此只適用於進入對象的方法調用。內部方法調用不通過代理,因此這兩個方法調用基本上是徒勞的。 –

+0

謝謝M.Deinum。這些信息與另一篇文章(對不起,我現在失去了它的鏈接)有所幫助。我將兩個putDescriptionInCache()方法都移到了較低層(ProductsRepository內),並將以下注釋添加到getProductByCode()和getProductById() - @Cacheable(「products」)。這樣,第一次調用通過getAllProducts()並緩存數據。另外,我的ProductRepository還有其他幾個方法 - getDirectionalTextById()和getDirectionalTextByCode() - 每個方法都有SQL來獲取描述。我從上面一層的同名方法中調用這些方法。 – lenniekid

回答

1

因爲它是由M. Deinum評論的,問題就來了從註釋,如CachePutCacheable,被改造成在運行時的一個方面。這種方法的主要侷限性是來自同一個班級的電話沒有被正確捕獲。

正如你在評論部分回覆自己,將註釋的方法移動到當前注入的另一個類型解決了這個問題。

+0

這是否也適用於其他註釋,如@Cacheable? – lenniekid

+0

是的,編輯答案使其更加清晰。當然,如果註釋比裝飾一個方法調用有另一個影響,那麼這個註釋與那些無關。 –