2015-06-29 5 views
3

Я получаю дубликаты ключей в своем кэше.CacheLoader загружает одни и те же ключи в несколько раз

Я звоню в веб-службу, используя SOAP для оценки политик для страховой компании. Я пытаюсь использовать Cachebuilder/loader для хранения DTO в качестве ключа и ответа от службы как значения. Из того, что я исследовал, методы .get и .getUnchecked получат значение из кеша, и если его там нет, он загрузит это значение в кеш. здесь некоторый код:

public class CacheLoaderImpl 
{ 
    private static CacheLoaderImpl instance = null; 
    private static LoadingCache<PolicyDTO, RatingServiceObjectsResponse> responses; 

    protected CacheLoaderImpl() 
    { 
     responses = CacheBuilder.newBuilder() 
      .expireAfterWrite(10, TimeUnit.MINUTES) 
      .build(
       new CacheLoader<PolicyDTO, RatingServiceObjectsResponse>() { 
        public RatingServiceObjectsResponse load(PolicyDTO key) 
         throws Exception 
        { 
         return getResponse(key); 
        } 
       }); 
    } 

    public static CacheLoaderImpl getIntance() 
    { 
     if(instance == null) 
     { 
     instance = new CacheLoaderImpl(); 
     } 

     return instance; 
    } 

    public LoadingCache<PolicyDTO, RatingServiceObjectsResponse> getResponses() 
    { 
     return responses; 
    } 

    public RatingServiceObjectsResponse getResponse(PolicyDTO key) throws ExecutionException 
    { 
    RatingServiceObjectsResponse response = new RatingServiceObjectsResponse(); 
    try 
    { 
     response = new CGIRatabaseServiceImpl().getCoverages(key); 
    } 
    catch (RemoteException e) 
    { 
     e.printStackTrace(); 
    } 
    catch (IllegalArgumentException e) 
    { 
     e.printStackTrace(); 
    } 
    return response; 

    } 

} 

И это где я называю метод прибудет:

RatingServiceObjectsResponse response = CacheLoaderImpl.getIntance().getResponses().get(policy.toCoveragesCallDTO()); 

Я был в предположении, что, возможно, сравнивали адреса памяти, которые будут отличаться, так что я переписал toString для преобразования объекта DTO в JSON. После проверки кеша я вижу, что ключи точно совпадают с инструментом сравнения. Тем не менее, они все еще хранятся и каждый раз звонят в службу. Я попытался переписать метод equals в PolicyDTO, но он никогда не попадает, когда я отлаживаю.

Как я могу заставить кеш-загрузчик загружать только значения разных ключей и вытаскивать существующие значения изначально?

Я думаю, что у меня просто нет четкой идеи о том, как работает cacheLoader. Я ценю любую помощь или предложения.

класс

PolicyDTO:

public class PolicyDTO extends AbstractDto implements IPolicyDTO 
{ 
    private ArrayList<ILineOfBusinessDTO> lobDTOs = new ArrayList<ILineOfBusinessDTO>(); 
    private String pcInd; 
    private String ratingEffectiveDate; 
    private String companyName; 

    public String getPcInd() 
    { 
     return pcInd; 
    } 

    public void setPcInd(String pcInd) 
    { 
     this.pcInd = pcInd; 
    } 

    public String getRatingEffectiveDate() 
    { 
     return ratingEffectiveDate; 
    } 

    public void setRatingEffectiveDate(AdvancedDate ratingEffectiveDate) 
    { 
     if(ratingEffectiveDate != null) 
     { 
     this.ratingEffectiveDate = ratingEffectiveDate.toFormattedStringMMDDYYYY(); 
     } 
     else 
     { 
     this.ratingEffectiveDate = new AdvancedDate().toFormattedStringMMDDYYYY(); 
     } 
    } 

    public String getCompanyName() 
    { 
     return companyName; 
    } 

    public void setCompanyName(String companyName) 
    { 
     this.companyName = companyName; 
    } 

    public DtoType getType() 
    { 
     return hasGetCoveragesCoverageDTO() ? DtoType.GET_COVERAGE_POLICY : DtoType.RATE_POLICY; 
    } 

    public boolean hasGetCoveragesCoverageDTO() 
    { 
     if(lobDTOs != null) 
     { 
      for(ILineOfBusinessDTO lineDTO : lobDTOs) 
      { 
       if(lineDTO.hasGetCoveragesCoverageDTO()) 
       { 
        return true; 
       } 
      } 
     } 

     return false; 
    } 

    @Override 
    public void addLob(ILineOfBusinessDTO lob) { 

     lobDTOs.add(lob); 
    } 

    @Override 
    public Iterator<ILineOfBusinessDTO> getLobIterator() { 

     return lobDTOs.iterator(); 
    } 

    public ICoverageDTO findCoverage(String coverageID) 
    { 
     ICoverageDTO coverageDTO = null; 

     for(ILineOfBusinessDTO lineDTO : lobDTOs) 
     { 
      coverageDTO = lineDTO.findCoverage(coverageID); 

      if(coverageDTO != null) 
      { 
       return coverageDTO; 
      } 
     } 

     return null; 
    } 
    @Override 
    public String toString() 
    { 
     return JSONConversionUtility.convertPolicyDTO(this); 
    } 

    @Override 
    public int hashCode() 
    { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result 
      + ((companyName == null) ? 0 : companyName.hashCode()); 
     result = prime * result + ((lobDTOs == null) ? 0 : lobDTOs.hashCode()); 
     result = prime * result + ((pcInd == null) ? 0 : pcInd.hashCode()); 
     result = prime 
      * result 
      + ((ratingEffectiveDate == null) ? 0 : ratingEffectiveDate 
        .hashCode()); 
     return result; 
    } 

    @Override 
    public boolean equals(Object object) 
    { 
     if(object instanceof PolicyDTO) 
     { 
     return object.toString().equals(this.toString()); 
     } 
     return false; 

    } 
} 
+0

Можете ли вы поделиться кодом для - 1. Как и где вы помещаете вещи в cacheLoader и 2. PolicyDTO class –

+0

Вы переопределили методы 'equals' ** и **' hashCode'? –

+0

Ben Manes - Да, но после отладки я обнаружил, что он никогда не попадает ни в один из методов, только мой toString переопределяет. – unsensibled

ответ

3

Ваш класс PolicyDTO имеет hashCode несовместимым с equals - он нарушает следующие правила:

Если два объекта равны по методу equals(Object), то Назвав hashCode на каждом из двух объектов должен производить тот же целочисленный результат.

Cache использует hashCode (очень как HashMap класс делает), поэтому, когда он видит два ключа с разным hashcodes, это предполагает, что они не равны.

Смежные вопросы