/** * INTERNAL: Return the classification for the field contained in the mapping. This is used to * convert the row value to a consistent java value. */ @Override public Class getFieldClassification(DatabaseField fieldToClassify) { if ((getTypeField() != null) && (fieldToClassify.equals(getTypeField()))) { return getTypeField().getType(); } String queryKey = (String) getSourceToTargetQueryKeyNames().get(fieldToClassify); if (queryKey == null) { return null; } // Search any of the implementor descriptors for a mapping for the query-key. Iterator iterator = getReferenceDescriptor().getInterfacePolicy().getChildDescriptors().iterator(); if (iterator.hasNext()) { ClassDescriptor firstChild = (ClassDescriptor) iterator.next(); DatabaseMapping mapping = firstChild.getObjectBuilder().getMappingForAttributeName(queryKey); if ((mapping != null) && (mapping.isDirectToFieldMapping())) { return ((AbstractDirectMapping) mapping).getAttributeClassification(); } QueryKey targetQueryKey = firstChild.getQueryKeyNamed(queryKey); if ((targetQueryKey != null) && (targetQueryKey.isDirectQueryKey())) { return firstChild .getObjectBuilder() .getFieldClassification(((DirectQueryKey) targetQueryKey).getField()); } } return null; }
/** INTERNAL: Get a value from the object and set that in the respective field of the row. */ @Override public Object valueFromObject(Object object, DatabaseField field, AbstractSession session) { // First check if the value can be obtained from the value holder's row. AbstractRecord referenceRow = getIndirectionPolicy().extractReferenceRow(getAttributeValueFromObject(object)); if (referenceRow != null) { Object value = referenceRow.get(field); // Must ensure the classification to get a cache hit. try { value = session.getDatasourcePlatform().convertObject(value, getFieldClassification(field)); } catch (ConversionException e) { throw ConversionException.couldNotBeConverted(this, getDescriptor(), e); } return value; } // 2.5.1.6 PWK. added to support batch reading on variable one to ones Object referenceObject = getRealAttributeValueFromObject(object, session); String queryKeyName = (String) getSourceToTargetQueryKeyNames().get(field); ClassDescriptor objectDescriptor = session.getDescriptor(referenceObject.getClass()); DatabaseField targetField = objectDescriptor.getObjectBuilder().getTargetFieldForQueryKeyName(queryKeyName); if (targetField == null) { return null; } return objectDescriptor .getObjectBuilder() .extractValueFromObjectForField(referenceObject, targetField, session); }
public Object getObjectForUpdate( Session session, Object objectToUpdateBeforeChange, Object objectToUpdateAfterChange, boolean useUOW) { ClassDescriptor desc = session.getClassDescriptor(objectToUpdateBeforeChange); Record rowBeforeChange = desc.getObjectBuilder() .buildRow(objectToUpdateBeforeChange, (AbstractSession) session, WriteType.UPDATE); Record rowAfterChange = desc.getObjectBuilder() .buildRow(objectToUpdateAfterChange, (AbstractSession) session, WriteType.UPDATE); Record rowChange = new DatabaseRecord(); getChange( rowChange, session, objectToUpdateBeforeChange, objectToUpdateAfterChange, desc, useUOW, WriteType.UPDATE); Record rowReturn = getRowForUpdate(rowChange); if (rowReturn != null && !rowReturn.isEmpty()) { Record row = new DatabaseRecord(rowAfterChange.size()); row.putAll(rowAfterChange); row.putAll(rowReturn); return readObjectFromRow(session, desc, row); } else { return objectToUpdateAfterChange; } }
/** * INTERNAL: Compare the references of the two objects are the same, not the objects themselves. * Used for independent relationships. This is used for testing and validation purposes. * * <p>Must get separate fields for the objects because we may be adding a different class to the * attribute because of the interface */ @Override protected boolean compareObjectsWithoutPrivateOwned( Object firstObject, Object secondObject, AbstractSession session) { Object firstPrivateObject = getRealAttributeValueFromObject(firstObject, session); Object secondPrivateObject = getRealAttributeValueFromObject(secondObject, session); if ((firstPrivateObject == null) && (secondPrivateObject == null)) { return true; } if ((firstPrivateObject == null) || (secondPrivateObject == null)) { return false; } if (firstPrivateObject.getClass() != secondPrivateObject.getClass()) { return false; } Iterator targetKeys = getSourceToTargetQueryKeyNames().values().iterator(); ClassDescriptor descriptor = session.getDescriptor(firstPrivateObject.getClass()); ClassDescriptor descriptor2 = session.getDescriptor(secondPrivateObject.getClass()); while (targetKeys.hasNext()) { String queryKey = (String) targetKeys.next(); DatabaseField field = descriptor.getObjectBuilder().getFieldForQueryKeyName(queryKey); Object firstObjectField = descriptor .getObjectBuilder() .extractValueFromObjectForField(firstPrivateObject, field, session); DatabaseField field2 = descriptor2.getObjectBuilder().getFieldForQueryKeyName(queryKey); Object secondObjectField = descriptor2 .getObjectBuilder() .extractValueFromObjectForField(secondPrivateObject, field2, session); if (!((firstObjectField == null) && (secondObjectField == null))) { if ((firstObjectField == null) || (secondObjectField == null)) { return false; } if (!firstObjectField.equals(secondObjectField)) { return false; } } } return true; }
@Override protected Object buildCompositeObject( ClassDescriptor descriptor, AbstractRecord nestedRow, ObjectBuildingQuery query, CacheKey parentCacheKey, JoinedAttributeManager joinManger, AbstractSession targetSession) { return descriptor.getObjectBuilder().buildObject(query, nestedRow, joinManger); }
@Override protected Object buildCompositeObject( ClassDescriptor descriptor, AbstractRecord nestedRow, ObjectBuildingQuery query, CacheKey parentsCacheKey, JoinedAttributeManager joinManager, AbstractSession targetSession) { if (((EISDescriptor) descriptor).getDataFormat() == EISDescriptor.XML) { return descriptor.getObjectBuilder().buildObject(query, nestedRow, joinManager); } else { Object element = descriptor.getObjectBuilder().buildNewInstance(); descriptor .getObjectBuilder() .buildAttributesIntoObject( element, parentsCacheKey, nestedRow, query, joinManager, false, targetSession); return element; } }
/** INTERNAL: Get a value from the object and set that in the respective field of the row. */ @Override public void writeFromObjectIntoRowForWhereClause( ObjectLevelModifyQuery query, AbstractRecord record) { if (isReadOnly()) { return; } Object object; if (query.isDeleteObjectQuery()) { object = query.getObject(); } else { object = query.getBackupClone(); } Object referenceObject = getRealAttributeValueFromObject(object, query.getSession()); if (referenceObject == null) { writeFromNullObjectIntoRow(record); } else { if (isForeignKeyRelationship()) { Enumeration sourceFields = getForeignKeyFields().elements(); ClassDescriptor descriptor = query.getSession().getDescriptor(referenceObject.getClass()); while (sourceFields.hasMoreElements()) { DatabaseField sourceKey = (DatabaseField) sourceFields.nextElement(); String targetQueryKey = (String) getSourceToTargetQueryKeyNames().get(sourceKey); DatabaseField targetKeyField = descriptor.getObjectBuilder().getFieldForQueryKeyName(targetQueryKey); if (targetKeyField == null) { throw DescriptorException.variableOneToOneMappingIsNotDefinedProperly( this, descriptor, targetQueryKey); } Object referenceValue = descriptor .getObjectBuilder() .extractValueFromObjectForField( referenceObject, targetKeyField, query.getSession()); record.put(sourceKey, referenceValue); } } if (getTypeField() != null) { record.put(getTypeField(), getTypeForImplementor(referenceObject.getClass())); } } }
@Override protected Object buildCompositeObject( ClassDescriptor descriptor, AbstractRecord nestedRow, ObjectBuildingQuery query, CacheKey parentCacheKey, JoinedAttributeManager joinManager, AbstractSession targetSession) { Object element = descriptor.getObjectBuilder().buildNewInstance(); descriptor .getObjectBuilder() .buildAttributesIntoObject( element, parentCacheKey, nestedRow, query, joinManager, query.getExecutionFetchGroup(descriptor), false, targetSession); return element; }
/** * 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 * @param xmlFld * @param session * @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 */ public Object buildFieldValue(Object targetObject, XMLField xmlFld, AbstractSession session) { if (targetObject == null || getReferenceClass() == null) { return null; } ClassDescriptor descriptor = getReferenceDescriptor(); ObjectBuilder objectBuilder = descriptor.getObjectBuilder(); Vector pks = objectBuilder.extractPrimaryKeyFromObject(targetObject, session); XMLField tgtXMLField = (XMLField) getSourceToTargetKeyFieldAssociations().get(xmlFld); int idx = descriptor.getPrimaryKeyFields().indexOf(tgtXMLField); if (idx == -1) { return null; } return pks.get(idx); }
/** * INTERNAL: Get a value from the object and set that in the respective field of the row. If the * mapping id target foreign key, you must only write the type into the roe, the rest will be * updated when the object itself is written */ @Override public void writeFromObjectIntoRowWithChangeRecord( ChangeRecord changeRecord, AbstractRecord record, AbstractSession session) { if (isReadOnly()) { return; } ObjectChangeSet changeSet = (ObjectChangeSet) ((ObjectReferenceChangeRecord) changeRecord).getNewValue(); if (changeSet == null) { writeFromNullObjectIntoRow(record); } else { Object referenceObject = changeSet.getUnitOfWorkClone(); if (isForeignKeyRelationship()) { Enumeration sourceFields = getForeignKeyFields().elements(); ClassDescriptor descriptor = session.getDescriptor(referenceObject.getClass()); while (sourceFields.hasMoreElements()) { DatabaseField sourceKey = (DatabaseField) sourceFields.nextElement(); String targetQueryKey = (String) getSourceToTargetQueryKeyNames().get(sourceKey); DatabaseField targetKeyField = descriptor.getObjectBuilder().getFieldForQueryKeyName(targetQueryKey); if (targetKeyField == null) { throw DescriptorException.variableOneToOneMappingIsNotDefinedProperly( this, descriptor, targetQueryKey); } Object referenceValue = descriptor .getObjectBuilder() .extractValueFromObjectForField(referenceObject, targetKeyField, session); record.put(sourceKey, referenceValue); } } if (getTypeField() != null) { record.put(getTypeField(), getTypeForImplementor(referenceObject.getClass())); } } }
/** * INTERNAL: This method marks the object as changed. This method is only called by EclipseLink */ public void internalPropertyChange(PropertyChangeEvent evt) { if (evt.getNewValue() == evt.getOldValue()) { return; } DatabaseMapping mapping = descriptor.getObjectBuilder().getMappingForAttributeName(evt.getPropertyName()); // Bug#4127952 Throw an exception indicating there is no mapping for the property name. if (mapping == null) { throw ValidationException.wrongPropertyNameInChangeEvent( owner.getClass(), evt.getPropertyName()); } if (mapping instanceof AbstractDirectMapping || mapping instanceof AbstractTransformationMapping) { // If both newValue and oldValue are null, or newValue is not null and newValue equals // oldValue, don't build ChangeRecord if (((evt.getNewValue() == null) && (evt.getOldValue() == null)) || ((evt.getNewValue() != null) && (evt.getNewValue()).equals(evt.getOldValue()))) { return; } } super.internalPropertyChange(evt); if (uow.getUnitOfWorkChangeSet() == null) { uow.setUnitOfWorkChangeSet(new UnitOfWorkChangeSet(uow)); } if (objectChangeSet == null) { // only null if new or if in a new UOW // add to tracker list to prevent GC of clone if using weak references // put it in here so that it only occurs on the 1st change for a particular UOW uow.addToChangeTrackedHardList(owner); objectChangeSet = getDescriptor() .getObjectBuilder() .createObjectChangeSet( owner, (UnitOfWorkChangeSet) uow.getUnitOfWorkChangeSet(), false, uow); } if (evt.getClass().equals(ClassConstants.PropertyChangeEvent_Class)) { mapping.updateChangeRecord( evt.getSource(), evt.getNewValue(), evt.getOldValue(), objectChangeSet, getUnitOfWork()); } else if (evt.getClass().equals(ClassConstants.CollectionChangeEvent_Class) || (evt.getClass().equals(ClassConstants.MapChangeEvent_Class))) { mapping.updateCollectionChangeRecord( (CollectionChangeEvent) evt, objectChangeSet, getUnitOfWork()); } else { throw ValidationException.wrongChangeEvent(evt.getClass()); } }
// bug 331064 - Sort the delete order based on PKs. private List sort(Class theClass, List objects) { ClassDescriptor descriptor = session.getDescriptor(theClass); org.eclipse.persistence.internal.descriptors.ObjectBuilder objectBuilder = descriptor.getObjectBuilder(); int size = objects.size(); TreeMap sortedObjects = new TreeMap(); for (int index = 0; index < size; index++) { Object objectToDelete = objects.get(index); if (objectToDelete.getClass() == theClass) { sortedObjects.put( objectBuilder.extractPrimaryKeyFromObject(objectToDelete, session), objectToDelete); } } return new ArrayList(sortedObjects.values()); }
public Object getObjectForInsert(Session session, Object objectToInsert) { ClassDescriptor desc = session.getClassDescriptor(objectToInsert); Record rowToInsert = desc.getObjectBuilder() .buildRow(objectToInsert, (AbstractSession) session, WriteType.INSERT); Record rowReturn = getRowForInsert(rowToInsert); if (rowReturn != null && !rowReturn.isEmpty()) { Record row = new DatabaseRecord(rowToInsert.size()); row.putAll(rowToInsert); row.putAll(rowReturn); return readObjectFromRow(session, desc, row); } else { return objectToInsert; } }
protected AbstractRecord buildCompositeRowForDescriptor( ClassDescriptor classDesc, Object attributeValue, AbstractSession session, XMLRecord parentRow, WriteType writeType) { XMLObjectBuilder objectBuilder = (XMLObjectBuilder) classDesc.getObjectBuilder(); XMLRecord child = (XMLRecord) objectBuilder.createRecordFor(attributeValue, (XMLField) getField(), parentRow, this); child.setNamespaceResolver(parentRow.getNamespaceResolver()); child.setSession(session); objectBuilder.buildIntoNestedRow( child, attributeValue, session, (XMLDescriptor) getReferenceDescriptor(), (XMLField) getField()); return child; }
protected Object readObjectFromRow(Session session, ClassDescriptor desc, Record row) { if (desc.hasInheritance()) { Class newClass = desc.getInheritancePolicy().classFromRow((DatabaseRecord) row, (AbstractSession) session); desc = session.getClassDescriptor(newClass); } Object object = desc.getObjectBuilder().buildNewInstance(); ReadObjectQuery query = new ReadObjectQuery(); query.setSession((AbstractSession) session); for (Enumeration mappings = desc.getMappings().elements(); mappings.hasMoreElements(); ) { DatabaseMapping mapping = (DatabaseMapping) mappings.nextElement(); mapping.readFromRowIntoObject( (DatabaseRecord) row, query.getJoinedAttributeManager(), object, null, query, query.getSession(), true); } return object; }
protected boolean compare(int i) { if (objectVectors[i] == null) { return false; } Vector currentVector = getDbSession().readAllObjects(classes[i]); if (currentVector.size() != objectVectors[i].size()) { return false; } ClassDescriptor descriptor = getDbSession().getDescriptor(classes[i]); for (int j = 0; j < currentVector.size(); j++) { Object obj1 = objectVectors[i].elementAt(j); Object obj2 = currentVector.elementAt(j); if (!descriptor .getObjectBuilder() .compareObjects( obj1, obj2, (org.eclipse.persistence.internal.sessions.AbstractSession) getDbSession())) { return false; } } return true; }
/** @return DatabaseMapping for given attribute name */ private DatabaseMapping getMappingForAttributeName(String attributeName) { return descriptor.getObjectBuilder().getMappingForAttributeName(attributeName); }
/** * INTERNAL: Check if existence can be determined without going to the database. Note that custom * query check is not require for does exist as the custom is always used. Used by unit of work, * and will return null if checkDatabaseIfInvalid is set and the cachekey is invalidated */ public Object checkEarlyReturn( Object object, Vector primaryKey, AbstractSession session, AbstractRecord translationRow) { // For bug 3136413/2610803 building the selection criteria from an EJBQL string or // an example object is done just in time. buildSelectionCriteria(session); // Return false on null since it can't exist. Little more done in case PK not set in the query if (object == null) { return Boolean.FALSE; } ClassDescriptor descriptor = session.getDescriptor(object.getClass()); if (primaryKey == null) { primaryKey = getPrimaryKey(); if (primaryKey == null) { primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, session, true); } } if ((primaryKey == null) || (primaryKey.contains(null))) { return Boolean.FALSE; } // Need to do the cache check first if flag set or if we should check the cache only for // existence. if ((shouldCheckCacheForDoesExist() || this.checkCacheFirst) && !descriptor.isDescriptorForInterface()) { // If this is a UOW and modification queries have been executed, the cache cannot be trusted. if (this.checkDatabaseIfInvalid && (session.isUnitOfWork() && ((UnitOfWorkImpl) session).shouldReadFromDB())) { return null; } CacheKey cacheKey; Class objectClass = object.getClass(); AbstractSession tempSession = session; while (tempSession.isUnitOfWork()) { // could be nested lets check all UOWs cacheKey = tempSession .getIdentityMapAccessorInstance() .getCacheKeyForObjectForLock(primaryKey, objectClass, descriptor); if (cacheKey != null) { // If in the UOW cache it can't be invalid. return Boolean.TRUE; } tempSession = ((UnitOfWorkImpl) tempSession).getParent(); } // Did not find it registered in UOW so check main cache and check for invalidation. cacheKey = tempSession .getIdentityMapAccessorInstance() .getCacheKeyForObject(primaryKey, objectClass, descriptor); if ((cacheKey != null)) { // Assume that if there is a cachekey, object exists. if (this.checkDatabaseIfInvalid) { checkDescriptor(object, session); if (this.descriptor .getCacheInvalidationPolicy() .isInvalidated(cacheKey, System.currentTimeMillis())) { return null; } } Object objectFromCache = cacheKey.getObject(); if ((session.isUnitOfWork()) && ((UnitOfWorkImpl) session).wasDeleted(objectFromCache)) { if (shouldCheckCacheForDoesExist()) { return Boolean.FALSE; } } else { return Boolean.TRUE; } } else if (shouldCheckCacheForDoesExist()) { // We know its not in cache, and a checkcache policy so return false. return Boolean.FALSE; } } // Check if we have to assume that the object does not exist. if (shouldAssumeNonExistenceForDoesExist()) { return Boolean.FALSE; } // Check to see if we only need to check that the object contains a primary key. if (shouldAssumeExistenceForDoesExist()) { return Boolean.TRUE; } return null; }
/** * INTERNAL: Build and return the nested rows from the specified field value. This method allows * the field value to be an ARRAY containing other structures such as arrays or Struct, or direct * values. */ public static Object buildContainerFromArray( Array fieldValue, ObjectRelationalDatabaseField arrayField, AbstractSession session) throws DatabaseException { if (arrayField.getType() == null) { return fieldValue; } Object[] objects = null; try { objects = (Object[]) fieldValue.getArray(); } catch (java.sql.SQLException ex) { throw DatabaseException.sqlException(ex, session, false); } if (objects == null) { return null; } boolean isNestedStructure = false; ObjectRelationalDataTypeDescriptor ord = null; DatabaseField nestedType = null; if (arrayField != null) { nestedType = arrayField.getNestedTypeField(); if ((nestedType != null) && nestedType.getSqlType() == Types.STRUCT) { ClassDescriptor descriptor = session.getDescriptor(nestedType.getType()); if ((descriptor != null) && (descriptor.isObjectRelationalDataTypeDescriptor())) { // this is used to convert non-null objects passed through stored procedures and custom // SQL to structs ord = (ObjectRelationalDataTypeDescriptor) descriptor; } } else if ((nestedType != null) && (nestedType instanceof ObjectRelationalDatabaseField)) { isNestedStructure = true; } } // handle ARRAY conversions ReadObjectQuery query = new ReadObjectQuery(); query.setSession(session); ContainerPolicy cp = ContainerPolicy.buildPolicyFor(arrayField.getType()); Object container = cp.containerInstance(objects.length); for (int i = 0; i < objects.length; i++) { Object arrayValue = objects[i]; if (arrayValue == null) { return null; } if (ord != null) { AbstractRecord nestedRow = ord.buildRowFromStructure((Struct) arrayValue); ClassDescriptor descriptor = ord; if (descriptor.hasInheritance()) { Class newElementClass = descriptor.getInheritancePolicy().classFromRow(nestedRow, session); if (!descriptor.getJavaClass().equals(newElementClass)) { descriptor = session.getDescriptor(newElementClass); if (descriptor == null) { descriptor = ord; } } } arrayValue = descriptor.getObjectBuilder().buildNewInstance(); descriptor .getObjectBuilder() .buildAttributesIntoObject(arrayValue, nestedRow, query, null, false); } else if (isNestedStructure && (arrayValue instanceof Array)) { arrayValue = buildContainerFromArray( (Array) arrayValue, (ObjectRelationalDatabaseField) nestedType, session); } cp.addInto(arrayValue, container, session); } return container; }