Search in sources :

Example 16 with CacheId

use of org.eclipse.persistence.internal.identitymaps.CacheId in project eclipselink by eclipse-ee4j.

the class MappedKeyMapContainerPolicy method valueFromPKList.

/**
 * INTERNAL:
 * This method is used to load a relationship from a list of PKs. This list
 * may be available if the relationship has been cached.
 */
@Override
public Object valueFromPKList(Object[] pks, AbstractRecord foreignKeys, ForeignReferenceMapping mapping, AbstractSession session) {
    int mapSize = pks.length / 2;
    Object result = containerInstance(mapSize);
    Object[] keys = new Object[mapSize];
    Object[] values = new Object[mapSize];
    for (int index = 0; index < pks.length; ++index) {
        keys[index / 2] = pks[index];
        ++index;
        values[index / 2] = pks[index];
    }
    List<Object> keyObjects = keyMapping.createMapComponentsFromSerializableKeyInfo(keys, session);
    if (((DatabaseMapping) valueMapping).isElementCollectionMapping()) {
        for (int i = 0; i < mapSize; i++) {
            addInto(keyObjects.get(i), values[i], result, session);
        }
    } else {
        Map<Object, Object> fromCache = session.getIdentityMapAccessorInstance().getAllFromIdentityMapWithEntityPK(values, elementDescriptor);
        List foreignKeyValues = new ArrayList(pks.length - fromCache.size());
        CacheKeyType cacheKeyType = this.elementDescriptor.getCachePolicy().getCacheKeyType();
        for (int index = 0; index < mapSize; ++index) {
            Object pk = values[index];
            if (!fromCache.containsKey(pk)) {
                if (cacheKeyType == CacheKeyType.CACHE_ID) {
                    foreignKeyValues.add(Arrays.asList(((CacheId) pk).getPrimaryKey()));
                } else {
                    foreignKeyValues.add(pk);
                }
            }
        }
        if (!foreignKeyValues.isEmpty()) {
            if (foreignKeyValues.size() == pks.length) {
                // need to find all of the entities so just perform a FK search
                return session.executeQuery(mapping.getSelectionQuery(), foreignKeys);
            }
            ReadAllQuery query = new ReadAllQuery(elementDescriptor.getJavaClass());
            query.setIsExecutionClone(true);
            query.addArgument(ForeignReferenceMapping.QUERY_BATCH_PARAMETER);
            query.setSession(session);
            query.setSelectionCriteria(elementDescriptor.buildBatchCriteriaByPK(query.getExpressionBuilder(), query));
            int pkCount = foreignKeyValues.size();
            Collection<Object> temp = new ArrayList<>();
            List arguments = new ArrayList();
            arguments.add(foreignKeyValues);
            if (pkCount > 1000) {
                int index = 0;
                while (index + 1000 < pkCount) {
                    // some databases only support ins < 1000 entries
                    List pkList = new ArrayList();
                    pkList.addAll(foreignKeyValues.subList(index, index + 1000));
                    arguments.set(0, pkList);
                    query.setArgumentValues(arguments);
                    temp.addAll((Collection<Object>) session.executeQuery(query));
                    index += 1000;
                }
                foreignKeyValues = foreignKeyValues.subList(index, pkCount);
            }
            arguments.set(0, foreignKeyValues);
            query.setArgumentValues(arguments);
            // need to put the translation row here or it will be replaced later.
            temp.addAll((Collection<Object>) session.executeQuery(query));
            if (temp.size() < pkCount) {
                // element.  Execute a reload based on FK.
                return session.executeQuery(mapping.getSelectionQuery(), foreignKeys);
            }
            for (Object element : temp) {
                Object pk = elementDescriptor.getObjectBuilder().extractPrimaryKeyFromObject(element, session);
                fromCache.put(pk, element);
            }
        }
        Iterator<Object> keyIterator = keyObjects.iterator();
        for (Object key : values) {
            addInto(keyIterator.next(), fromCache.get(key), result, session);
        }
    }
    return result;
}
Also used : ArrayList(java.util.ArrayList) ReadAllQuery(org.eclipse.persistence.queries.ReadAllQuery) DatabaseMapping(org.eclipse.persistence.mappings.DatabaseMapping) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) CacheKeyType(org.eclipse.persistence.annotations.CacheKeyType) ArrayList(java.util.ArrayList) List(java.util.List)

Example 17 with CacheId

use of org.eclipse.persistence.internal.identitymaps.CacheId in project eclipselink by eclipse-ee4j.

the class XMLCollectionReferenceMapping method buildReference.

/**
 * INTERNAL:
 * Create (if necessary) and populate a reference object that will be used
 * during the mapping reference resolution phase after unmarshalling is
 * complete.
 */
public void buildReference(Object srcObject, XMLField xmlField, Object object, AbstractSession session, Object container, ReferenceResolver resolver) {
    if (resolver == null) {
        return;
    }
    Reference reference = resolver.getReference(this, srcObject, xmlField);
    if (reference == null) {
        // if reference is null, create a new instance and set it on the resolver
        reference = new Reference(this, srcObject, referenceClass, new HashMap(), container);
        resolver.addReference(reference);
    }
    CacheId primaryKeys;
    if (null == referenceClass || ClassConstants.OBJECT == referenceClass) {
        HashMap primaryKeyMap = reference.getPrimaryKeyMap();
        CacheId pks = (CacheId) primaryKeyMap.get(null);
        if (pks == null) {
            Object[] pkValues = new Object[1];
            pks = new CacheId(pkValues);
            primaryKeyMap.put(null, pks);
        }
        if (usesSingleNode) {
            for (StringTokenizer stok = new StringTokenizer((String) object); stok.hasMoreTokens(); ) {
                pks.add(stok.nextToken());
                reference = resolver.getReference(this, srcObject, xmlField);
                if (reference == null) {
                    // if reference is null, create a new instance and set it on the resolver
                    reference = new Reference(this, srcObject, referenceClass, new HashMap(), container);
                    resolver.addReference(reference);
                }
                primaryKeyMap = reference.getPrimaryKeyMap();
                pks = (CacheId) primaryKeyMap.get(null);
                if (pks == null) {
                    Object[] pkValues = new Object[1];
                    pks = new CacheId(pkValues);
                    primaryKeyMap.put(null, pks);
                }
            }
        } else {
            pks.add(object);
        }
    } else {
        XMLField tgtFld = (XMLField) getSourceToTargetKeyFieldAssociations().get(xmlField);
        String tgtXPath = tgtFld.getQualifiedName();
        HashMap primaryKeyMap = reference.getPrimaryKeyMap();
        CacheId pks = (CacheId) primaryKeyMap.get(tgtXPath);
        ClassDescriptor descriptor = session.getClassDescriptor(referenceClass);
        if (pks == null) {
            pks = new CacheId(new Object[0]);
            primaryKeyMap.put(tgtXPath, pks);
        }
        Class<?> type = descriptor.getTypedField(tgtFld).getType();
        XMLConversionManager xmlConversionManager = (XMLConversionManager) session.getDatasourcePlatform().getConversionManager();
        if (usesSingleNode) {
            for (StringTokenizer stok = new StringTokenizer((String) object); stok.hasMoreTokens(); ) {
                Object value = xmlConversionManager.convertObject(stok.nextToken(), type);
                if (value != null) {
                    pks.add(value);
                }
                reference = resolver.getReference(this, srcObject, xmlField);
                if (reference == null) {
                    // if reference is null, create a new instance and set it on the resolver
                    reference = new Reference(this, srcObject, referenceClass, new HashMap(), container);
                    resolver.addReference(reference);
                }
                primaryKeyMap = reference.getPrimaryKeyMap();
                pks = (CacheId) primaryKeyMap.get(null);
                if (pks == null) {
                    pks = new CacheId(new Object[0]);
                    primaryKeyMap.put(tgtXPath, pks);
                }
            }
        } else {
            Object value = xmlConversionManager.convertObject(object, type);
            if (value != null) {
                pks.add(value);
            }
        }
    }
}
Also used : XMLField(org.eclipse.persistence.oxm.XMLField) StringTokenizer(java.util.StringTokenizer) ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) HashMap(java.util.HashMap) Reference(org.eclipse.persistence.internal.oxm.Reference) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) XMLConversionManager(org.eclipse.persistence.internal.oxm.XMLConversionManager)

Example 18 with CacheId

use of org.eclipse.persistence.internal.identitymaps.CacheId in project eclipselink by eclipse-ee4j.

the class XMLCollectionReferenceMapping method buildFieldValue.

/**
 * INTERNAL:
 * Retrieve the target object's primary key value that is mapped to a given
 * source xpath (in the source-target key field association list).
 *
 * @param targetObject - the reference class instance that holds the required pk value
 * @return null if the target object is null, the reference class is null, or
 * a primary key field name does not exist on the reference descriptor that
 * matches the target field name - otherwise, return the associated primary
 * key value
 */
@Override
public Object buildFieldValue(Object targetObject, XMLField xmlFld, AbstractSession session) {
    if (targetObject == null) {
        return null;
    }
    ClassDescriptor descriptor = referenceDescriptor;
    if (null == descriptor) {
        descriptor = session.getClassDescriptor(targetObject);
    }
    ObjectBuilder objectBuilder = descriptor.getObjectBuilder();
    Object primaryKey = objectBuilder.extractPrimaryKeyFromObject(targetObject, session);
    XMLField tgtXMLField = (XMLField) getSourceToTargetKeyFieldAssociations().get(xmlFld);
    int idx = 0;
    if (!(null == referenceClass || ClassConstants.OBJECT == referenceClass)) {
        idx = descriptor.getPrimaryKeyFields().indexOf(tgtXMLField);
        if (idx == -1) {
            return null;
        }
    }
    if (primaryKey instanceof CacheId) {
        return ((CacheId) primaryKey).getPrimaryKey()[idx];
    } else {
        return primaryKey;
    }
}
Also used : XMLField(org.eclipse.persistence.oxm.XMLField) ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) ObjectBuilder(org.eclipse.persistence.internal.descriptors.ObjectBuilder)

Example 19 with CacheId

use of org.eclipse.persistence.internal.identitymaps.CacheId 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 20 with CacheId

use of org.eclipse.persistence.internal.identitymaps.CacheId in project eclipselink by eclipse-ee4j.

the class XMLObjectReferenceMapping method buildFieldValue.

/**
 * INTERNAL:
 * Retrieve the target object's primary key value that is mapped to a given
 * source xpath (in the source-target key field association list).
 *
 * @return null if the target object is null, the reference class is null, or
 * a primary key field name does not exist on the reference descriptor that
 * matches the target field name - otherwise, return the associated primary
 * key value
 */
@Override
public Object buildFieldValue(Object targetObject, XMLField xmlFld, AbstractSession session) {
    if (targetObject == null || getReferenceClass() == null) {
        return null;
    }
    ClassDescriptor descriptor = referenceDescriptor;
    if (null == descriptor) {
        descriptor = session.getClassDescriptor(targetObject);
    }
    ObjectBuilder objectBuilder = descriptor.getObjectBuilder();
    Object primaryKey = objectBuilder.extractPrimaryKeyFromObject(targetObject, session);
    int idx = 0;
    if (!(null == referenceClass || ClassConstants.OBJECT == getReferenceClass())) {
        idx = descriptor.getPrimaryKeyFields().indexOf(getSourceToTargetKeyFieldAssociations().get(xmlFld));
        if (idx == -1) {
            return null;
        }
    }
    if (primaryKey instanceof CacheId) {
        return ((CacheId) primaryKey).getPrimaryKey()[idx];
    } else {
        return primaryKey;
    }
}
Also used : ClassDescriptor(org.eclipse.persistence.descriptors.ClassDescriptor) CacheId(org.eclipse.persistence.internal.identitymaps.CacheId) ObjectBuilder(org.eclipse.persistence.internal.descriptors.ObjectBuilder)

Aggregations

CacheId (org.eclipse.persistence.internal.identitymaps.CacheId)38 DatabaseField (org.eclipse.persistence.internal.helper.DatabaseField)19 ArrayList (java.util.ArrayList)12 List (java.util.List)10 ClassDescriptor (org.eclipse.persistence.descriptors.ClassDescriptor)8 ConversionException (org.eclipse.persistence.exceptions.ConversionException)8 ConversionManager (org.eclipse.persistence.internal.helper.ConversionManager)8 CacheKey (org.eclipse.persistence.internal.identitymaps.CacheKey)5 DatabaseMapping (org.eclipse.persistence.mappings.DatabaseMapping)5 HashMap (java.util.HashMap)4 AbstractRecord (org.eclipse.persistence.internal.sessions.AbstractRecord)4 XMLField (org.eclipse.persistence.oxm.XMLField)4 Vector (java.util.Vector)3 CacheKeyType (org.eclipse.persistence.annotations.CacheKeyType)3 CoreDescriptor (org.eclipse.persistence.core.descriptors.CoreDescriptor)3 InvalidObject (org.eclipse.persistence.internal.helper.InvalidObject)3 Descriptor (org.eclipse.persistence.internal.oxm.mappings.Descriptor)3 ReadAllQuery (org.eclipse.persistence.queries.ReadAllQuery)3 SAXException (org.xml.sax.SAXException)3 SAXParseException (org.xml.sax.SAXParseException)3