2017-02-21 56 views
0

我无法通过ehcache获取数据列表。Spring Cache - 无法获取数据列表

的servlet上下文:

<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和Spring的水平问题。

对于Ehcache,您不应该有比堆大小更小的磁盘大小。一段时间以来,ehcache中的分层模型意味着所有条目都必须位于磁盘层中,因此使用此设置可以有效地将堆大小限制为磁盘大小。

在Spring方面,您使用单个缓存来保存不同的内容,但它们会发生冲突。

  • @CachePut将存储在单个类别,映射到long键符合你@CacheablefindById做什么。
  • 但是,这将与冲突,也使用long作为关键,但高速缓存List<Category>。因此,userIdcategoryId之间的任何冲突都可能导致客户端代码中发生意外的类别转换异常 - 期望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