use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class PersistableMapping method postUpdate.
/**
* Method executed just afer any update of the owning object, allowing any necessary action to this field and the object stored in it.
* @param op ObjectProvider for the owner
*/
public void postUpdate(ObjectProvider op) {
Object pc = op.provideField(mmd.getAbsoluteFieldNumber());
pc = mmd.isSingleCollection() ? SCOUtils.singleCollectionValue(getStoreManager().getNucleusContext().getTypeManager(), pc) : pc;
ClassLoaderResolver clr = op.getExecutionContext().getClassLoaderResolver();
RelationType relationType = mmd.getRelationType(clr);
if (pc == null) {
if (relationType == RelationType.MANY_TO_ONE_UNI) {
// Update join table entry
PersistableRelationStore store = (PersistableRelationStore) storeMgr.getBackingStoreForField(clr, mmd, mmd.getType());
store.remove(op);
}
return;
}
ObjectProvider otherOP = op.getExecutionContext().findObjectProvider(pc);
if (otherOP == null) {
if (relationType == RelationType.ONE_TO_ONE_BI || relationType == RelationType.MANY_TO_ONE_BI || relationType == RelationType.MANY_TO_ONE_UNI) {
// Related object is not yet persisted (e.g 1-1 with FK at other side) so persist it
Object other = op.getExecutionContext().persistObjectInternal(pc, null, -1, ObjectProvider.PC);
otherOP = op.getExecutionContext().findObjectProvider(other);
}
}
if (relationType == RelationType.MANY_TO_ONE_UNI) {
// Update join table entry
PersistableRelationStore store = (PersistableRelationStore) storeMgr.getBackingStoreForField(clr, mmd, mmd.getType());
store.update(op, otherOP);
}
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class ReferenceMapping method getReferenceStringForObject.
/**
* Method to convert an object to be stored into a "reference string" to store.
* Reference string is of the form :
* <ul>
* <li>ID_MAPPING : "{classname}:{id}"</li>
* <li>XCALIA_MAPPING (datastore-id) : "{definer}:{id-key}" where definer is discriminator/classname</li>
* <li>XCALIA_MAPPING (app-id) : "{definer}:{id}" where definer is discriminator/classname</li>
* </ul>
* @param ec ExecutionContext
* @param value The object
* @return The reference string
*/
protected String getReferenceStringForObject(ExecutionContext ec, Object value) {
if (ec.getApiAdapter().isPersistable(value)) {
ObjectProvider op = ec.findObjectProvider(value);
if (op == null) {
// Referenced object is not yet persistent, so persist it
ec.persistObjectInternal(value, null, -1, ObjectProvider.PC);
op = ec.findObjectProvider(value);
// Make sure the object is in the datastore so the id is set
op.flush();
}
String refString = null;
if (mappingStrategy == ID_MAPPING) {
refString = value.getClass().getName() + ":" + op.getInternalObjectId();
} else if (mappingStrategy == XCALIA_MAPPING) {
AbstractClassMetaData cmd = op.getClassMetaData();
DiscriminatorMetaData dismd = cmd.getDiscriminatorMetaData();
String definer = null;
if (dismd != null && dismd.getValue() != null) {
definer = dismd.getValue();
} else {
definer = cmd.getFullClassName();
}
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
refString = definer + ":" + IdentityUtils.getTargetKeyForDatastoreIdentity(op.getInternalObjectId());
} else {
refString = definer + ":" + op.getInternalObjectId().toString();
}
}
return refString;
}
// Cater for non-persistable objects
throw new NucleusException("Identity mapping of non-persistable interface/Object fields not supported");
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class ForwardQueryResult method nextResultSetElement.
/**
* Accessor for the next object from the ResultSet.
* @return The next element from the ResultSet.
*/
protected E nextResultSetElement() {
if (rof == null) {
// Already disconnected
return null;
}
// Convert this row into its associated object and save it
E nextElement = rof.getObject();
JDBCUtils.logWarnings(rs);
resultObjs.add(nextElement);
if (resultIds != null) {
resultIds.add(api.getIdForObject(nextElement));
}
// Process any bulk loaded members
if (bulkLoadedValueByMemberNumber != null) {
Map<Integer, Object> memberValues = bulkLoadedValueByMemberNumber.get(api.getIdForObject(nextElement));
if (memberValues != null) {
ObjectProvider op = query.getExecutionContext().findObjectProvider(nextElement);
Iterator<Map.Entry<Integer, Object>> memberValIter = memberValues.entrySet().iterator();
while (memberValIter.hasNext()) {
Map.Entry<Integer, Object> memberValueEntry = memberValIter.next();
op.replaceField(memberValueEntry.getKey(), memberValueEntry.getValue());
}
op.replaceAllLoadedSCOFieldsWithWrappers();
}
}
// Update the status of whether there are more results outstanding
if (rs == null) {
throw new NucleusUserException("Results for query have already been closed. Perhaps you called flush(), closed the query, or ended a transaction");
}
try {
moreResultSetRows = rs.next();
if (applyRangeChecks) {
// Check if we have reached the end of the range
int maxElements = (int) (query.getRangeToExcl() - query.getRangeFromIncl());
if (resultObjs.size() == maxElements) {
moreResultSetRows = false;
}
}
if (!moreResultSetRows) {
closeResults();
}
} catch (SQLException e) {
throw api.getDataStoreExceptionForException(Localiser.msg("052601", e.getMessage()), e);
}
return nextElement;
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class CollectionMapping method postInsert.
/**
* Method to be called after the insert of the owner class element.
* @param ownerOP ObjectProvider of the owner
*/
public void postInsert(ObjectProvider ownerOP) {
ExecutionContext ec = ownerOP.getExecutionContext();
Collection value = (Collection) ownerOP.provideField(getAbsoluteFieldNumber());
if (containerIsStoredInSingleColumn()) {
if (value != null) {
if (mmd.getCollection().elementIsPersistent()) {
// Make sure all persistable elements have ObjectProviders
Object[] collElements = value.toArray();
for (Object elem : collElements) {
if (elem != null) {
ObjectProvider elemOP = ec.findObjectProvider(elem);
if (elemOP == null || ec.getApiAdapter().getExecutionContext(elem) == null) {
elemOP = ec.getNucleusContext().getObjectProviderFactory().newForEmbedded(ec, elem, false, ownerOP, mmd.getAbsoluteFieldNumber());
}
}
}
}
}
return;
}
if (value == null) {
// replace null collections with an empty SCO wrapper
replaceFieldWithWrapper(ownerOP, null);
return;
}
Object[] collElements = value.toArray();
if (!mmd.isCascadePersist()) {
// Check that all elements are persistent before continuing and throw exception if necessary
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("007006", mmd.getFullFieldName()));
}
for (Object collElement : collElements) {
if (!ec.getApiAdapter().isDetached(collElement) && !ec.getApiAdapter().isPersistent(collElement)) {
// Element is not persistent so throw exception
throw new ReachableObjectNotCascadedException(mmd.getFullFieldName(), collElement);
}
}
} else {
// Reachability
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("007007", mmd.getFullFieldName()));
}
}
// Check if some elements need attaching
// TODO Investigate if we can just use the attachCopy route below and skip off this check
boolean needsAttaching = false;
for (Object collElement : collElements) {
if (ownerOP.getExecutionContext().getApiAdapter().isDetached(collElement)) {
needsAttaching = true;
break;
}
}
if (needsAttaching) {
// Create a wrapper and attach the elements (and add the others)
SCO collWrapper = replaceFieldWithWrapper(ownerOP, null);
if (value.size() > 0) {
collWrapper.attachCopy(value);
// The attach will have put entries in the operationQueue if using optimistic, so flush them
ownerOP.getExecutionContext().flushOperationsForBackingStore(((BackedSCO) collWrapper).getBackingStore(), ownerOP);
}
} else {
if (value.size() > 0) {
// Add the elements direct to the datastore
((CollectionStore) storeMgr.getBackingStoreForField(ownerOP.getExecutionContext().getClassLoaderResolver(), mmd, value.getClass())).addAll(ownerOP, value, 0);
// Create a SCO wrapper with the elements loaded
replaceFieldWithWrapper(ownerOP, value);
} else {
if (mmd.getRelationType(ownerOP.getExecutionContext().getClassLoaderResolver()) == RelationType.MANY_TO_MANY_BI) {
// Create a SCO wrapper, pass in null so it loads any from the datastore (on other side?)
replaceFieldWithWrapper(ownerOP, null);
} else {
// Create a SCO wrapper, pass in empty collection to avoid loading from DB (extra SQL)
replaceFieldWithWrapper(ownerOP, value);
}
}
}
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class EmbeddedMapping method getObject.
/**
* Accessor for the embedded object from the result set
* @param ec ExecutionContext
* @param rs The ResultSet
* @param param Array of param numbers in the ResultSet for the fields of this object
* @param ownerOP ObjectProvider of the owning object containing this embedded object
* @param ownerFieldNumber Field number in the owning object where this is stored
* @return The embedded object
*/
public Object getObject(ExecutionContext ec, ResultSet rs, int[] param, ObjectProvider ownerOP, int ownerFieldNumber) {
Object value = null;
int n = 0;
// Determine the type of the embedded object
AbstractClassMetaData embCmd = this.embCmd;
if (discrimMapping != null) {
Object discrimValue = discrimMapping.getObject(ec, rs, new int[] { param[n] });
String className = ec.getMetaDataManager().getClassNameFromDiscriminatorValue((String) discrimValue, discrimMetaData);
embCmd = storeMgr.getMetaDataManager().getMetaDataForClass(className, clr);
n++;
}
// Create a persistable to put the values into
Class embeddedType = clr.classForName(embCmd.getFullClassName());
if (mmd.getFieldTypes() != null && mmd.getFieldTypes().length > 0) {
// Embedded type has field-type defined so use that as our embedded type
embeddedType = ec.getClassLoaderResolver().classForName(mmd.getFieldTypes()[0]);
}
ObjectProvider embOP = ec.getNucleusContext().getObjectProviderFactory().newForHollow(ec, embeddedType, null);
embOP.setPcObjectType(objectType);
value = embOP.getObject();
String nullColumn = null;
String nullValue = null;
if (emd != null) {
nullColumn = emd.getNullIndicatorColumn();
nullValue = emd.getNullIndicatorValue();
}
// Populate the field values
for (int i = 0; i < javaTypeMappings.size(); i++) {
JavaTypeMapping mapping = javaTypeMappings.get(i);
int embAbsFieldNum = embCmd.getAbsolutePositionOfMember(mapping.getMemberMetaData().getName());
if (embAbsFieldNum >= 0) {
// Mapping for field that is present in this embedded type, so set the field
if (mapping instanceof EmbeddedPCMapping) {
// We have a nested embedded
int numSubParams = mapping.getNumberOfDatastoreMappings();
int[] subParam = new int[numSubParams];
int k = 0;
for (int j = n; j < n + numSubParams; j++) {
subParam[k++] = param[j];
}
n += numSubParams;
// Use the sub-object mapping to extract the value for that object
Object subValue = mapping.getObject(ec, rs, subParam, embOP, embAbsFieldNum);
if (subValue != null) {
embOP.replaceField(embAbsFieldNum, subValue);
}
// TODO Check the null column and its value in the sub-embedded ?
} else {
if (mapping.getNumberOfDatastoreMappings() > 0) {
// Extract the value(s) for this field and update the PC if it is not null
int[] posMapping = new int[mapping.getNumberOfDatastoreMappings()];
for (int j = 0; j < posMapping.length; j++) {
posMapping[j] = param[n++];
}
Object fieldValue = mapping.getObject(ec, rs, posMapping);
// Check for the null column and its value and break if this matches the null check
if (nullColumn != null && mapping.getMemberMetaData().getColumnMetaData()[0].getName().equals(nullColumn)) {
if ((nullValue == null && fieldValue == null) || (nullValue != null && fieldValue != null && fieldValue.toString().equals(nullValue))) {
value = null;
break;
}
}
// Set the field value
if (fieldValue != null) {
embOP.replaceField(embAbsFieldNum, fieldValue);
} else {
// If the value is null, but the field is not a primitive update it
AbstractMemberMetaData embFmd = embCmd.getMetaDataForManagedMemberAtAbsolutePosition(embAbsFieldNum);
if (!embFmd.getType().isPrimitive()) {
embOP.replaceField(embAbsFieldNum, fieldValue);
}
}
}
}
} else {
// Mapping not present in this embedded type so maybe subclass, so just omit the positions
int numSubParams = mapping.getNumberOfDatastoreMappings();
n += numSubParams;
}
}
// Update owner field in the element (if present)
if (emd != null) {
String ownerField = emd.getOwnerMember();
if (ownerField != null) {
int ownerFieldNumberInElement = embCmd.getAbsolutePositionOfMember(ownerField);
if (ownerFieldNumberInElement >= 0) {
embOP.replaceField(ownerFieldNumberInElement, ownerOP != null ? ownerOP.getObject() : null);
}
}
}
// Register the owner-embedded ObjectProvider relation now we have values set
if (value != null && ownerOP != null) {
ec.registerEmbeddedRelation(ownerOP, ownerFieldNumber, embOP);
}
return value;
}
Aggregations