Java 使用JPA获取旧数据
我使用JPA获取旧数据,即使我禁用了缓存。我猜是因为资源配置为resource_LOCAL,但我不确定Java 使用JPA获取旧数据,java,jpa,eclipselink,Java,Jpa,Eclipselink,我使用JPA获取旧数据,即使我禁用了缓存。我猜是因为资源配置为resource_LOCAL,但我不确定 org.eclipse.persistence.jpa.PersistenceProvider com.myentities.User 获取有关用户的旧信息的我的代码: public List<User> findAll(App app) { getEntityManager().getTransaction().begin();
org.eclipse.persistence.jpa.PersistenceProvider
com.myentities.User
获取有关用户的旧信息的我的代码:
public List<User> findAll(App app) {
getEntityManager().getTransaction().begin();
Query q = getEntityManager().createQuery("SELECT t1 FROM User t1 WHERE t1.app.idApp=:idApp");
q.setParameter("idApp", app.getIdApp());
getEntityManager().flush();
getEntityManager().getTransaction().commit();
List resultList = q.getResultList();
return resultList;
}
有人知道发生了什么吗
更新1
begin、flush和commit方法只是绝望的行为!我知道不需要
我忘了说一些重要的话:我做的测试是直接在数据库控制台上添加一条用户记录,然后尝试通过我的webapp查看它,它没有显示新用户。这就是我提到的“旧数据”,它只显示“旧用户”
我已经尝试将其设置为persistence.xml,结果没有任何差异:
还有别的东西吗…用
<property name="eclipselink.cache.shared.default" value="false"/>
<property name="eclipselink.cache.size.default" value="0"/>
<property name="eclipselink.cache.type.default" value="None"/>
与缓存答案(我将不得不尝试)相反,您可能会遇到引用实体未更新的情况
@Entity
Class Parent
{
@OneToOne(Cascade.ALL)//Or only Merge, whatever you're needs
Child child;
}
@Entity
Class Child
{
Parent parent;
... Values
}
保存子级后,需要更新对父级的引用,以便内存模型(缓存)与数据库匹配。这是相当令人沮丧的,但我处理这个问题的方法是只从父级级联
public void saveChild(Child child)
{
child.getParent().setChild(this); //or DTO Code, whatever
EntityManager.merge(parent); //cascades to the child.
//If you're manually cascading (why?)
//EntityManager.merge(child);
}
如果你设置它,它会级联——我看到的是反向级联(子合并导致级联到父级)不可靠——这是由于我对该主题缺乏了解
简言之,如果显式地处理数据层中的合并,问题就会消失。我不愿意禁用缓存,因为它可能会对大型应用程序产生重大影响,因此,我选择了这条路线。祝您好运,请告诉我们您的方法。已经发布了一些建议,例如确保共享缓存已关闭,以及管理反向引用以使缓存一致。这些是针对可能发生的特定情况,但您没有提供足够的信息来说明真正发生了什么 另一个是特定的,但根据getEntityManager()的使用情况,可能是重用EntityManager实例而不清除它。EntityManager保存对所有托管实体的引用,因为EM需要在后续查询中返回同一实例,并查找用于维护标识的调用 如果尚未执行此操作,则需要清除EntityManager或在某些点获取新的EntityManager,以释放内存和受管实体 首先,不要使用
@Cache(type=CacheType.NONE)
or,
<property name="eclipselink.cache.size.default" value="0"/>
or,
<property name="eclipselink.cache.type.default" value="None"/>
@Cache(type=CacheType.NONE)
或
或
刚刚好
@Cache(shared=false)
or,
<property name="eclipselink.cache.shared.default" value="false"/>
@缓存(shared=false)
或
第二,您的EntityManager来自哪里?您是否为每个请求/事务创建一个新的请求/事务?如果不这样做,则EntityManager中读取的所有内容都将在其(一级)缓存中。您需要调用clear()或创建一个新的。1)优化代码
public List<User> findAll(App app) {
Query q = getEntityManager().createQuery("SELECT t1 FROM User t1 WHERE t1.app.idApp=:idApp"); q.setParameter("idApp", app.getIdApp());
List resultList = q.getResultList();
return resultList;
}
公共列表findAll(App){
Query q=getEntityManager().createQuery(“从用户t1中选择t1,其中t1.app.idApp=:idApp”);q.setParameter(“idApp”,app.getIdApp());
List resultList=q.getResultList();
返回结果列表;
}
2) 从实体类中删除@Cache(type=CacheType.NONE)
3) 无需更改persistence.xmlEntityManager的使用是关键。几个月后,我找到了完美的解决方案:
- 对实体的所有读取使用通用默认实体管理器。这意味着为每个实体创建一个单独的实体管理器
- 为每个实体的每个写入/更新/删除操作创建一个新的实体管理器。对该新实体的事务使用begin/commit。操作完成后关闭实体管理器
- 节点点:提交并关闭writer实体管理器后,清除默认实体管理器(reader one)。这意味着只有在写后才清楚;每次阅读前都不要
clear()
或refresh()
,您可以在链接中找到更多信息。
@Cache(shared=false)
or,
<property name="eclipselink.cache.shared.default" value="false"/>
public List<User> findAll(App app) {
Query q = getEntityManager().createQuery("SELECT t1 FROM User t1 WHERE t1.app.idApp=:idApp"); q.setParameter("idApp", app.getIdApp());
List resultList = q.getResultList();
return resultList;
}