在JPA中禁用caching(eclipselink)
我想使用JPA(eclipselink)从我的数据库中获取数据。 数据库被其他许多来源所改变,因此我想回到执行的每个查找的数据库。 我已经阅读了许多关于禁用caching的post,但这似乎并没有工作。 有任何想法吗?
我试图执行下面的代码:
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("default"); EntityManager em = entityManagerFactory.createEntityManager(); MyLocation one = em.createNamedQuery("MyLocation.findMyLoc").getResultList().get(0); MyLocation two = em.createNamedQuery("MyLocation.findMyLoc").getResultList().get(0); System.out.println(one==two);
一个==两个是真的,而我希望它是假的。
我已经尝试添加每个/所有以下到我的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"/>
我也尝试添加@Cache注释到实体本身:
@Cache( type=CacheType.NONE, // Cache nothing expiry=0, alwaysRefresh=true )
我误解了什么?
这种行为是正确的,否则如果你改变对象一和对象二不同的值,你将会遇到问题时,坚持他们。 发生什么事是调用加载对象两个更新在第一次调用加载的实体。 他们必须指向同一个对象,因为他们是同一个对象。 这确保了不能写入脏数据。
如果你在两个调用之间调用em.clear(),实体之一应该分离,你的检查将返回false。 然而,没有必要这样做,日食链接实际上更新您的数据到最新的,我猜是你想要的,因为它经常改变。
在附注中,如果您希望使用JPA来更新这些数据,您将需要获得对实体的悲观locking ,以便底层数据无法在数据库中更改。
你将需要禁用查询caching以及你的caching选项只是从播放中删除对象caching而不是查询caching,这就是为什么你没有得到新的结果:
在你的代码中:
em.createNamedQuery("MyLocation.findMyLoc").setHint(QueryHints.CACHE_USAGE, CacheUsage.DoNotCheckCache).getResultList().get(0);
或者在persistence.xml中:
<property name="eclipselink.query-results-cache" value="false"/>
final Query readQuery = this.entityManager.createQuery(selectQuery); readQuery.setParameter(paramA, valueA); // Update the JPA session cache with objects that the query returns. // Hence the entity objects in the returned collection always updated. readQuery.setHint(QueryHints.REFRESH, HintValues.TRUE); entityList = readQuery.getResultList();
这对我有用。
看到,
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching
对于同一个EntityManager,JPA总是要求一个==两个,所以这是正确的,不pipe你的caching选项(这是L1caching,还是事务caching,它强制你的事务隔离和维护对象的身份)。
要强制查询刷新(并恢复所做的任何更改),可以使用查询提示“eclipselink.refresh”=“true”。 或者可能更好,为每个查询/请求使用一个新的EntityManager,或在您的EntityManager上调用clear()。
<property name="eclipselink.cache.shared.default" value="false"/>
禁用共享caching(L2caching)是正确的方法。 请删除所有其他设置,因为它们不正确,可能会导致问题。
EclipseLink默认情况下不会保留查询caching,所以这些设置不会有任何影响。 CacheUsage也是不正确的,不要使用这个(它用于内存查询)。
如果您希望禁用caching而无需获取供应商特定的信息,则可以使用以下注释来注释域对象:
@Cacheable(false)
这里是一个例子:
@Entity @Table(name="SomeEntity") @Cacheable(false) public class SomeEntity { // ... }
如果手动修改对象的属性,例如MyLocation。 上面的技巧( CACHE_USAGE=CacheUsage.DoNotCheckCache
,或CACHE_USAGE=CacheUsage.DoNotCheckCache
eclipselink.query-results-cache=false
)似乎不工作,因为我试过。
所以我试图设置eclipselink.refresh
另一个提示为true
。 那么它的工作。 我的意思是手动更改的属性被检索。
所以,据我了解,上述技巧只能确保它得到正确的对象。 但是,如果对象已经被caching了,eclipselink只是返回它们而不检查对象内容的新鲜度。 只有当提示eclipselink.refresh
设置为true
,这些对象才会刷新以反映最新的属性值。
我知道这个post可能很老,但是我正在为需要帮助的人写信。 我有这个问题,最后我解决了这个代码:
em.createNamedQuery("findAll").setHint(QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.BYPASS).getResultList();
它工作得很好。 我们可以在BYPASS枚举的javadoc中看到,它写道:
绕过caching:直接从数据库中获取数据。
我应该注意到,我使用Weblogic 12c和TopLink作为JPA实现。