Search in sources :

Example 1 with CacheIndex

use of org.eclipse.persistence.descriptors.CacheIndex in project eclipselink by eclipse-ee4j.

the class CacheIndexMetadata method process.

/**
 * INTERNAL:
 * Process the index metadata
 */
public void process(MetadataDescriptor descriptor, String defaultColumnName) {
    CacheIndex index = new CacheIndex();
    if (m_columnNames.isEmpty() && (defaultColumnName != null)) {
        index.addField(getField(defaultColumnName));
    } else {
        for (String column : m_columnNames) {
            index.addField(getField(column));
        }
    }
    if (this.updateable != null) {
        index.setIsUpdateable(this.updateable);
    }
    descriptor.getClassDescriptor().getCachePolicy().addCacheIndex(index);
}
Also used : CacheIndex(org.eclipse.persistence.descriptors.CacheIndex)

Example 2 with CacheIndex

use of org.eclipse.persistence.descriptors.CacheIndex in project eclipselink by eclipse-ee4j.

the class OracleChangeNotificationListener method register.

/**
 * INTERNAL:
 * Register the event listener with the database.
 */
@Override
public void register(Session session) {
    final AbstractSession databaseSession = (AbstractSession) session;
    // Determine which tables should be tracked for change events.
    this.descriptorsByTable = new HashMap<DatabaseTable, ClassDescriptor>();
    for (ClassDescriptor descriptor : session.getDescriptors().values()) {
        if (!descriptor.getTables().isEmpty()) {
            if ((descriptor.getCachePolicy().getDatabaseChangeNotificationType() != null) && (descriptor.getCachePolicy().getDatabaseChangeNotificationType() != DatabaseChangeNotificationType.NONE)) {
                this.descriptorsByTable.put(descriptor.getTables().get(0), descriptor);
            }
        }
    }
    Accessor accessor = databaseSession.getAccessor();
    accessor.incrementCallCount(databaseSession);
    try {
        OracleConnection connection = (OracleConnection) databaseSession.getServerPlatform().unwrapConnection(accessor.getConnection());
        databaseSession.log(SessionLog.FINEST, SessionLog.CONNECTION, "dcn_registering");
        Properties properties = new Properties();
        properties.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS, "true");
        properties.setProperty(OracleConnection.DCN_IGNORE_INSERTOP, "true");
        try {
            // Register with the database change notification, the connection is not relevant, the events occur after the connection is closed,
            // and a different connection can be used to unregister the event listener.
            this.register = connection.registerDatabaseChangeNotification(properties);
            final List<DatabaseField> fields = new ArrayList<DatabaseField>();
            fields.add(new DatabaseField(ROWID));
            this.register.addListener(new DatabaseChangeListener() {

                @Override
                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);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            });
            // Register each table for database events, this is done by executing a select from the table.
            for (DatabaseTable table : this.descriptorsByTable.keySet()) {
                OracleStatement statement = (OracleStatement) connection.createStatement();
                statement.setDatabaseChangeRegistration(this.register);
                try {
                    statement.executeQuery("SELECT ROWID FROM " + table.getQualifiedName()).close();
                    databaseSession.log(SessionLog.FINEST, SessionLog.CONNECTION, "dcn_register_table", table.getQualifiedName());
                } catch (Exception failed) {
                    // This will fail if the table does not exist,
                    // just log the error to allow table creation to work.
                    databaseSession.logThrowable(SessionLog.WARNING, SessionLog.SQL, failed);
                } finally {
                    statement.close();
                }
            }
        } catch (SQLException exception) {
            throw DatabaseException.sqlException(exception, databaseSession.getAccessor(), databaseSession, false);
        }
    } finally {
        accessor.decrementCallCount();
    }
}
Also used : OracleStatement(oracle.jdbc.OracleStatement) ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) CacheIndex(org.eclipse.persistence.descriptors.CacheIndex) SQLException(java.sql.SQLException) ArrayList(java.util.ArrayList) RowChangeDescription(oracle.jdbc.dcn.RowChangeDescription) OracleConnection(oracle.jdbc.OracleConnection) Properties(java.util.Properties) Accessor(org.eclipse.persistence.internal.databaseaccess.Accessor) SQLException(java.sql.SQLException) DatabaseException(org.eclipse.persistence.exceptions.DatabaseException) DatabaseChangeEvent(oracle.jdbc.dcn.DatabaseChangeEvent) TableChangeDescription(oracle.jdbc.dcn.TableChangeDescription) DatabaseChangeListener(oracle.jdbc.dcn.DatabaseChangeListener) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) DatabaseTable(org.eclipse.persistence.internal.helper.DatabaseTable) CacheKey(org.eclipse.persistence.internal.identitymaps.CacheKey) AbstractSession(org.eclipse.persistence.internal.sessions.AbstractSession)

Example 3 with CacheIndex

use of org.eclipse.persistence.descriptors.CacheIndex in project eclipselink by eclipse-ee4j.

the class OracleChangeNotificationListener method initialize.

/**
 * Initialize the descriptor to receive database change events.
 * This is called when the descriptor is initialized.
 */
@Override
public void initialize(final ClassDescriptor descriptor, AbstractSession session) {
    if (descriptor.getOptimisticLockingPolicy() == null) {
        boolean requiresLocking = descriptor.hasMultipleTables();
        for (DatabaseMapping mapping : descriptor.getMappings()) {
            if (mapping.isCollectionMapping()) {
                requiresLocking = true;
            }
        }
        if (requiresLocking) {
            session.log(SessionLog.WARNING, SessionLog.METADATA, "locking_required_for_database_change_notification", descriptor.getJavaClass());
        }
    }
    final DatabaseField rowId = descriptor.buildField(new DatabaseField(ROWID));
    final List<DatabaseField> fields = new ArrayList<DatabaseField>();
    fields.add(rowId);
    // May already have the index if has inheritance.
    CacheIndex existingIndex = descriptor.getCachePolicy().getCacheIndex(fields);
    if (existingIndex == null) {
        if (descriptor.isChildDescriptor()) {
            existingIndex = descriptor.getInheritancePolicy().getRootParentDescriptor().getCachePolicy().getCacheIndex(fields);
        }
        if (existingIndex == null) {
            existingIndex = new CacheIndex(fields);
            existingIndex.setIsUpdateable(false);
            existingIndex.setIsInsertable(false);
        }
        descriptor.getCachePolicy().addCacheIndex(existingIndex);
    }
    final CacheIndex index = existingIndex;
    rowId.setInsertable(false);
    rowId.setUpdatable(false);
    rowId.setCreatable(false);
    descriptor.getFields().add(rowId);
    descriptor.getAllFields().add(rowId);
    final ValueReadQuery rowIdQuery = new ValueReadQuery();
    rowIdQuery.setName(ROWID);
    SQLSelectStatement sqlStatement = new SQLSelectStatement();
    sqlStatement.setWhereClause(descriptor.getObjectBuilder().getPrimaryKeyExpression());
    sqlStatement.addField(rowId);
    sqlStatement.addTable(descriptor.getTables().get(0));
    rowIdQuery.setSQLStatement(sqlStatement);
    sqlStatement.normalize(session, null);
    descriptor.getEventManager().addListener(new DescriptorEventAdapter() {

        @Override
        public void postMerge(DescriptorEvent event) {
            if ((event.getChangeSet() != null) && event.getChangeSet().hasChanges()) {
                Object id = event.getChangeSet().getId();
                CacheKey cacheKey = event.getChangeSet().getActiveCacheKey();
                if (cacheKey == null) {
                    cacheKey = event.getSession().getParent().getIdentityMapAccessorInstance().getIdentityMapManager().getCacheKeyForObject(id, descriptor.getJavaClass(), descriptor, false);
                }
                cacheKey.setTransactionId(event.getSession().getProperty(ORA_TRANSACTION_ID));
                if (event.getChangeSet().isNew()) {
                    AbstractRecord row = descriptor.getObjectBuilder().buildRowFromPrimaryKeyValues(id, event.getSession());
                    Object rowid = event.getSession().executeQuery(rowIdQuery, row);
                    CacheId indexValue = new CacheId(new Object[] { rowid });
                    event.getSession().getParent().getIdentityMapAccessorInstance().getIdentityMapManager().putCacheKeyByIndex(index, indexValue, cacheKey, descriptor);
                }
            }
        }

        @Override
        public void postUpdate(DescriptorEvent event) {
            Object txId = event.getSession().getProperty(ORA_TRANSACTION_ID);
            if (txId == null) {
                txId = event.getSession().executeQuery(transactionIdQuery);
                event.getSession().setProperty(ORA_TRANSACTION_ID, txId);
            }
        }
    });
}
Also used : CacheIndex(org.eclipse.persistence.descriptors.CacheIndex) ValueReadQuery(org.eclipse.persistence.queries.ValueReadQuery) ArrayList(java.util.ArrayList) AbstractRecord(org.eclipse.persistence.internal.sessions.AbstractRecord) DatabaseMapping(org.eclipse.persistence.mappings.DatabaseMapping) DescriptorEvent(org.eclipse.persistence.descriptors.DescriptorEvent) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) DatabaseField(org.eclipse.persistence.internal.helper.DatabaseField) DescriptorEventAdapter(org.eclipse.persistence.descriptors.DescriptorEventAdapter) SQLSelectStatement(org.eclipse.persistence.internal.expressions.SQLSelectStatement) CacheKey(org.eclipse.persistence.internal.identitymaps.CacheKey)

Aggregations

CacheIndex (org.eclipse.persistence.descriptors.CacheIndex)3 ArrayList (java.util.ArrayList)2 DatabaseField (org.eclipse.persistence.internal.helper.DatabaseField)2 CacheId (org.eclipse.persistence.internal.identitymaps.CacheId)2 CacheKey (org.eclipse.persistence.internal.identitymaps.CacheKey)2 SQLException (java.sql.SQLException)1 Properties (java.util.Properties)1 OracleConnection (oracle.jdbc.OracleConnection)1 OracleStatement (oracle.jdbc.OracleStatement)1 DatabaseChangeEvent (oracle.jdbc.dcn.DatabaseChangeEvent)1 DatabaseChangeListener (oracle.jdbc.dcn.DatabaseChangeListener)1 RowChangeDescription (oracle.jdbc.dcn.RowChangeDescription)1 TableChangeDescription (oracle.jdbc.dcn.TableChangeDescription)1 ClassDescriptor (org.eclipse.persistence.descriptors.ClassDescriptor)1 DescriptorEvent (org.eclipse.persistence.descriptors.DescriptorEvent)1 DescriptorEventAdapter (org.eclipse.persistence.descriptors.DescriptorEventAdapter)1 DatabaseException (org.eclipse.persistence.exceptions.DatabaseException)1 Accessor (org.eclipse.persistence.internal.databaseaccess.Accessor)1 SQLSelectStatement (org.eclipse.persistence.internal.expressions.SQLSelectStatement)1 DatabaseTable (org.eclipse.persistence.internal.helper.DatabaseTable)1