use of org.datanucleus.state.DNStateManager in project datanucleus-rdbms by datanucleus.
the class OracleArrayMapping method postUpdate.
/**
* Method to be called after any update of the owner class element.
* @param ownerSM StateManager of the owner
*/
public void postUpdate(DNStateManager ownerSM) {
if (containerIsStoredInSingleColumn()) {
Object value = ownerSM.provideField(mmd.getAbsoluteFieldNumber());
if (value == null) {
return;
}
ExecutionContext ec = ownerSM.getExecutionContext();
if (mmd.getArray().elementIsPersistent()) {
// Make sure all persistable elements have StateManagers
Object[] arrElements = (Object[]) value;
for (Object elem : arrElements) {
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_ARRAY_ELEMENT_PC);
}
}
}
}
} else {
super.postUpdate(ownerSM);
}
}
use of org.datanucleus.state.DNStateManager in project datanucleus-rdbms by datanucleus.
the class SerialisedReferenceMapping method getObject.
/**
* Method to extract the value of the persistable from a ResultSet.
* @param ec execution context
* @param exprIndex The parameter positions in the result set to use.
* @param ownerSM StateManager for the owning object
* @param resultSet The ResultSet
* @param fieldNumber Absolute number of field in owner object
* @return The (deserialised) persistable object
*/
@Override
public Object getObject(ExecutionContext ec, ResultSet resultSet, int[] exprIndex, DNStateManager ownerSM, int fieldNumber) {
Object obj = getColumnMapping(0).getObject(resultSet, exprIndex[0]);
ApiAdapter api = ec.getApiAdapter();
if (api.isPersistable(obj)) {
// Assign a StateManager to the serialised object if none present
DNStateManager embSM = ec.findStateManager(obj);
if (embSM == null || api.getExecutionContext(obj) == null) {
ec.getNucleusContext().getStateManagerFactory().newForEmbedded(ec, obj, false, ownerSM, fieldNumber, PersistableObjectType.EMBEDDED_PC);
}
}
return obj;
}
use of org.datanucleus.state.DNStateManager in project datanucleus-rdbms by datanucleus.
the class MappingHelper method getObjectForApplicationIdentity.
/**
* Get the persistent object instance for a class using application identity defined by the provided result set columns
* @param ec ExecutionContext
* @param mapping The mapping in which this is returned
* @param rs the ResultSet
* @param resultIndexes indexes in the result set to retrieve
* @param cmd the AbstractClassMetaData
* @return the persistent object instance
*/
public static Object getObjectForApplicationIdentity(final ExecutionContext ec, JavaTypeMapping mapping, final ResultSet rs, int[] resultIndexes, AbstractClassMetaData cmd) {
ClassLoaderResolver clr = ec.getClassLoaderResolver();
// Abstract class
if (cmd instanceof ClassMetaData && ((ClassMetaData) cmd).isAbstract() && cmd.getObjectidClass() != null) {
return getObjectForAbstractClass(ec, mapping, rs, resultIndexes, cmd);
}
// Create a ResultSetGetter with the data for the primary key column(s) of this class solely
int totalMemberCount = cmd.getNoOfManagedMembers() + cmd.getNoOfInheritedManagedMembers();
final StatementMappingIndex[] statementExpressionIndex = new StatementMappingIndex[totalMemberCount];
DatastoreClass datastoreClass = mapping.getStoreManager().getDatastoreClass(cmd.getFullClassName(), clr);
final int[] pkMemberPositions = cmd.getPKMemberPositions();
int paramIndex = 0;
for (int i = 0; i < pkMemberPositions.length; ++i) {
AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkMemberPositions[i]);
JavaTypeMapping m = datastoreClass.getMemberMapping(mmd);
statementExpressionIndex[mmd.getAbsoluteFieldNumber()] = new StatementMappingIndex(m);
int[] expressionsIndex = new int[m.getNumberOfColumnMappings()];
for (int j = 0; j < expressionsIndex.length; j++) {
expressionsIndex[j] = resultIndexes[paramIndex++];
}
statementExpressionIndex[mmd.getAbsoluteFieldNumber()].setColumnPositions(expressionsIndex);
}
final StatementClassMapping resultMappings = new StatementClassMapping();
for (int i = 0; i < pkMemberPositions.length; i++) {
resultMappings.addMappingForMember(pkMemberPositions[i], statementExpressionIndex[pkMemberPositions[i]]);
}
// TODO Use any other (non-PK) param values
final FieldManager resultsFM = new ResultSetGetter(ec, rs, resultMappings, cmd);
Object id = IdentityUtils.getApplicationIdentityForResultSetRow(ec, cmd, null, false, resultsFM);
Class type = ec.getClassLoaderResolver().classForName(cmd.getFullClassName());
return ec.findObject(id, new FieldValues() {
public void fetchFields(DNStateManager sm) {
sm.replaceFields(pkMemberPositions, resultsFM);
}
public void fetchNonLoadedFields(DNStateManager sm) {
sm.replaceNonLoadedFields(pkMemberPositions, resultsFM);
}
public FetchPlan getFetchPlanForLoading() {
return ec.getFetchPlan();
}
}, type, false, true);
}
use of org.datanucleus.state.DNStateManager in project datanucleus-rdbms by datanucleus.
the class OracleBlobColumnMapping method setPostProcessing.
@SuppressWarnings("deprecation")
@Override
public void setPostProcessing(DNStateManager sm, Object value) {
// Oracle requires that a BLOB is initialised with EMPTY_BLOB() and then you retrieve the column and update its BLOB value. Performs a statement
// SELECT {blobColumn} FROM TABLE WHERE ID=? FOR UPDATE
// and then updates the Blob value returned.
ExecutionContext ec = sm.getExecutionContext();
byte[] bytes = (byte[]) value;
Table table = column.getTable();
RDBMSStoreManager storeMgr = table.getStoreManager();
if (table instanceof DatastoreClass) {
// BLOB within a primary table
DatastoreClass classTable = (DatastoreClass) table;
// Generate "SELECT {blobColumn} 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);
sqlStmt.select(blobSqlTbl, column, null);
StatementClassMapping mappingDefinition = new StatementClassMapping();
AbstractClassMetaData cmd = sm.getClassMetaData();
SQLExpressionFactory exprFactory = storeMgr.getSQLExpressionFactory();
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.getNumberOfColumnMappings()];
for (int j = 0; j < pkMapping.getNumberOfColumnMappings(); j++) {
inputParams[j] = inputParamNum++;
}
pkIdx.addParameterOccurrence(inputParams);
}
}
String textStmt = sqlStmt.getSQLText().toSQL();
if (sm.isEmbedded()) {
// This mapping is embedded, so navigate back to the real owner since that is the "id" in the table
DNStateManager embeddedOwner = ec.getOwnerForEmbeddedStateManager(sm);
if (embeddedOwner != null) {
// TODO Should check if the owner is stored in this table
sm = embeddedOwner;
}
}
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), sm.getInternalObjectId());
}
} else if (cmd.getIdentityType() == IdentityType.APPLICATION) {
sm.provideFields(cmd.getPKMemberPositions(), new ParameterSetter(sm, ps, mappingDefinition));
}
ResultSet rs = sqlControl.executeStatementQuery(ec, mconn, textStmt, ps);
try {
if (!rs.next()) {
throw new NucleusObjectNotFoundException(Localiser.msg("050018", IdentityUtils.getPersistableIdentityForId(sm.getInternalObjectId())));
}
DatastoreAdapter dba = storeMgr.getDatastoreAdapter();
int jdbcMajorVersion = dba.getDriverMajorVersion();
if (dba.getDatastoreDriverName().equalsIgnoreCase(OracleAdapter.OJDBC_DRIVER_NAME) && jdbcMajorVersion < 10) {
oracle.sql.BLOB blob = null;
if (jdbcMajorVersion <= 8) {
// Oracle JDBC <= v8
// We are effectively doing the following line but don't want to impose having Oracle <= v10 in the CLASSPATH, just any Oracle driver
// blob = ((oracle.jdbc.driver.OracleResultSet)rs).getBLOB(1);
Method getBlobMethod = ClassUtils.getMethodForClass(rs.getClass(), "getBLOB", new Class[] { int.class });
try {
blob = (BLOB) getBlobMethod.invoke(rs, new Object[] { 1 });
} catch (Throwable thr) {
throw new NucleusDataStoreException("Error in getting BLOB", thr);
}
} else {
// Oracle JDBC v9
blob = (BLOB) rs.getBlob(1);
}
if (blob != null) {
// Deprecated but what can you do
blob.putBytes(1, bytes);
}
} else {
// Oracle JDBC v10+ supposedly use the JDBC standard class for Blobs
java.sql.Blob blob = rs.getBlob(1);
if (blob != null) {
blob.setBytes(1, bytes);
}
}
} finally {
rs.close();
}
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException e) {
throw new NucleusDataStoreException("Update of BLOB value failed: " + textStmt, e);
}
} else {
// TODO Support join table
throw new NucleusDataStoreException("We do not support INSERT/UPDATE BLOB post processing of non-primary table " + table);
}
}
use of org.datanucleus.state.DNStateManager 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 ownerSM StateManager of the owner
*/
public void postUpdate(DNStateManager ownerSM) {
ExecutionContext ec = ownerSM.getExecutionContext();
Object value = ownerSM.provideField(getAbsoluteFieldNumber());
if (containerIsStoredInSingleColumn()) {
if (value != null) {
if (mmd.getArray().elementIsPersistent()) {
// Make sure all persistable elements have StateManagers
Object[] arrElements = (Object[]) value;
for (Object elem : arrElements) {
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_ARRAY_ELEMENT_PC);
}
}
}
}
}
return;
}
if (value == null) {
// array is now null so remove any elements in the array
((ArrayStore) storeMgr.getBackingStoreForField(ec.getClassLoaderResolver(), mmd, null)).clear(ownerSM);
return;
}
if (!mmd.isCascadePersist()) {
// User doesn't want to update by reachability
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("007008", IdentityUtils.getPersistableIdentityForId(ownerSM.getInternalObjectId()), mmd.getFullFieldName()));
}
return;
}
if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
NucleusLogger.PERSISTENCE.debug(Localiser.msg("007009", IdentityUtils.getPersistableIdentityForId(ownerSM.getInternalObjectId()), 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(ownerSM);
backingStore.set(ownerSM, value);
}
Aggregations