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;
}
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);
}
}
}
}
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;
}
}
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();
}
}
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;
}
}
Aggregations