use of org.datanucleus.state.DNStateManager in project datanucleus-rdbms by datanucleus.
the class MultiPersistableMapping method setObject.
/**
* Sets the specified positions in the PreparedStatement associated with this field, and value.
* If the number of positions in "pos" is not the same as the number of datastore mappings then it is assumed
* that we should only set the positions for the real implementation FK; this happens where we have a statement
* like "... WHERE IMPL1_ID_OID = ? AND IMPL2_ID_OID IS NULL" so we need to filter on the other implementations
* being null and only want to input parameter(s) for the real implementation of "value".
* @param ec execution context
* @param ps a datastore object that executes statements in the database
* @param value the value stored in this field
* @param ownerSM the owner StateManager
* @param ownerFieldNumber the owner absolute field number
* @param pos The position(s) of the PreparedStatement to populate
*/
@Override
public void setObject(ExecutionContext ec, PreparedStatement ps, int[] pos, Object value, DNStateManager ownerSM, int ownerFieldNumber) {
boolean setValueFKOnly = false;
if (pos != null && pos.length < getNumberOfColumnMappings()) {
setValueFKOnly = true;
}
// Make sure that this field has a sub-mapping appropriate for the specified value
int javaTypeMappingNumber = getMappingNumberForValue(ec, value);
if (value != null && javaTypeMappingNumber == -1) {
// TODO Change this to a multiple field mapping localised message
throw new ClassCastException(Localiser.msg("041044", mmd != null ? mmd.getFullFieldName() : "", getType(), value.getClass().getName()));
}
if (value != null) {
ApiAdapter api = ec.getApiAdapter();
ClassLoaderResolver clr = ec.getClassLoaderResolver();
// Make sure the value is persisted if it is persistable in its own right
if (!ec.isInserting(value)) {
// Object either already exists, or is not yet being inserted.
Object id = api.getIdForObject(value);
// Check if the persistable exists in this datastore
boolean requiresPersisting = false;
if (ec.getApiAdapter().isDetached(value) && ownerSM != null) {
// Detached object that needs attaching (or persisting if detached from a different datastore)
requiresPersisting = true;
} else if (id == null) {
// Transient object, so we need to persist it
requiresPersisting = true;
} else {
ExecutionContext valueEC = api.getExecutionContext(value);
if (valueEC != null && ec != valueEC) {
throw new NucleusUserException(Localiser.msg("041015"), id);
}
}
if (requiresPersisting) {
// The object is either not yet persistent or is detached and so needs attaching
Object pcNew = ec.persistObjectInternal(value, null, -1, PersistableObjectType.PC);
ec.flushInternal(false);
id = api.getIdForObject(pcNew);
if (ec.getApiAdapter().isDetached(value) && ownerSM != null) {
// Update any detached reference to refer to the attached variant
ownerSM.replaceFieldMakeDirty(ownerFieldNumber, pcNew);
if (mmd != null) {
RelationType relationType = mmd.getRelationType(clr);
if (relationType == RelationType.ONE_TO_ONE_BI) {
DNStateManager relatedSM = ec.findStateManager(pcNew);
AbstractMemberMetaData[] relatedMmds = mmd.getRelatedMemberMetaData(clr);
// TODO Allow for multiple related fields
relatedSM.replaceFieldMakeDirty(relatedMmds[0].getAbsoluteFieldNumber(), ownerSM.getObject());
} else if (relationType == RelationType.MANY_TO_ONE_BI) {
// TODO Update the container element with the attached variant
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug("PCMapping.setObject : object " + ownerSM.getInternalObjectId() + " has field " + ownerFieldNumber + " that is 1-N bidirectional - should really update the reference in the relation. Not yet supported");
}
}
}
}
}
if (getNumberOfColumnMappings() <= 0) {
// If the field doesn't map to any columns, omit the set process
return;
}
}
}
if (pos == null) {
return;
}
DNStateManager sm = (value != null ? ec.findStateManager(value) : null);
try {
if (sm != null) {
sm.setStoringPC();
}
int n = 0;
NotYetFlushedException notYetFlushed = null;
for (int i = 0; i < javaTypeMappings.length; i++) {
// Set the PreparedStatement positions for this implementation mapping
int[] posMapping;
if (setValueFKOnly) {
// Only using first "pos" value(s)
n = 0;
} else if (n >= pos.length) {
// store all implementations to the same columns, so we reset the index
n = 0;
}
if (javaTypeMappings[i].getReferenceMapping() != null) {
posMapping = new int[javaTypeMappings[i].getReferenceMapping().getNumberOfColumnMappings()];
} else {
posMapping = new int[javaTypeMappings[i].getNumberOfColumnMappings()];
}
for (int j = 0; j < posMapping.length; j++) {
posMapping[j] = pos[n++];
}
try {
if (javaTypeMappingNumber == -2 || (value != null && javaTypeMappingNumber == i)) {
// This mapping is where the value is to be stored, or using persistent interfaces
javaTypeMappings[i].setObject(ec, ps, posMapping, value);
} else if (!setValueFKOnly) {
// Set null for this mapping, since the value is null or is for something else
javaTypeMappings[i].setObject(ec, ps, posMapping, null);
}
} catch (NotYetFlushedException e) {
notYetFlushed = e;
}
}
if (notYetFlushed != null) {
throw notYetFlushed;
}
} finally {
if (sm != null) {
sm.unsetStoringPC();
}
}
}
use of org.datanucleus.state.DNStateManager in project datanucleus-rdbms by datanucleus.
the class OracleCollectionMapping method postUpdate.
public void postUpdate(DNStateManager ownerSM) {
if (containerIsStoredInSingleColumn()) {
ExecutionContext ec = ownerSM.getExecutionContext();
Collection value = (Collection) ownerSM.provideField(mmd.getAbsoluteFieldNumber());
if (value != null) {
if (mmd.getCollection().elementIsPersistent()) {
// Make sure all persistable elements have StateManagers
Object[] collElements = value.toArray();
for (Object elem : collElements) {
if (elem != null) {
DNStateManager elemSM = ec.findStateManager(elem);
if (elemSM == null || ec.getApiAdapter().getExecutionContext(elem) == null) {
elemSM = ec.getNucleusContext().getStateManagerFactory().newForEmbedded(ec, elem, false, ownerSM, mmd.getAbsoluteFieldNumber(), PersistableObjectType.EMBEDDED_COLLECTION_ELEMENT_PC);
}
}
}
}
}
} else {
super.postUpdate(ownerSM);
}
}
use of org.datanucleus.state.DNStateManager in project datanucleus-rdbms by datanucleus.
the class OracleCollectionMapping method postInsert.
public void postInsert(DNStateManager ownerSM) {
if (containerIsStoredInSingleColumn()) {
ExecutionContext ec = ownerSM.getExecutionContext();
Collection value = (Collection) ownerSM.provideField(mmd.getAbsoluteFieldNumber());
if (value != null) {
if (mmd.getCollection().elementIsPersistent()) {
// Make sure all persistable elements have StateManagers
Object[] collElements = value.toArray();
for (Object elem : collElements) {
if (elem != null) {
DNStateManager elemSM = ec.findStateManager(elem);
if (elemSM == null || ec.getApiAdapter().getExecutionContext(elem) == null) {
elemSM = ec.getNucleusContext().getStateManagerFactory().newForEmbedded(ec, elem, false, ownerSM, mmd.getAbsoluteFieldNumber(), PersistableObjectType.EMBEDDED_COLLECTION_ELEMENT_PC);
}
}
}
}
}
} else {
super.postInsert(ownerSM);
}
}
use of org.datanucleus.state.DNStateManager in project datanucleus-rdbms by datanucleus.
the class SerialisedReferenceMapping method setObject.
/**
* Method to populate parameter positions in a PreparedStatement with this object
* @param ec execution context
* @param ps The Prepared Statement
* @param exprIndex The parameter positions to populate
* @param value The value of the PC to use in populating the parameter positions
* @param ownerSM StateManager for the owning object
* @param fieldNumber field number of this object in the owning object
*/
@Override
public void setObject(ExecutionContext ec, PreparedStatement ps, int[] exprIndex, Object value, DNStateManager ownerSM, int fieldNumber) {
ApiAdapter api = ec.getApiAdapter();
if (api.isPersistable(value)) {
// Assign a StateManager to the serialised object if none present
DNStateManager embSM = ec.findStateManager(value);
if (embSM == null || api.getExecutionContext(value) == null) {
embSM = ec.getNucleusContext().getStateManagerFactory().newForEmbedded(ec, value, false, ownerSM, fieldNumber, PersistableObjectType.EMBEDDED_PC);
}
}
DNStateManager sm = null;
if (api.isPersistable(value)) {
// Find SM for serialised PC object
sm = ec.findStateManager(value);
}
if (sm != null) {
sm.setStoringPC();
}
getColumnMapping(0).setObject(ps, exprIndex[0], value);
if (sm != null) {
sm.unsetStoringPC();
}
}
use of org.datanucleus.state.DNStateManager 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)) {
DNStateManager sm = ec.findStateManager(value);
if (sm == null) {
// Referenced object is not yet persistent, so persist it
ec.persistObjectInternal(value, null, -1, PersistableObjectType.PC);
sm = ec.findStateManager(value);
// Make sure the object is in the datastore so the id is set
sm.flush();
}
String refString = null;
if (mappingStrategy == ID_MAPPING) {
refString = value.getClass().getName() + ":" + sm.getInternalObjectId();
} else if (mappingStrategy == XCALIA_MAPPING) {
AbstractClassMetaData cmd = sm.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(sm.getInternalObjectId());
} else {
refString = definer + ":" + sm.getInternalObjectId().toString();
}
}
return refString;
}
// Cater for non-persistable objects
throw new NucleusException("Identity mapping of non-persistable interface/Object fields not supported");
}
Aggregations