我有兩個使用Eclipselink 2.4.2的Java 1.7應用程序用於持久性。一個應用程序是在Glassfish 3.1.2.2中運行的JEE應用程序,另一個是Java SE應用程序。這些應用程序讀取和寫入相同的數據,因此存在陳舊的JPA高速緩存條目的可能性。我試圖用Oracle DCN來解決陳舊的緩存問題。JPA Eclipselink數據庫更改通知不會使緩存項無效
如上面的鏈接描述我已經配置我的persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="drms-persistence-unit" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/DRMS</jta-data-source>
<properties>
<property name="eclipselink.cache.database-event-listener"
value="org.eclipse.persistence.platform.database.oracle.dcn.OracleChangeNotificationListener"/>
<property name="eclipselink.target-server" value="SunAS9"/>
<property name="eclipselink.target-database" value="Oracle"/>
<property name="eclipselink.logging.level" value="INFO"/>
<property name="eclipselink.logging.parameters" value="true"/>
<property name="eclipselink.jdbc.native-sql" value="true"/>
<property name="eclipselink.jdbc.batch-writing" value="Oracle-JDBC"/>
<property name="eclipselink.jdbc.cache-statements" value="true"/>
<property name="eclipselink.jdbc.cache-statements.size" value="200"/>
</properties>
</persistence-unit>
</persistence>
然而,我仍然獲得陳舊緩存條目。如果一個應用程序對數據庫提交了更改,則第二個應用程序仍然會看到其舊的緩存條目,而不是新的更改。使用調試器,我確認OracleChangeNotificationListener正在接收數據庫事件,但似乎從未使緩存中的任何內容無效。
的EclipseLink的OracleChangeNotificationListener註冊以下監聽器接收Oracle數據庫更改事件:
public void onDatabaseChangeNotification(DatabaseChangeEvent changeEvent) {
databaseSession.log(SessionLog.FINEST, SessionLog.CONNECTION, "dcn_change_event", changeEvent);
if (changeEvent.getTableChangeDescription() != null) {
for (TableChangeDescription tableChange : changeEvent.getTableChangeDescription()) {
ClassDescriptor descriptor = OracleChangeNotificationListener.this.descriptorsByTable.get(new DatabaseTable(tableChange.getTableName()));
if (descriptor != null) {
CacheIndex index = descriptor.getCachePolicy().getCacheIndex(fields);
for (RowChangeDescription rowChange : tableChange.getRowChangeDescription()) {
CacheId id = new CacheId(new Object[]{rowChange.getRowid().stringValue()});
CacheKey key = databaseSession.getIdentityMapAccessorInstance().getIdentityMapManager().getCacheKeyByIndex(
index, id, true, descriptor);
if (key != null) {
if ((key.getTransactionId() == null) || !key.getTransactionId().equals(changeEvent.getTransactionId(true))) {
databaseSession.log(SessionLog.FINEST, SessionLog.CONNECTION, "dcn_invalidate", key.getKey(), descriptor.getJavaClass().getName());
key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
}
}
}
}
}
}
}
這個監聽器被調用我們隨時進行更改數據庫。但是,查找到的CacheKey值始終爲空,因此失效代碼永遠不會運行。
如果我檢查調試器中的IdentityMapManager對象,我可以看到預期的實體在緩存中。然而,CacheId查找每次都失敗(返回null)。
任何幫助表示讚賞。
您能否提供更多信息,例如您如何驗證實體過時?失效適用於二級緩存,但不適用於EntityManager緩存,因爲它與工作單元相似。例如,如果保留和重用EM,請確保在邏輯點呼叫清除 – Chris
我在一個應用程序中對實體進行更改,並驗證它是否已提交到數據庫。然後我在其他應用程序中檢索同一個實體。第二個應用程序實際上並未命中數據庫,顯示的數據是實體的舊的更新前值。 – Jeff