sle*_*ske 5 database spring caching jpa eclipselink
我面临一个类似于Invalidating JPA EntityManager session 中描述的问题:
问题:获取陈旧数据
我们正在 SQL 数据库上运行 JPQL 查询,该数据库也由不同的应用程序同时更改。我们使用的是在Tomcat下运行的JSF+Spring+EclipseLink。
执行 JPQL 查询的类是一个单例 Spring bean,并使用注入的EntityManager:
@Component
public class DataRepository{
@PersistenceContext
private EntityManager entityManager;
public List<MyDTO> getStuff(long id) {
String jpqlQuery ="SELECT new MyDTO([...])";
TypedQuery<MyDTO> query = entityManager.createQuery(jpqlQuery,MyDTO.class);
return query.getResultList();
}
[...]
Run Code Online (Sandbox Code Playgroud)
(代码释义)。
问题是这段代码看不到直接对数据库执行的更改。这些更改仅在 Tomcat 实例重新启动时才可见。
我们尝试过的
我们假设此行为是由与 关联的一级缓存引起的EntityManager,如链接问题中所述。我们找到了两个解决方案:
entityManager.clear()调用之前createQuery(这是建议的链接的问题)EntityManagerFactor(使用@PersistenceUnit),然后EntityManager为每个查询创建并关闭一个新的两种解决方案都能满足我们的需求——我们获得了新的数据。
问题:
entityManager.clear()注入的 EntityManager,或者这是否会以某种方式影响也使用注入的 EntityManager 的其他代码(在相同或不同的类中)?EntityManager?我认为这一定是一个相当普遍的问题(因为它发生在多个应用程序共享一个数据库时),所以我认为必须有一个简单的解决方案......
看起来我们已经解决了问题。
其实有两个问题:
在调试问题时,在某些情况下,我们没有为每个查询使用新的 EntityManager。当使用和重用同一个 EntityManager 时,实体一旦被检索到显然永远不会被刷新(除非使用 显式刷新EntityManager.refresh())。这显然是因为一旦一个实体被加载,它就会被存储在 EntityManager 的持久化上下文(又名一级缓存)中。这样做是必要的,因为 JPA 规范要求对同一实体的后续查询返回相同的对象实例。换句话说:只要您使用相同的 EntityManager,除非您明确刷新,否则您将获得陈旧数据。
当我们没有使用新的EntityManager对于每个查询,事情总是很。但是,我们在 EclipseLink 中遇到了一个错误,其中为某些 JPQL 查询(涉及构造函数表达式和 JOIN FETCH)返回陈旧数据。
精简版
如果您想始终从从程序外部修改的数据库中获取新数据,那么
<shared-cache-mode>NONE</shared-cache-mode>在persistence.xml中)创建 newEntityManager是正确的,另一个则不正确(见下文)。
EntityManager#clear()除了单线程系统之外,调用在所有系统中都是非常危险的。
...导致所有托管实体变得分离...
因此,如果一个线程与附加实体一起工作,而“您的”线程清除实体管理器,则会产生严重的副作用。
嗯,很难说。如果在应用程序外部修改的实体数量很少,我将直接使用数据源和 aJdbcTemplate来执行相应的操作。
| 归档时间: |
|
| 查看次数: |
6637 次 |
| 最近记录: |