use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class OracleClobRDBMSMapping method updateClobColumn.
/**
* Convenience method to update the contents of a CLOB column.
* Oracle requires that a CLOB is initialised with EMPTY_CLOB() and then you retrieve
* the column and update its CLOB value. Performs a statement
* <pre>
* SELECT {clobColumn} FROM TABLE WHERE ID=? FOR UPDATE
* </pre>
* and then updates the Clob value returned.
* @param op ObjectProvider of the object
* @param table Table storing the CLOB column
* @param mapping Datastore mapping for the CLOB column
* @param value The value to store in the CLOB
* @throws NucleusObjectNotFoundException Thrown if an object is not found
* @throws NucleusDataStoreException Thrown if an error occurs in datastore communication
*/
@SuppressWarnings("deprecation")
public static void updateClobColumn(ObjectProvider op, Table table, DatastoreMapping mapping, String value) {
ExecutionContext ec = op.getExecutionContext();
RDBMSStoreManager storeMgr = table.getStoreManager();
// Don't support join tables yet
DatastoreClass classTable = (DatastoreClass) table;
SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
// Generate "SELECT {clobColumn} FROM TABLE WHERE ID=? FOR UPDATE" statement
SelectStatement sqlStmt = new SelectStatement(storeMgr, table, null, null);
sqlStmt.setClassLoaderResolver(ec.getClassLoaderResolver());
sqlStmt.addExtension(SQLStatement.EXTENSION_LOCK_FOR_UPDATE, true);
SQLTable blobSqlTbl = SQLStatementHelper.getSQLTableForMappingOfTable(sqlStmt, sqlStmt.getPrimaryTable(), mapping.getJavaTypeMapping());
sqlStmt.select(blobSqlTbl, mapping.getColumn(), null);
StatementClassMapping mappingDefinition = new StatementClassMapping();
AbstractClassMetaData cmd = op.getClassMetaData();
int inputParamNum = 1;
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
// Datastore identity value for input
JavaTypeMapping datastoreIdMapping = classTable.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false);
SQLExpression expr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), datastoreIdMapping);
SQLExpression val = exprFactory.newLiteralParameter(sqlStmt, datastoreIdMapping, null, "ID");
sqlStmt.whereAnd(expr.eq(val), true);
StatementMappingIndex datastoreIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
if (datastoreIdx == null) {
datastoreIdx = new StatementMappingIndex(datastoreIdMapping);
mappingDefinition.addMappingForMember(SurrogateColumnType.DATASTORE_ID.getFieldNumber(), datastoreIdx);
}
datastoreIdx.addParameterOccurrence(new int[] { inputParamNum });
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
// Application identity value(s) for input
int[] pkNums = cmd.getPKMemberPositions();
for (int i = 0; i < pkNums.length; i++) {
AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkNums[i]);
JavaTypeMapping pkMapping = classTable.getMemberMapping(mmd);
SQLExpression expr = exprFactory.newExpression(sqlStmt, sqlStmt.getPrimaryTable(), pkMapping);
SQLExpression val = exprFactory.newLiteralParameter(sqlStmt, pkMapping, null, "PK" + i);
sqlStmt.whereAnd(expr.eq(val), true);
StatementMappingIndex pkIdx = mappingDefinition.getMappingForMemberPosition(pkNums[i]);
if (pkIdx == null) {
pkIdx = new StatementMappingIndex(pkMapping);
mappingDefinition.addMappingForMember(pkNums[i], pkIdx);
}
int[] inputParams = new int[pkMapping.getNumberOfDatastoreMappings()];
for (int j = 0; j < pkMapping.getNumberOfDatastoreMappings(); j++) {
inputParams[j] = inputParamNum++;
}
pkIdx.addParameterOccurrence(inputParams);
}
}
String textStmt = sqlStmt.getSQLText().toSQL();
if (op.isEmbedded()) {
// This mapping is embedded, so navigate back to the real owner since that is the "id" in the table
ObjectProvider[] embeddedOwners = ec.getOwnersForEmbeddedObjectProvider(op);
if (embeddedOwners != null) {
// Just use the first owner
// TODO Should check if the owner is stored in this table
op = embeddedOwners[0];
}
}
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
PreparedStatement ps = sqlControl.getStatementForQuery(mconn, textStmt);
try {
// Provide the primary key field(s) to the JDBC statement
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
StatementMappingIndex datastoreIdx = mappingDefinition.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
for (int i = 0; i < datastoreIdx.getNumberOfParameterOccurrences(); i++) {
classTable.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false).setObject(ec, ps, datastoreIdx.getParameterPositionsForOccurrence(i), op.getInternalObjectId());
}
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
op.provideFields(cmd.getPKMemberPositions(), new ParameterSetter(op, ps, mappingDefinition));
}
ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, textStmt, ps);
try {
if (!rs.next()) {
throw new NucleusObjectNotFoundException("No such database row", op.getInternalObjectId());
}
DatastoreAdapter dba = storeMgr.getDatastoreAdapter();
int jdbcMajorVersion = dba.getDriverMajorVersion();
if (dba.getDatastoreDriverName().equalsIgnoreCase(OracleAdapter.OJDBC_DRIVER_NAME) && jdbcMajorVersion < 10) {
// Oracle JDBC drivers version 9 and below use some sh*tty Oracle-specific CLOB type
// we have to cast to that, face west, pray whilst saying ommmmmmmmmmm
oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob(1);
if (clob != null) {
// Deprecated but what can you do
clob.putString(1, value);
}
} else {
// Oracle JDBC drivers 10 and above supposedly use the JDBC standard class for Clobs
java.sql.Clob clob = rs.getClob(1);
if (clob != null) {
clob.setString(1, value);
}
}
} finally {
rs.close();
}
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException e) {
throw new NucleusDataStoreException("Update of CLOB value failed: " + textStmt, e);
}
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class CollectionMapping method postUpdate.
/**
* Method to be called after any update of the owner class element.
* This method could be called in two situations
* <ul>
* <li>Update a collection field of an object by replacing the collection with a new collection, so UpdateRequest is called, which calls here</li>
* <li>Persist a new object, and it needed to wait til the element was inserted so goes into dirty state and then flush() triggers UpdateRequest, which comes here</li>
* </ul>
* @param ownerOP ObjectProvider of the owner
*/
public void postUpdate(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 collElement : collElements) {
if (collElement != null) {
ObjectProvider elemOP = ec.findObjectProvider(collElement);
if (elemOP == null || ec.getApiAdapter().getExecutionContext(collElement) == null) {
elemOP = ec.getNucleusContext().getObjectProviderFactory().newForEmbedded(ec, collElement, false, ownerOP, mmd.getAbsoluteFieldNumber());
}
}
}
}
}
return;
}
if (value == null) {
// remove any elements in the collection and replace it with an empty SCO wrapper
((CollectionStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, null)).clear(ownerOP);
replaceFieldWithWrapper(ownerOP, null);
return;
}
if (value instanceof BackedSCO) {
// Already have a SCO value, so flush outstanding updates
ownerOP.getExecutionContext().flushOperationsForBackingStore(((BackedSCO) value).getBackingStore(), ownerOP);
return;
}
if (mmd.isCascadeUpdate()) {
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("007009", mmd.getFullFieldName()));
}
CollectionStore backingStore = ((CollectionStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, value.getClass()));
backingStore.update(ownerOP, value);
// Replace the field with a wrapper containing these elements
replaceFieldWithWrapper(ownerOP, value);
} else {
// User doesn't want to update by reachability
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("007008", mmd.getFullFieldName()));
}
return;
}
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class ArrayMapping method postUpdate.
/**
* Method to be called after any update of the owner class element.
* This method could be called in two situations
* <ul>
* <li>Update an array field of an object by replacing the array with a new array,
* so UpdateRequest is called, which calls here</li>
* <li>Persist a new object, and it needed to wait til the element was inserted so
* goes into dirty state and then flush() triggers UpdateRequest, which comes here</li>
* </ul>
* @param ownerOP ObjectProvider of the owner
*/
public void postUpdate(ObjectProvider ownerOP) {
ExecutionContext ec = ownerOP.getExecutionContext();
Object value = ownerOP.provideField(getAbsoluteFieldNumber());
if (containerIsStoredInSingleColumn()) {
if (value != null) {
if (mmd.getArray().elementIsPersistent()) {
// Make sure all persistable elements have ObjectProviders
Object[] arrElements = (Object[]) value;
for (Object elem : arrElements) {
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) {
// array is now null so remove any elements in the array
((ArrayStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, null)).clear(ownerOP);
return;
}
if (!mmd.isCascadeUpdate()) {
// User doesn't want to update by reachability
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("007008", mmd.getFullFieldName()));
}
return;
}
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("007009", mmd.getFullFieldName()));
}
// Update the datastore
// TODO Do this more efficiently, removing elements no longer present, and adding new ones
ArrayStore backingStore = (ArrayStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, null);
backingStore.clear(ownerOP);
backingStore.set(ownerOP, value);
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class LocateBulkRequest method processResults.
private ObjectProvider[] processResults(ResultSet rs, ObjectProvider[] ops) throws SQLException {
List<ObjectProvider> missingOps = new ArrayList<>();
for (int i = 0; i < ops.length; i++) {
missingOps.add(ops[i]);
}
ExecutionContext ec = ops[0].getExecutionContext();
while (rs.next()) {
FieldManager resultFM = new ResultSetGetter(ec, rs, resultMapping, cmd);
Object id = null;
Object key = null;
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
StatementMappingIndex idx = resultMapping.getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
JavaTypeMapping idMapping = idx.getMapping();
key = idMapping.getObject(ec, rs, idx.getColumnPositions());
if (IdentityUtils.isDatastoreIdentity(key)) {
// If mapping is OIDMapping then returns an OID rather than the column value
key = IdentityUtils.getTargetKeyForDatastoreIdentity(key);
}
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
if (cmd.usesSingleFieldIdentityClass()) {
int[] pkFieldNums = cmd.getPKMemberPositions();
AbstractMemberMetaData pkMmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkFieldNums[0]);
if (pkMmd.getType() == int.class) {
key = resultFM.fetchIntField(pkFieldNums[0]);
} else if (pkMmd.getType() == short.class) {
key = resultFM.fetchShortField(pkFieldNums[0]);
} else if (pkMmd.getType() == long.class) {
key = resultFM.fetchLongField(pkFieldNums[0]);
} else if (pkMmd.getType() == char.class) {
key = resultFM.fetchCharField(pkFieldNums[0]);
} else if (pkMmd.getType() == boolean.class) {
key = resultFM.fetchBooleanField(pkFieldNums[0]);
} else if (pkMmd.getType() == byte.class) {
key = resultFM.fetchByteField(pkFieldNums[0]);
} else if (pkMmd.getType() == double.class) {
key = resultFM.fetchDoubleField(pkFieldNums[0]);
} else if (pkMmd.getType() == float.class) {
key = resultFM.fetchFloatField(pkFieldNums[0]);
} else if (pkMmd.getType() == String.class) {
key = resultFM.fetchStringField(pkFieldNums[0]);
} else {
key = resultFM.fetchObjectField(pkFieldNums[0]);
}
} else {
id = IdentityUtils.getApplicationIdentityForResultSetRow(ec, cmd, null, true, resultFM);
}
}
// Find which ObjectProvider this row is for
ObjectProvider op = null;
for (ObjectProvider missingOp : missingOps) {
Object opId = missingOp.getInternalObjectId();
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
Object opKey = IdentityUtils.getTargetKeyForDatastoreIdentity(opId);
if (key != null && opKey.getClass() != key.getClass()) {
opKey = TypeConversionHelper.convertTo(opKey, key.getClass());
}
if (opKey.equals(key)) {
op = missingOp;
break;
}
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
if (cmd.usesSingleFieldIdentityClass()) {
Object opKey = IdentityUtils.getTargetKeyForSingleFieldIdentity(opId);
if (opKey.equals(key)) {
op = missingOp;
break;
}
} else {
if (opId.equals(id)) {
op = missingOp;
break;
}
}
}
}
if (op != null) {
// Mark ObjectProvider as processed
missingOps.remove(op);
// Load up any unloaded fields that we have selected
int[] selectedMemberNums = resultMapping.getMemberNumbers();
int[] unloadedMemberNums = ClassUtils.getFlagsSetTo(op.getLoadedFields(), selectedMemberNums, false);
if (unloadedMemberNums != null && unloadedMemberNums.length > 0) {
op.replaceFields(unloadedMemberNums, resultFM);
}
// Load version if present and not yet set
JavaTypeMapping versionMapping = table.getSurrogateMapping(SurrogateColumnType.VERSION, false);
if (op.getTransactionalVersion() == null && versionMapping != null) {
VersionMetaData currentVermd = table.getVersionMetaData();
Object datastoreVersion = null;
if (currentVermd != null) {
if (currentVermd.getFieldName() == null) {
// Surrogate version
// Why use true now?
versionMapping = table.getSurrogateMapping(SurrogateColumnType.VERSION, true);
StatementMappingIndex verIdx = resultMapping.getMappingForMemberPosition(SurrogateColumnType.VERSION.getFieldNumber());
datastoreVersion = versionMapping.getObject(ec, rs, verIdx.getColumnPositions());
} else {
datastoreVersion = op.provideField(cmd.getAbsolutePositionOfMember(currentVermd.getFieldName()));
}
op.setVersion(datastoreVersion);
}
}
}
}
if (!missingOps.isEmpty()) {
return missingOps.toArray(new ObjectProvider[missingOps.size()]);
}
return null;
}
use of org.datanucleus.state.ObjectProvider in project datanucleus-rdbms by datanucleus.
the class LocateBulkRequest method execute.
/**
* Method performing the location of the records in the datastore.
* @param ops ObjectProviders to be located
* @throws NucleusObjectNotFoundException with nested exceptions for each of missing objects (if any)
*/
public void execute(ObjectProvider[] ops) {
if (ops == null || ops.length == 0) {
return;
}
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
// Debug information about what we are retrieving
StringBuilder str = new StringBuilder();
for (int i = 0; i < ops.length; i++) {
if (i > 0) {
str.append(", ");
}
str.append(ops[i].getInternalObjectId());
}
NucleusLogger.PERSISTENCE.debug(Localiser.msg("052223", str.toString(), table));
}
ExecutionContext ec = ops[0].getExecutionContext();
RDBMSStoreManager storeMgr = table.getStoreManager();
AbstractClassMetaData cmd = ops[0].getClassMetaData();
boolean locked = ec.getSerializeReadForClass(cmd.getFullClassName());
LockMode lockType = ec.getLockManager().getLockMode(ops[0].getInternalObjectId());
if (lockType != LockMode.LOCK_NONE) {
if (lockType == LockMode.LOCK_PESSIMISTIC_READ || lockType == LockMode.LOCK_PESSIMISTIC_WRITE) {
// Override with pessimistic lock
locked = true;
}
}
String statement = getStatement(table, ops, locked);
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
PreparedStatement ps = sqlControl.getStatementForQuery(mconn, statement);
try {
// Provide the primary key field(s)
for (int i = 0; i < ops.length; i++) {
if (cmd.getIdentityType() == IdentityType.DATASTORE) {
StatementMappingIndex datastoreIdx = mappingDefinitions[i].getMappingForMemberPosition(SurrogateColumnType.DATASTORE_ID.getFieldNumber());
for (int j = 0; j < datastoreIdx.getNumberOfParameterOccurrences(); j++) {
table.getSurrogateMapping(SurrogateColumnType.DATASTORE_ID, false).setObject(ec, ps, datastoreIdx.getParameterPositionsForOccurrence(j), ops[i].getInternalObjectId());
}
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
ops[i].provideFields(cmd.getPKMemberPositions(), new ParameterSetter(ops[i], ps, mappingDefinitions[i]));
}
}
// Execute the statement
ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, statement, ps);
try {
ObjectProvider[] missingOps = processResults(rs, ops);
if (missingOps != null && missingOps.length > 0) {
NucleusObjectNotFoundException[] nfes = new NucleusObjectNotFoundException[missingOps.length];
for (int i = 0; i < nfes.length; i++) {
nfes[i] = new NucleusObjectNotFoundException("Object not found", missingOps[i].getInternalObjectId());
}
throw new NucleusObjectNotFoundException("Some objects were not found. Look at nested exceptions for details", nfes);
}
} finally {
rs.close();
}
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException sqle) {
String msg = Localiser.msg("052220", ops[0].getObjectAsPrintable(), statement, sqle.getMessage());
NucleusLogger.DATASTORE_RETRIEVE.warn(msg);
List exceptions = new ArrayList();
exceptions.add(sqle);
while ((sqle = sqle.getNextException()) != null) {
exceptions.add(sqle);
}
throw new NucleusDataStoreException(msg, (Throwable[]) exceptions.toArray(new Throwable[exceptions.size()]));
}
}
Aggregations