try
{
VersionMetaData vermd = table.getVersionMetaData();
ExecutionContext ec = sm.getExecutionContext();
RDBMSStoreManager storeMgr = (RDBMSStoreManager)ec.getStoreManager();
if (vermd != null && vermd.getFieldName() != null)
{
// Version field - Update the version in the object
AbstractMemberMetaData verfmd =
((AbstractClassMetaData)vermd.getParent()).getMetaDataForMember(vermd.getFieldName());
Object currentVersion = ec.getApiAdapter().getVersion(sm);
if (currentVersion instanceof Number)
{
// Cater for Integer based versions
currentVersion = Long.valueOf(((Number)currentVersion).longValue());
}
Object nextOptimisticVersion = VersionHelper.getNextVersion(table.getVersionMetaData().getVersionStrategy(), currentVersion);
if (verfmd.getType() == Integer.class || verfmd.getType() == int.class)
{
// Cater for Integer based versions TODO Generalise this
nextOptimisticVersion = Integer.valueOf(((Long)nextOptimisticVersion).intValue());
}
sm.replaceField(verfmd.getAbsoluteFieldNumber(), nextOptimisticVersion);
}
// Set the state to "inserting" (may already be at this state if multiple inheritance level INSERT)
sm.changeActivityState(ActivityState.INSERTING);
SQLController sqlControl = storeMgr.getSQLController();
ManagedConnection mconn = storeMgr.getConnection(ec);
try
{
PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, insertStmt, batch);
try
{
StatementClassMapping mappingDefinition = new StatementClassMapping();
StatementMappingIndex[] idxs = stmtMappings;
for (int i=0;i<idxs.length;i++)
{
if (idxs[i] != null)
{
mappingDefinition.addMappingForMember(i, idxs[i]);
}
}
// Provide the primary key field(s)
if (table.getIdentityType() == IdentityType.DATASTORE)
{
if (!table.isObjectIdDatastoreAttributed() || !table.isBaseDatastoreClass())
{
int[] paramNumber = {IDPARAMNUMBER};
table.getDatastoreObjectIdMapping().setObject(ec, ps, paramNumber, sm.getInternalObjectId());
}
}
else if (table.getIdentityType() == IdentityType.APPLICATION)
{
sm.provideFields(pkFieldNumbers,
storeMgr.getFieldManagerForStatementGeneration(sm, ps, mappingDefinition, true));
}
// Provide all non-key fields needed for the insert.
// This provides "persistence-by-reachability" for these fields
int numberOfFieldsToProvide = 0;
for (int i = 0; i < insertFieldNumbers.length; i++)
{
if (insertFieldNumbers[i] < sm.getClassMetaData().getMemberCount())
{
numberOfFieldsToProvide++;
}
}
int j = 0;
int[] classFieldNumbers = new int[numberOfFieldsToProvide];
for (int i = 0; i < insertFieldNumbers.length; i++)
{
if (insertFieldNumbers[i] < sm.getClassMetaData().getMemberCount())
{
classFieldNumbers[j++] = insertFieldNumbers[i];
}
}
sm.provideFields(classFieldNumbers,
storeMgr.getFieldManagerForStatementGeneration(sm, ps, mappingDefinition, true));
if (table.getVersionMapping(false) != null)
{
// Surrogate version - set the new version for the object
Object currentVersion = ec.getApiAdapter().getVersion(sm);
Object nextOptimisticVersion = VersionHelper.getNextVersion(table.getVersionMetaData().getVersionStrategy(), currentVersion);
for (int k=0;k<versionStmtMapping.getNumberOfParameterOccurrences();k++)
{
table.getVersionMapping(false).setObject(ec, ps,
versionStmtMapping.getParameterPositionsForOccurrence(k), nextOptimisticVersion);
}
sm.setTransactionalVersion(nextOptimisticVersion);
}
else if (vermd != null && vermd.getFieldName() != null)
{
// Version field - set the new version for the object
Object currentVersion = ec.getApiAdapter().getVersion(sm);
Object nextOptimisticVersion = VersionHelper.getNextVersion(table.getVersionMetaData().getVersionStrategy(), currentVersion);
sm.setTransactionalVersion(nextOptimisticVersion);
}
// Discriminator mapping (optional)
if (table.getDiscriminatorMapping(false) != null)
{
DiscriminatorMetaData dismd = table.getDiscriminatorMetaData();
if (dismd.getStrategy() == DiscriminatorStrategy.CLASS_NAME)
{
for (int k=0;k<discriminatorStmtMapping.getNumberOfParameterOccurrences();k++)
{
table.getDiscriminatorMapping(false).setObject(ec, ps,
discriminatorStmtMapping.getParameterPositionsForOccurrence(k),
sm.getObject().getClass().getName());
}
}
else if (dismd.getStrategy() == DiscriminatorStrategy.VALUE_MAP)
{
// Use Discriminator info for the actual class
dismd = sm.getClassMetaData().getInheritanceMetaData().getDiscriminatorMetaData();
for (int k=0;k<discriminatorStmtMapping.getNumberOfParameterOccurrences();k++)
{
table.getDiscriminatorMapping(false).setObject(ec, ps,
discriminatorStmtMapping.getParameterPositionsForOccurrence(k), dismd.getValue());
}
}
}
// External FK columns (optional)
if (externalFKStmtMappings != null)
{
for (int i=0;i<externalFKStmtMappings.length;i++)
{
Object fkValue = sm.getAssociatedValue(externalFKStmtMappings[i].getMapping());
if (fkValue != null)
{
// Need to provide the owner field number so PCMapping can work out if it is inserted yet
AbstractMemberMetaData ownerFmd =
table.getMetaDataForExternalMapping(externalFKStmtMappings[i].getMapping(),
MappingConsumer.MAPPING_TYPE_EXTERNAL_FK);
for (int k=0;k<externalFKStmtMappings[i].getNumberOfParameterOccurrences();k++)
{
externalFKStmtMappings[i].getMapping().setObject(ec, ps,
externalFKStmtMappings[i].getParameterPositionsForOccurrence(k),
fkValue, null, ownerFmd.getAbsoluteFieldNumber());
}
}
else
{
// We're inserting a null so dont need the owner field
for (int k=0;k<externalFKStmtMappings[i].getNumberOfParameterOccurrences();k++)
{
externalFKStmtMappings[i].getMapping().setObject(ec, ps,
externalFKStmtMappings[i].getParameterPositionsForOccurrence(k), null);
}
}
}
}
// External FK discriminator columns (optional)
if (externalFKDiscrimStmtMappings != null)
{
for (int i=0;i<externalFKDiscrimStmtMappings.length;i++)
{
Object discrimValue = sm.getAssociatedValue(externalFKDiscrimStmtMappings[i].getMapping());
for (int k=0;k<externalFKDiscrimStmtMappings[i].getNumberOfParameterOccurrences();k++)
{
externalFKDiscrimStmtMappings[i].getMapping().setObject(ec, ps,
externalFKDiscrimStmtMappings[i].getParameterPositionsForOccurrence(k), discrimValue);
}
}
}
// External order columns (optional)
if (externalOrderStmtMappings != null)
{
for (int i=0;i<externalOrderStmtMappings.length;i++)
{
Object orderValue = sm.getAssociatedValue(externalOrderStmtMappings[i].getMapping());
if (orderValue == null)
{
// No order value so use -1
orderValue = Integer.valueOf(-1);
}
for (int k=0;k<externalOrderStmtMappings[i].getNumberOfParameterOccurrences();k++)
{
externalOrderStmtMappings[i].getMapping().setObject(ec, ps,
externalOrderStmtMappings[i].getParameterPositionsForOccurrence(k), orderValue);
}
}
}
sqlControl.executeStatementUpdate(mconn, insertStmt, ps, !batch);
if (hasIdentityColumn)
{
// Identity was set in the datastore using auto-increment/identity/serial etc
Object newId = getInsertedDatastoreIdentity(ec, sqlControl, sm, mconn, ps);
if (NucleusLogger.DATASTORE_PERSIST.isDebugEnabled())
{
NucleusLogger.DATASTORE_PERSIST.debug(LOCALISER.msg("052206",
sm.toPrintableID(), newId));
}
sm.setPostStoreNewObjectId(newId);
}
// Execute any mapping actions on the insert of the fields (e.g Oracle CLOBs/BLOBs)
for (int i = 0; i < callbacks.length; ++i)
{
if (NucleusLogger.PERSISTENCE.isDebugEnabled())
{
NucleusLogger.PERSISTENCE.debug(LOCALISER.msg("052222",
sm.toPrintableID(),
((JavaTypeMapping)callbacks[i]).getMemberMetaData().getFullFieldName()));
}
callbacks[i].insertPostProcessing(sm);
}
// Update the insert status for this table via the StoreManager
storeMgr.setObjectIsInsertedToLevel(sm, table);
// Make sure all relation fields (1-1, N-1 with FK) we processed in the INSERT are attached.
// This is necessary because with a bidir relation and the other end attached we can just
// do the INSERT above first and THEN attach the other end here
// (if we did it the other way around we would get a NotYetFlushedException thrown above).
for (int i=0;i<relationFieldNumbers.length;i++)
{
Object value = sm.provideField(relationFieldNumbers[i]);
if (value != null && ec.getApiAdapter().isDetached(value))
{
Object valueAttached = ec.persistObjectInternal(value, null, -1, ObjectProvider.PC);
sm.replaceField(relationFieldNumbers[i], valueAttached);
}
}
// Perform reachability on all fields that have no datastore column (1-1 bi non-owner, N-1 bi join)
int numberOfReachableFields = 0;
for (int i = 0; i < reachableFieldNumbers.length; i++)
{
if (reachableFieldNumbers[i] < sm.getClassMetaData().getMemberCount())
{
numberOfReachableFields++;
}
}
classFieldNumbers = new int[numberOfReachableFields];
j = 0;
for (int i = 0; i < reachableFieldNumbers.length; i++)
{
if (reachableFieldNumbers[i] < sm.getClassMetaData().getMemberCount())
{
classFieldNumbers[j++] = reachableFieldNumbers[i];
}
}
mappingDefinition = new StatementClassMapping();
idxs = retrievedStmtMappings;
for (int i=0;i<idxs.length;i++)
{
if (idxs[i] != null)
{
mappingDefinition.addMappingForMember(i, idxs[i]);
}
}
sm.provideFields(classFieldNumbers,
storeMgr.getFieldManagerForStatementGeneration(sm, ps, mappingDefinition, true));
}
finally
{
sqlControl.closeStatement(mconn, ps);
}