2016-12-08 10 views
0

Я пытаюсь реализовать DCC oracle с eclipselink 2.6 и Oracle 11.2 с помощью драйвера ojdbc6.JPA eclipselink OracleChangeNotificationListener не может получить cacheKey из CacheId

В настоящее время через установку, я получаю правильно уведомления об изменении таблицы через мой ресивер.

Я продлил 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); 
      } 

Я также хранение object_id каждой таблицы (tableNameIdMap) для того, чтобы правильно найти таблицу с каждого уведомления.

Вот метод 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 (...) всегда возвращает нуль

Отладка через, кажется, что identityMaManager должен вернуть cacheKey из identityMap (а WeakHashMap). Соответствующий rowId присутствует, но он не возвращается.

Вот строка в IdentityMapManager # getCacheKeyByIndex

CacheKey cacheKey = map.getCacheKey(indexValues, false); 

Это кажется HashMap в CacheId основывается на значениях хэш-код. Но когда вы смотрите на карте, значение, которое я должен получить, индексируется CacheId, который содержит ROWID. Поэтому, я не могу видеть, как это когда-нибудь работать ...

Я попытался создать экземпляр CacheId, используя вместо этого:

CacheId id = new CacheId(new Object[]{rowChange.getRowid(}); 

он все еще не работает, как хэш-код из ROWID является хэш-код объекта или так кажется.

Поэтому я застрял здесь. Я не понимаю, как это может работать в другом месте.

Любая помощь приветствуется.

FYI, вот отрывок из моей 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" /> 

ответ

0

Найдено ответ:

Проблема была примерно такой же, как this question.

Я действительно настроил базу данных eclipselink.target правильно в сохранении.XML, но это было преодолено конфигурацией пружинной:

<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" />

Теперь, FYI, EclipseLink хранит ROWIDs как строки в ключах CacheId которая осуществляется по адресу: org.eclipse.persistence.platform.database.oracle.Oracle9Platform.getObjectFromResultSet(ResultSet, int, int, AbstractSession)

else if (type == OracleTypes.ROWID) { 
    return resultSet.getString(columnNumber); 
}