use of org.datanucleus.ExecutionContext 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.ExecutionContext 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.ExecutionContext in project datanucleus-rdbms by datanucleus.
the class AbstractContainerMapping method replaceFieldWithWrapper.
/**
* Method to replace the field that this mapping represents with a SCO wrapper.
* The wrapper will be suitable for the passed instantiated type and if it is null will be for the declared type of the field.
* @param op ObjectProvider for the owning object
* @param value The value to create the wrapper with
* @return The SCO wrapper object that the field was replaced with
*/
protected SCO replaceFieldWithWrapper(ObjectProvider op, Object value) {
Class type = mmd.getType();
if (value != null) {
type = value.getClass();
} else if (mmd.getOrderMetaData() != null && type.isAssignableFrom(java.util.List.class)) {
type = java.util.List.class;
Store backingStore = storeMgr.getExistingBackingStoreForMember(mmd);
if (backingStore != null && (backingStore instanceof SetStore)) {
// Member has already been instantiated as Set-based, so don't use List
type = mmd.getType();
}
}
ExecutionContext ec = op.getExecutionContext();
if (mmd.getAbsoluteFieldNumber() < 0) {
// The metadata being used here is an embedded form, so swap for the real one
mmd = ec.getMetaDataManager().getMetaDataForClass(mmd.getClassName(true), ec.getClassLoaderResolver()).getMetaDataForMember(mmd.getName());
}
return ec.getTypeManager().createSCOInstance(op, mmd, type, value, true);
}
use of org.datanucleus.ExecutionContext 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.ExecutionContext in project datanucleus-rdbms by datanucleus.
the class AbstractRDBMSQueryResult method registerMemberBulkResultSet.
public void registerMemberBulkResultSet(IteratorStatement iterStmt, ResultSet rs) {
if (bulkLoadedValueByMemberNumber == null) {
bulkLoadedValueByMemberNumber = new HashMap<>();
}
try {
ExecutionContext ec = query.getExecutionContext();
AbstractMemberMetaData mmd = iterStmt.getBackingStore().getOwnerMemberMetaData();
if (mmd.hasCollection() || mmd.hasArray()) {
ElementContainerStore backingStore = (ElementContainerStore) iterStmt.getBackingStore();
if (backingStore.isElementsAreEmbedded() || backingStore.isElementsAreSerialised()) {
int[] param = new int[backingStore.getElementMapping().getNumberOfDatastoreMappings()];
for (int i = 0; i < param.length; ++i) {
param[i] = i + 1;
}
if (backingStore.getElementMapping() instanceof SerialisedPCMapping || backingStore.getElementMapping() instanceof SerialisedReferenceMapping || backingStore.getElementMapping() instanceof EmbeddedElementPCMapping) {
// Element = Serialised
while (rs.next()) {
Object owner = iterStmt.getOwnerMapIndex().getMapping().getObject(ec, rs, iterStmt.getOwnerMapIndex().getColumnPositions());
Object element = backingStore.getElementMapping().getObject(ec, rs, param, ec.findObjectProvider(owner), backingStore.getOwnerMemberMetaData().getAbsoluteFieldNumber());
addOwnerMemberValue(mmd, owner, element);
}
} else {
// Element = Non-PC
while (rs.next()) {
Object owner = iterStmt.getOwnerMapIndex().getMapping().getObject(ec, rs, iterStmt.getOwnerMapIndex().getColumnPositions());
Object element = backingStore.getElementMapping().getObject(ec, rs, param);
addOwnerMemberValue(mmd, owner, element);
}
}
} else if (backingStore.getElementMapping() instanceof ReferenceMapping) {
// Element is Reference (interface/Object) so just use elementMapping
int[] param = new int[backingStore.getElementMapping().getNumberOfDatastoreMappings()];
for (int i = 0; i < param.length; ++i) {
param[i] = i + 1;
}
while (rs.next()) {
Object owner = iterStmt.getOwnerMapIndex().getMapping().getObject(ec, rs, iterStmt.getOwnerMapIndex().getColumnPositions());
Object element = backingStore.getElementMapping().getObject(ec, rs, param);
addOwnerMemberValue(mmd, owner, element);
}
} else {
String elementType = mmd.hasCollection() ? backingStore.getOwnerMemberMetaData().getCollection().getElementType() : backingStore.getOwnerMemberMetaData().getArray().getElementType();
ResultObjectFactory<E> scoROF = new PersistentClassROF(ec, rs, query.getIgnoreCache(), iterStmt.getStatementClassMapping(), backingStore.getElementClassMetaData(), ec.getClassLoaderResolver().classForName(elementType));
while (rs.next()) {
Object owner = iterStmt.getOwnerMapIndex().getMapping().getObject(ec, rs, iterStmt.getOwnerMapIndex().getColumnPositions());
Object element = scoROF.getObject();
addOwnerMemberValue(mmd, owner, element);
}
}
} else if (mmd.hasMap()) {
// TODO Cater for maps
}
} catch (SQLException sqle) {
NucleusLogger.DATASTORE.error("Exception thrown processing bulk loaded field " + iterStmt.getBackingStore().getOwnerMemberMetaData().getFullFieldName(), sqle);
} finally {
// Close the ResultSet (and its Statement)
try {
Statement stmt = null;
try {
stmt = rs.getStatement();
// Close the result set
rs.close();
} catch (SQLException e) {
NucleusLogger.DATASTORE.error(Localiser.msg("052605", e));
} finally {
try {
if (stmt != null) {
// Close the original statement
stmt.close();
}
} catch (SQLException e) {
// Do nothing
}
}
} finally {
rs = null;
}
}
}
Aggregations