JPA eclipselink OracleChangeNotificationListener 无法从 CacheId 获取 cacheKey
JPA eclipselink OracleChangeNotificationListener cannot get cacheKey from CacheId
我正在尝试使用 eclipselink 2.6 和 Oracle 11.2 以及 ojdbc6 驱动程序实现 oracle DCN。
目前,通过设置,我可以通过我的接收器正确接收 table 更改通知。
我扩展了 org.eclipse.persistence.platform.database.oracle.dcn.OracleChangeNotificationListener
以修复我在项目中注意到的几个问题。
首先我重写了注册方法以正确解包连接:
OracleConnection connection = null;
try {
Connection unwrapConnection = databaseSession.getServerPlatform().unwrapConnection(accessor.getConnection());
try {
if (unwrapConnection.isWrapperFor(OracleConnection.class)) {
connection = unwrapConnection.unwrap(OracleConnection.class);
} else {
// recover, not an oracle connection
connection = (OracleConnection) databaseSession.getServerPlatform().unwrapConnection(accessor.getConnection());
}
} catch (SQLException e) {
e.printStackTrace();
throw DatabaseException.sqlException(e, databaseSession.getAccessor(), databaseSession, false);
}
我还存储每个 table 的 object_id (tableNameIdMap),以便从每个通知中正确找到 table。
这是 DatabaseChangeListener 方法:
public void onDatabaseChangeNotification(final DatabaseChangeEvent changeEvent) {
if (changeEvent.getTableChangeDescription() != null) {
for (TableChangeDescription tableChange : changeEvent.getTableChangeDescription()) {
String tableName = this.tableNameIdMap.get(tableChange.getObjectNumber());
if (tableName != null)
{
ClassDescriptor descriptor = DatabaseChangeNotificationListener.this.descriptorsByTable.get(new DatabaseTable(tableName));
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。
方法 getIdentityMapManager().getCacheKeyByIndex(...) 总是 returns null
通过调试,identityMaManager 似乎应该 return 来自 identityMap(weakHashMap)的 cacheKey。存在对应的 rowId,但未 returned.
这是 IdentityMapManager#getCacheKeyByIndex 中的行
CacheKey cacheKey = map.getCacheKey(indexValues, false);
CacheId 的 hashMap 似乎是基于值哈希码的。但是在查看地图时,我应该接收的值由包含 ROWID 的 CacheId 索引。因此,我看不出这应该如何工作...
我尝试使用以下方法实例化 cacheId:
CacheId id = new CacheId(new Object[]{rowChange.getRowid(});
它仍然不起作用,因为 ROWID 的哈希码似乎是对象的哈希码。
所以我被困在这里了。我不明白这在其他地方如何运作。
感谢任何帮助。
仅供参考,这是我的 persistence.xml
的摘录
<property name="eclipselink.target-database" value="Oracle11" />
<property name="eclipselink.jdbc.native-sql" value="true" />
<property name="eclipselink.jdbc.cache-statements" value="true" />
<property name="eclipselink.query-results-cache" value="true" />
<property name="eclipselink.cache.shared.default" value="true"/>
<property name="eclipselink.refresh" value="true" />
<property name="eclipselink.weaving" value="true"/>
<property name="eclipselink.cache.database-event-listener" value="com.isel.persistence.database.DatabaseChangeNotificationListener" />
找到答案:
问题与 this question 大致相同。
我确实在 persistence.xml 中正确设置了 eclipselink.target 数据库,但它被 spring 配置覆盖了:
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.eclipse.persistence.platform.database.OraclePlatform" />
</bean>
然后我改为 <property name="databasePlatform" value="org.eclipse.persistence.platform.database.oracle.Oracle11Platform" />
现在,仅供参考,eclipselink 将 rowId 存储为 CacheId 键中的字符串,这是在以下位置完成的:org.eclipse.persistence.platform.database.oracle.Oracle9Platform.getObjectFromResultSet(ResultSet, int, int, AbstractSession)
else if (type == OracleTypes.ROWID) {
return resultSet.getString(columnNumber);
}
我正在尝试使用 eclipselink 2.6 和 Oracle 11.2 以及 ojdbc6 驱动程序实现 oracle DCN。
目前,通过设置,我可以通过我的接收器正确接收 table 更改通知。
我扩展了 org.eclipse.persistence.platform.database.oracle.dcn.OracleChangeNotificationListener
以修复我在项目中注意到的几个问题。
首先我重写了注册方法以正确解包连接:
OracleConnection connection = null;
try {
Connection unwrapConnection = databaseSession.getServerPlatform().unwrapConnection(accessor.getConnection());
try {
if (unwrapConnection.isWrapperFor(OracleConnection.class)) {
connection = unwrapConnection.unwrap(OracleConnection.class);
} else {
// recover, not an oracle connection
connection = (OracleConnection) databaseSession.getServerPlatform().unwrapConnection(accessor.getConnection());
}
} catch (SQLException e) {
e.printStackTrace();
throw DatabaseException.sqlException(e, databaseSession.getAccessor(), databaseSession, false);
}
我还存储每个 table 的 object_id (tableNameIdMap),以便从每个通知中正确找到 table。
这是 DatabaseChangeListener 方法:
public void onDatabaseChangeNotification(final DatabaseChangeEvent changeEvent) {
if (changeEvent.getTableChangeDescription() != null) {
for (TableChangeDescription tableChange : changeEvent.getTableChangeDescription()) {
String tableName = this.tableNameIdMap.get(tableChange.getObjectNumber());
if (tableName != null)
{
ClassDescriptor descriptor = DatabaseChangeNotificationListener.this.descriptorsByTable.get(new DatabaseTable(tableName));
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。
方法 getIdentityMapManager().getCacheKeyByIndex(...) 总是 returns null
通过调试,identityMaManager 似乎应该 return 来自 identityMap(weakHashMap)的 cacheKey。存在对应的 rowId,但未 returned.
这是 IdentityMapManager#getCacheKeyByIndex 中的行
CacheKey cacheKey = map.getCacheKey(indexValues, false);
CacheId 的 hashMap 似乎是基于值哈希码的。但是在查看地图时,我应该接收的值由包含 ROWID 的 CacheId 索引。因此,我看不出这应该如何工作...
我尝试使用以下方法实例化 cacheId:
CacheId id = new CacheId(new Object[]{rowChange.getRowid(});
它仍然不起作用,因为 ROWID 的哈希码似乎是对象的哈希码。
所以我被困在这里了。我不明白这在其他地方如何运作。
感谢任何帮助。
仅供参考,这是我的 persistence.xml
的摘录 <property name="eclipselink.target-database" value="Oracle11" />
<property name="eclipselink.jdbc.native-sql" value="true" />
<property name="eclipselink.jdbc.cache-statements" value="true" />
<property name="eclipselink.query-results-cache" value="true" />
<property name="eclipselink.cache.shared.default" value="true"/>
<property name="eclipselink.refresh" value="true" />
<property name="eclipselink.weaving" value="true"/>
<property name="eclipselink.cache.database-event-listener" value="com.isel.persistence.database.DatabaseChangeNotificationListener" />
找到答案:
问题与 this question 大致相同。
我确实在 persistence.xml 中正确设置了 eclipselink.target 数据库,但它被 spring 配置覆盖了:
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.eclipse.persistence.platform.database.OraclePlatform" />
</bean>
然后我改为 <property name="databasePlatform" value="org.eclipse.persistence.platform.database.oracle.Oracle11Platform" />
现在,仅供参考,eclipselink 将 rowId 存储为 CacheId 键中的字符串,这是在以下位置完成的:org.eclipse.persistence.platform.database.oracle.Oracle9Platform.getObjectFromResultSet(ResultSet, int, int, AbstractSession)
else if (type == OracleTypes.ROWID) {
return resultSet.getString(columnNumber);
}