use of org.eclipse.persistence.internal.identitymaps.CacheId in project eclipselink by eclipse-ee4j.
the class OneToManyMapping method extractKeyFromTargetRow.
/**
* INTERNAL:
* Extract the source primary key value from the target row.
* Used for batch reading, most following same order and fields as in the mapping.
*/
@Override
protected Object extractKeyFromTargetRow(AbstractRecord row, AbstractSession session) {
int size = this.sourceKeyFields.size();
Object[] key = new Object[size];
ConversionManager conversionManager = session.getDatasourcePlatform().getConversionManager();
for (int index = 0; index < size; index++) {
DatabaseField targetField = this.targetForeignKeyFields.get(index);
DatabaseField sourceField = this.sourceKeyFields.get(index);
Object value = row.get(targetField);
// Must ensure the classification gets a cache hit.
try {
value = conversionManager.convertObject(value, sourceField.getType());
} catch (ConversionException e) {
throw ConversionException.couldNotBeConverted(this, getDescriptor(), e);
}
key[index] = value;
}
return new CacheId(key);
}
use of org.eclipse.persistence.internal.identitymaps.CacheId 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);
}
}
});
}
use of org.eclipse.persistence.internal.identitymaps.CacheId in project eclipselink by eclipse-ee4j.
the class EntityManagerImpl method findInternal.
/**
* Find by primary key.
*
* @param descriptor
* - the entity class to find.
* @param id
* - the entity primary key value, or primary key class, or a
* List of primary key values.
* @return the found entity instance or null, if the entity does not exist.
* @throws IllegalArgumentException
* if the first argument does not denote an entity type or the
* second argument is not a valid type for that entity's primary
* key.
*/
protected Object findInternal(ClassDescriptor descriptor, AbstractSession session, Object id, LockModeType lockMode, Map<String, Object> properties) {
if (id == null) {
// gf721 - check for null PK
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("null_pk"));
}
Object primaryKey;
if (id instanceof List) {
if (descriptor.getCacheKeyType() == CacheKeyType.ID_VALUE) {
if (((List) id).isEmpty()) {
primaryKey = null;
} else {
primaryKey = ((List) id).get(0);
}
} else {
primaryKey = new CacheId(((List) id).toArray());
}
} else if (id instanceof CacheId) {
primaryKey = id;
} else {
CMPPolicy policy = descriptor.getCMPPolicy();
Class<Object> pkClass = policy.getPKClass();
if ((pkClass != null) && (pkClass != id.getClass()) && (!BasicTypeHelperImpl.getInstance().isStrictlyAssignableFrom(pkClass, id.getClass()))) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("invalid_pk_class", new Object[] { descriptor.getCMPPolicy().getPKClass(), id.getClass() }));
}
primaryKey = policy.createPrimaryKeyFromId(id, session);
}
// Must avoid using the new JPA 2.0 Enum values directly to allow JPA 1.0 jars to still work.
if (lockMode != null && (lockMode.name().equals(ObjectLevelReadQuery.PESSIMISTIC_READ) || lockMode.name().equals(ObjectLevelReadQuery.PESSIMISTIC_WRITE) || lockMode.name().equals(ObjectLevelReadQuery.PESSIMISTIC_FORCE_INCREMENT))) {
// PERF: check if the UnitOfWork has pessimistically locked objects to avoid a cache query
if (session.isUnitOfWork() && ((UnitOfWorkImpl) session).hasPessimisticLockedObjects()) {
ReadObjectQuery query = new ReadObjectQuery();
query.setReferenceClass(descriptor.getJavaClass());
query.setSelectionId(primaryKey);
query.checkCacheOnly();
Object cachedEntity = session.executeQuery(query);
if (cachedEntity != null && ((UnitOfWorkImpl) session).isPessimisticLocked(cachedEntity)) {
return cachedEntity;
}
}
}
// Get the read object query and apply the properties to it.
// PERF: use descriptor defined query to avoid extra query creation.
ReadObjectQuery query = descriptor.getQueryManager().getReadObjectQuery();
if (query == null) {
// The properties/query hints and setIsExecutionClone etc. is set
// in the getReadObjectQuery.
query = getReadObjectQuery(descriptor.getJavaClass(), primaryKey, properties);
} else {
query.checkPrepare(session, null);
query = (ReadObjectQuery) query.clone();
// Apply the properties if there are some.
QueryHintsHandler.apply(properties, query, session.getLoader(), session);
query.setIsExecutionClone(true);
query.setSelectionId(primaryKey);
}
// the properties.
if (properties == null || (!properties.containsKey(QueryHints.CACHE_USAGE) && !properties.containsKey(QueryHints.CACHE_RETRIEVE_MODE) && !properties.containsKey(QueryHints.CACHE_STORE_MODE) && !properties.containsKey("jakarta.persistence.cacheRetrieveMode") && !properties.containsKey("jakarta.persistence.cacheStoreMode"))) {
query.conformResultsInUnitOfWork();
}
return executeQuery(query, lockMode, session);
}
Aggregations