2017-02-21 40 views
0

Я не могу получить список данных через ehcache.Spring Cache - невозможно получить список данных

сервлетов контекст:

<cache:annotation-driven /> 

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" 
    p:cacheManager-ref="ehcache"/> 

<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" 
     p:configLocation="/WEB-INF/spring/appServlet/ehcache.xml" p:shared="true" /> 

ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:noNamespaceSchemaLocation="ehcache.xsd" 
    updateCheck="true" monitoring="autodetect" dynamicConfig="true"> 
<cache name="category" 
     maxEntriesLocalHeap="5000" 
     maxEntriesLocalDisk="1000" 
     eternal="false" 
     diskSpoolBufferSizeMB="20" 
     timeToIdleSeconds="200" 
     timeToLiveSeconds="500" 
     memoryStoreEvictionPolicy="LFU" 
     transactionalMode="off"> 
    <persistence strategy="localTempSwap"/> 
</cache> 

У меня есть сущность Категория:

@Entity 
@Table(name = "categories") 
public class Category implements Serializable { 
@Id 
@GeneratedValue(strategy = GenerationType.IDENTITY) 
private long categoryId; 

@Column(nullable = false) 
private String name; 

private long level; 
private long parentId; 

@ManyToMany(fetch = FetchType.EAGER, mappedBy = "categories") 
private Set<Post> posts; 

@ManyToOne(fetch = FetchType.LAZY) 
@JoinColumn(name = "userId") 
private User user; 

public Category() { 
} 

public Category(User user, long level, String name, long parentId) { 
this.user = user; 
this.level = level; 
this.name = name; 
this.parentId = parentId; 
} 
// ... 
} 

Затем я пытаюсь кэшировать этот методы:

@Service 
@Repository 
@Transactional 
public class CategoryServiceImpl implements CategoryService { 
@Resource 
private CategoryRepository categoryRepository; 

@Override 
@CachePut(value = "category", key = "#category.categoryId") 
public Category add(Category category) { 
    return categoryRepository.saveAndFlush(category); 
} 

@Override 
@Cacheable("category") 
public Category findById(long id) { 
    return categoryRepository.findOne(id); 
} 

@Override 
@Cacheable("category") 
public Category findByParentIdThroughCategoryId(long prntId, long userId) { 
    return categoryRepository.findByParentIdThroughCategoryId(prntId, userId); 
} 

@Override 
@Cacheable("category") 
public List<Category> findByParentId(long prntId, long userId) { 
    return categoryRepository.findByParentId(prntId, userId); 
} 

@Override 
@Cacheable("category") 
public List<Category> findAll(long userId) { 
    return categoryRepository.findAll(userId); 
} 

@Override 
@CacheEvict("category") 
public void remove(long id) { 
    categoryRepository.delete(id); 
} 
} 

При добавлении категории, а затем попытаться принести его, чтобы просмотреть все категории, которые имеют пользователь findByParentId/FindAll, она возвращает пустой список

[]

Он имеет что-то делать, например, я кэширую категории, а затем беру список категорий, я попытался получить категорию с ID 11 - findById и нашел:

[email protected]

+0

Прежде всего убедитесь, что 'categoryRepository.findAll (userId)' и 'categoryRepository.findByParentId (prntId, userId)' возвращают что-то при вызове напрямую. Еще один несвязанный комментарий состоит в том, что ваш класс 'CategoryServiceImpl' не должен быть аннотирован с помощью' @ Repository', только ваш 'CategoryRepository' должен. – artemisian

+0

Эти методы возвращают значения. Если это не удалось, я бы не стал кэшировать. Хм ... Я всегда делаю это @Repository и все работает. Спасибо, я переместил '@ Repository' в' CategoryRepository'. – shank

+0

@artemisian Я также пытаюсь сделать это: '@Cacheable (cacheNames =" category ", key =" #userId ")', но он ничего не изменил – mrchebik

ответ

2

Ваша установка имеет ряд проблем как на уровне Ehcache и пружинные.

Для Ehcache вы не должны иметь меньший размер диска, чем размер кучи. Некоторое время модель уровня в ehcache означает, что все записи должны быть в уровне диска, поэтому вы эффективно искусственно ограничиваете размер кучи размером диска с помощью этой настройки.

С другой стороны, вы используете один кэш для хранения разных вещей, но они конфликтуют.

  • Ваш @CachePut будет хранить одну категорию, отображенный на long ключ, который соответствует тому, что ваш @Cacheable на findById делает.
  • Однако это будет конфликтовать с @Cacheable на findAll, который также использует long в качестве ключа, но кэширует List<Category>. Таким образом, любое столкновение между userId и categoryId может привести к неожиданным исключениям класса в клиентском коде - ожидается, что List получит Category или наоборот.
  • Наконец, у вас есть два метода, которые принимают два параметра long в качестве параметров, но выполняют другой служебный вызов, пока кеширование настроено одинаково. И этот служебный вызов снова возвращает непересекающиеся типы - List<Category> и Category. Это вызовет аналогичные проблемы, как в предыдущем пункте.

Кроме того, у меня создалось впечатление, что вы ожидаете, что кэширование с одним входом магически добавит записи в соответствующие списки. Этого не произойдет.

Я настоятельно рекомендую проанализировать ваши потребности в кешировании и лучше понять, что предлагает абстракция Spring ... и что это не так.

+0

Благодарю вас, я удалил некоторые кешируемые элементы и оставил 2: 'findByParentId' и' findAll'. Итак, я добавил ключи: ''findByParrentId-' + #category. родитель Id + ',' + # category.user.userId "и' 'findAll-' + # category.user.userId'. Как вы говорите, я получаю исключение из 'ClassCastException: ru.mrchebik.model.Category нельзя отнести к java.util.List'. Можете ли вы мне помочь, как я могу это исправить? – shank

+0

Без трассировки стека, трудно сказать. Однако может потребоваться отдельный вопрос. –

+0

трассировка стека: http://pastebin.com/35A14ZW9 – shank

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