2

我正在通过 JBoss7.1 使用 JSF2、JPA2、EJB3 开发一个 Web 应用程序。我有一个实体(论坛),其中包含子实体(主题)的列表。当我第一次尝试通过 forumId 获取主题列表时,数据是从数据库加载的。

List<Topic> topics = entityManager.find(Forum.class, 1).getTopics();

之后,我向论坛添加了更多子实体(主题),然后我再次尝试按 forumId 检索主题列表。坚果我只得到旧的缓存结果。新插入的子记录未从数据库加载。

我可以使用以下方法加载子实体(主题):

方法一:在 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() 方法从数据库而不是缓存加载数据?

PS:我使用的是扩展持久性上下文类型。

@PersistenceContext(unitName="forum", type=PersistenceContextType.EXTENDED)
protected EntityManager em;
4

3 回答 3

2

find您可以通过设置控制实体管理器与二级缓存交互的附加属性来指定单个操作的行为。

Map<String, Object> props = new HashMap<String, Object>();
props.put("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
entityMgr.find(Forum.class, 1, props).getTopics();
于 2012-05-02T04:28:47.917 回答
0

Forum是否有可能和之间的关系Topic仅在您的实体 bean 中添加到一个方向?如果您在主题上设置了论坛 id,您还应该将此主题添加到Forum对象中,以便在一级缓存中具有一致的数据。您还应该确保您没有使用两个不同的实体管理器进行更新和查找。第一级缓存仅保留每个实体管理器,另一个 em 仍然可以包含旧版本的实体。

可能不相关,但是使用 JPA2,您还可以使用最小的 api 从二级缓存中驱逐实体,可以在更新后使用:

em.getEntityManagerFactory().getCache().evict(Forum.class, forumId);
于 2012-05-02T07:57:33.617 回答
0

将 @Cacheable(false) 放在 Forum.class 中。

于 2014-07-18T19:28:09.213 回答