我有两个返回User
实体的存储过程调用。人们会查看用户是否通过用户实体中包含的两个参数不进行注册。如果该过程未返回任何用户,则调用第二个存储过程来注册该用户。
我看到的行为是,当按此顺序调用时,第二个存储过程从缓存中返回一个User
实体,几乎所有字段都为null。当我禁用缓存时,它会适当地返回用户对象。似乎第一个调用是缓存用户对象。
在用户登录的正常操作中,我希望它进行缓存,因此我不想禁用第一次调用的缓存。我希望第二个存储过程调用不使用缓存。在做了一些研究和测试几个选项之后,我发现了很少的选择。
这对存储过程不起作用:
proc.setHint("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
java.lang.IllegalArgumentException: Query linkUser, query hint javax.persistence.cache.retrieveMode is not valid for this type of query.
这看起来像是为所有用户驱逐了所有缓存。
em.getEntityManagerFactory().getCache().evict(User.class);
并且these选项可以为实体的所有实例或整个应用程序禁用缓存。
如何使用Eclipselink对单个存储过程调用使用缓存?
Bonus:为什么要缓存返回null用户的存储过程调用?
答案 0 :(得分:1)
JPA规范要求管理从JPA查询(包括本机和存储过程查询)返回的所有实体,这意味着它们也被缓存以维护对象标识。如果您的第一个查询返回一个不完整的实体,那么这也将被缓存。应用程序在使用返回实体的查询时需要小心,这些查询返回完整的数据集或者可能损坏缓存,并且还要注意它们的实体可能从缓存中提取而不是使用查询中的数据重建,并且可能想要返回java对象(构造函数查询)而不是JPA实体。
有关第一部分的答案,请参阅https://stackoverflow.com/a/4471109/496099
答案 1 :(得分:0)
找到一个Java EE Tutorial,显示如何逐出个人缓存。我仍然不确定为什么它甚至被缓存,因为第一个调用永远不会有userId。
Cache cache = em.getEntityManagerFactory().getCache();
cache.evict(User.class, userId);