我正在通过JBoss7.1使用JSF2,JPA2,EJB3开发Web应用程序。 我有一个实体(论坛),其中包含子实体列表(主题)。 当我第一次尝试通过forumId获取主题列表时,数据从DB加载。
List<Topic> topics = entityManager.find(Forum.class, 1).getTopics();
之后我将更多的子实体(主题)添加到论坛,然后我再次尝试通过forumId检索主题列表。坚果我只得到旧的缓存结果。新插入的子记录未从DB加载。
我可以使用以下方法加载子实体(主题):
方法1:在entityManager.find()之前调用entityManager.clear()
方法2:使用
em.createQuery("select t from Topic t where t.forum.forumId=?1", Topic.class);
或
em.createQuery("SELECT t FROM Topic t JOIN t.forum f WHERE f.forumId = ?1", Topic.class);
我知道在NamedQueries上设置QueryHints。但是em.find()方法是在一个超级CrudService中,它被所有DAO(无状态EJB)扩展。所以设置QueryHints对我来说不起作用。
所以我想知道如何让em.find()方法从DB而不是Cache加载数据?
PS:我正在使用扩展持久化上下文类型。
@PersistenceContext(unitName="forum", type=PersistenceContextType.EXTENDED)
protected EntityManager em;
答案 0 :(得分:1)
您可以通过设置控制实体管理器与二级缓存交互的其他属性来指定单个find
操作的行为。
Map<String, Object> props = new HashMap<String, Object>();
props.put("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
entityMgr.find(Forum.class, 1, props).getTopics();
答案 1 :(得分:0)
Forum
和Topic
之间的关系是否可能仅在实体bean的一个方向上添加?如果在主题上设置论坛ID,则还应将此主题添加到Forum
对象,以在第一级缓存中包含一致的数据。您还应该确保没有使用两个不同的实体管理器进行更新和查找。第一级缓存仅按实体管理器保留,另一个em仍可包含旧版本的权利。
可能不相关,但是对于JPA2,你还有一个最小的api来驱逐二级缓存中的实体,这可以在更新后使用:
em.getEntityManagerFactory().getCache().evict(Forum.class, forumId);
答案 2 :(得分:0)
将@Cacheable(false)放在Forum.class中。