【问题标题】:JPA Eclipselink Database Change Notification does not invalidate cache entryJPA Eclipselink 数据库更改通知不会使缓存条目无效
【发布时间】:2014-04-04 15:22:51
【问题描述】:

我有两个使用 Eclipselink 2.4.2 进行持久性的 Java 1.7 应用程序。一个应用程序是在 Glassfish 3.1.2.2 中运行的 JEE 应用程序,另一个是 Java SE 应用程序。这些应用程序读取和写入相同的数据,因此存在陈旧的 JPA 缓存条目的可能性。我正在尝试使用Oracle DCN 来解决过期缓存问题。

我已经按照上面链接中的描述配置了我的 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,请确保在逻辑点调用 clear
  • 我对一个应用程序中的实体进行了更改,并验证它是否已提交到数据库。然后我在其他应用程序中检索相同的实体。第二个应用程序实际上并没有访问数据库,并且显示的数据是实体的旧的、更新前的值。

标签: java oracle caching jpa eclipselink


【解决方案1】:

问题已解决。这是由persistence.xml 中“eclipselink.target-database”属性的值引起的。我们将其设置为“Oracle”,并将其更改为“Oracle11”解决了这个问题。显然,直到 Oracle 版本 11 才添加 DCN 功能,并且 Eclipselink 的行为取决于该值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-29
    • 1970-01-01
    • 2014-01-22
    • 2012-11-17
    • 2011-11-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多