use of org.datanucleus.ExecutionContext in project datanucleus-rdbms by datanucleus.
the class RDBMSPersistenceHandler method fetchObject.
// ------------------------------ Fetch ----------------------------------
/**
* Fetches (fields of) a persistent object from the database.
* This does a single SELECT on the candidate of the class in question. Will join to inherited
* tables as appropriate to get values persisted into other tables. Can also join to the tables of
* related objects (1-1, N-1) as neccessary to retrieve those objects.
* @param op Object Provider of the object to be fetched.
* @param memberNumbers The numbers of the members to be fetched.
* @throws NucleusObjectNotFoundException if the object doesn't exist
* @throws NucleusDataStoreException when an error occurs in the datastore communication
*/
public void fetchObject(ObjectProvider op, int[] memberNumbers) {
ExecutionContext ec = op.getExecutionContext();
ClassLoaderResolver clr = ec.getClassLoaderResolver();
// Extract metadata of members to process
AbstractMemberMetaData[] mmds = null;
if (memberNumbers != null && memberNumbers.length > 0) {
int[] memberNumbersToProcess = memberNumbers;
AbstractClassMetaData cmd = op.getClassMetaData();
if (storeMgr.getBooleanProperty(RDBMSPropertyNames.PROPERTY_RDBMS_FETCH_UNLOADED_AUTO)) {
// Here we simply load up any unloaded non-relation or 1-1/N-1 members
if (!op.getLifecycleState().isDeleted()) {
// Check if this will actually do a SELECT (because we don't want to impose that if not otherwise)
boolean fetchPerformsSelect = false;
for (int i = 0; i < memberNumbers.length; i++) {
AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(memberNumbers[i]);
RelationType relationType = mmd.getRelationType(clr);
if (relationType != RelationType.ONE_TO_MANY_UNI && relationType != RelationType.ONE_TO_MANY_BI && relationType != RelationType.MANY_TO_MANY_BI) {
fetchPerformsSelect = true;
break;
}
}
if (fetchPerformsSelect) {
// Definitely does a SELECT, so try to identify any additional non-relation or 1-1, N-1
// members that aren't loaded that could be fetched right now in this call.
List<Integer> memberNumberList = new ArrayList<>();
for (int i = 0; i < memberNumbers.length; i++) {
memberNumberList.add(memberNumbers[i]);
}
// Check if we could retrieve any other unloaded fields in this call
boolean[] loadedFlags = op.getLoadedFields();
for (int i = 0; i < loadedFlags.length; i++) {
boolean requested = false;
for (int j = 0; j < memberNumbers.length; j++) {
if (memberNumbers[j] == i) {
requested = true;
break;
}
}
if (!requested && !loadedFlags[i]) {
AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(i);
RelationType relType = mmd.getRelationType(clr);
if (relType == RelationType.NONE || relType == RelationType.ONE_TO_ONE_BI || relType == RelationType.ONE_TO_ONE_UNI) {
memberNumberList.add(i);
}
}
}
memberNumbersToProcess = new int[memberNumberList.size()];
int i = 0;
Iterator<Integer> fieldNumberIter = memberNumberList.iterator();
while (fieldNumberIter.hasNext()) {
memberNumbersToProcess[i++] = fieldNumberIter.next();
}
}
}
}
// Convert the field numbers for this class into their metadata for the class
mmds = new AbstractMemberMetaData[memberNumbersToProcess.length];
for (int i = 0; i < mmds.length; i++) {
mmds[i] = cmd.getMetaDataForManagedMemberAtAbsolutePosition(memberNumbersToProcess[i]);
}
}
if (op.isEmbedded()) {
StringBuilder str = new StringBuilder();
if (mmds != null) {
for (int i = 0; i < mmds.length; i++) {
if (i > 0) {
str.append(',');
}
str.append(mmds[i].getName());
}
}
NucleusLogger.PERSISTENCE.info("Request to load fields \"" + str.toString() + "\" of class " + op.getClassMetaData().getFullClassName() + " but object is embedded, so ignored");
} else {
if (ec.getStatistics() != null) {
ec.getStatistics().incrementFetchCount();
}
DatastoreClass table = getDatastoreClass(op.getClassMetaData().getFullClassName(), clr);
Request req = getFetchRequest(table, mmds, op.getClassMetaData(), clr);
req.execute(op);
}
}
use of org.datanucleus.ExecutionContext in project datanucleus-rdbms by datanucleus.
the class ScrollableQueryResult method getObjectForIndex.
/**
* Accessor for the result object at an index.
* If the object has already been processed will return that object,
* otherwise will retrieve the object using the factory.
* @param index The list index position
* @return The result object
*/
protected E getObjectForIndex(int index) {
if (resultsObjsByIndex != null) {
// Caching objects, so check the cache for this index
E obj = resultsObjsByIndex.get(index);
if (obj != null) {
// Already retrieved so return it
return obj;
}
}
if (rs == null) {
throw new NucleusUserException("Results for query have already been closed. Perhaps you called flush(), closed the query, or ended a transaction");
}
try {
// ResultSet is numbered 1, 2, ... N
// List is indexed 0, 1, 2, ... N-1
rs.absolute(index + 1);
E obj = rof.getObject();
JDBCUtils.logWarnings(rs);
// Process any bulk loaded members
if (bulkLoadedValueByMemberNumber != null) {
ExecutionContext ec = query.getExecutionContext();
Map<Integer, Object> memberValues = bulkLoadedValueByMemberNumber.get(api.getIdForObject(obj));
if (memberValues != null) {
ObjectProvider op = ec.findObjectProvider(obj);
Iterator<Map.Entry<Integer, Object>> memberValIter = memberValues.entrySet().iterator();
while (memberValIter.hasNext()) {
Map.Entry<Integer, Object> memberValueEntry = memberValIter.next();
op.replaceField(memberValueEntry.getKey(), memberValueEntry.getValue());
}
op.replaceAllLoadedSCOFieldsWithWrappers();
}
}
if (resultsObjsByIndex != null) {
// Put it in our cache, keyed by the list index
resultsObjsByIndex.put(index, obj);
if (resultIdsByPosition != null) {
resultIdsByPosition.put(index, api.getIdForObject(obj));
}
}
return obj;
} catch (SQLException sqe) {
throw api.getDataStoreExceptionForException(Localiser.msg("052601", sqe.getMessage()), sqe);
}
}
use of org.datanucleus.ExecutionContext in project datanucleus-rdbms by datanucleus.
the class FKArrayStore method updateElementFk.
/**
* Update a FK and element position in the element.
* @param ownerOP ObjectProvider for the owner
* @param element The element to update
* @param owner The owner object to set in the FK
* @param index The index position (or -1 if not known)
* @return Whether it was performed successfully
*/
private boolean updateElementFk(ObjectProvider ownerOP, E element, Object owner, int index) {
if (element == null) {
return false;
}
boolean retval;
String updateFkStmt = getUpdateFkStmt();
ExecutionContext ec = ownerOP.getExecutionContext();
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, updateFkStmt, false);
try {
int jdbcPosition = 1;
if (elementInfo.length > 1) {
DatastoreClass table = storeMgr.getDatastoreClass(element.getClass().getName(), clr);
if (table != null) {
ps.setString(jdbcPosition++, table.toString());
} else {
NucleusLogger.PERSISTENCE.info(">> FKArrayStore.updateElementFK : need to set table in statement but dont know table where to store " + element);
}
}
if (owner == null) {
ownerMapping.setObject(ec, ps, MappingHelper.getMappingIndices(jdbcPosition, ownerMapping), null);
jdbcPosition += ownerMapping.getNumberOfDatastoreMappings();
} else {
jdbcPosition = BackingStoreHelper.populateOwnerInStatement(ownerOP, ec, ps, jdbcPosition, this);
}
jdbcPosition = BackingStoreHelper.populateOrderInStatement(ec, ps, index, jdbcPosition, orderMapping);
if (relationDiscriminatorMapping != null) {
jdbcPosition = BackingStoreHelper.populateRelationDiscriminatorInStatement(ec, ps, jdbcPosition, this);
}
jdbcPosition = BackingStoreHelper.populateElementInStatement(ec, ps, element, jdbcPosition, elementMapping);
sqlControl.executeStatementUpdate(ec, mconn, updateFkStmt, ps, true);
retval = true;
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException e) {
throw new NucleusDataStoreException(Localiser.msg("056027", updateFkStmt), e);
}
return retval;
}
use of org.datanucleus.ExecutionContext in project datanucleus-rdbms by datanucleus.
the class FKListStore method clear.
/**
* Method to clear the List.
* This is called by the List.clear() method, or when the container object is being deleted
* and the elements are to be removed (maybe for dependent field), or also when updating a Collection
* and removing all existing prior to adding all new.
* @param ownerOP ObjectProvider for the owner
*/
public void clear(ObjectProvider ownerOP) {
boolean deleteElements = false;
ExecutionContext ec = ownerOP.getExecutionContext();
boolean dependent = ownerMemberMetaData.getCollection().isDependentElement();
if (ownerMemberMetaData.isCascadeRemoveOrphans()) {
dependent = true;
}
if (dependent) {
// Elements are dependent and can't exist on their own, so delete them all
NucleusLogger.DATASTORE.debug(Localiser.msg("056034"));
deleteElements = true;
} else {
if (ownerMapping.isNullable() && orderMapping == null) {
// Field is not dependent, and nullable so we null the FK
NucleusLogger.DATASTORE.debug(Localiser.msg("056036"));
deleteElements = false;
} else if (ownerMapping.isNullable() && orderMapping != null && orderMapping.isNullable()) {
// Field is not dependent, and nullable so we null the FK
NucleusLogger.DATASTORE.debug(Localiser.msg("056036"));
deleteElements = false;
} else {
// Field is not dependent, and not nullable so we just delete the elements
NucleusLogger.DATASTORE.debug(Localiser.msg("056035"));
deleteElements = true;
}
}
if (deleteElements) {
// Find elements present in the datastore and delete them one-by-one
Iterator elementsIter = iterator(ownerOP);
if (elementsIter != null) {
while (elementsIter.hasNext()) {
Object element = elementsIter.next();
if (ec.getApiAdapter().isPersistable(element) && ec.getApiAdapter().isDeleted(element)) {
// Element is waiting to be deleted so flush it (it has the FK)
ObjectProvider objSM = ec.findObjectProvider(element);
objSM.flush();
} else {
// Element not yet marked for deletion so go through the normal process
ec.deleteObjectInternal(element);
}
}
}
} else {
boolean ownerSoftDelete = ownerOP.getClassMetaData().hasExtension(MetaData.EXTENSION_CLASS_SOFTDELETE);
if (!ownerSoftDelete) {
// Clear without delete
// TODO If the relation is bidirectional we need to clear the owner in the element
String clearNullifyStmt = getClearNullifyStmt();
try {
ManagedConnection mconn = storeMgr.getConnectionManager().getConnection(ec);
SQLController sqlControl = storeMgr.getSQLController();
try {
PreparedStatement ps = sqlControl.getStatementForUpdate(mconn, clearNullifyStmt, false);
try {
int jdbcPosition = 1;
jdbcPosition = BackingStoreHelper.populateOwnerInStatement(ownerOP, ec, ps, jdbcPosition, this);
if (relationDiscriminatorMapping != null) {
BackingStoreHelper.populateRelationDiscriminatorInStatement(ec, ps, jdbcPosition, this);
}
sqlControl.executeStatementUpdate(ec, mconn, clearNullifyStmt, ps, true);
} finally {
sqlControl.closeStatement(mconn, ps);
}
} finally {
mconn.release();
}
} catch (SQLException e) {
throw new NucleusDataStoreException(Localiser.msg("056013", clearNullifyStmt), e);
}
}
}
}
use of org.datanucleus.ExecutionContext in project datanucleus-rdbms by datanucleus.
the class FKListStore method internalRemove.
/**
* Convenience method to remove the specified element from the List.
* @param ownerOP ObjectProvider for the owner
* @param element The element
* @return Whether the List was modified
*/
protected boolean internalRemove(ObjectProvider ownerOP, Object element, int size) {
if (indexedList) {
// Indexed List
// The element can be at one position only (no duplicates allowed in FK list)
int index = indexOf(ownerOP, element);
if (index == -1) {
return false;
}
internalRemoveAt(ownerOP, index, size);
} else {
// Ordered List - no index so null the FK (if nullable) or delete the element
if (ownerMapping.isNullable()) {
// Nullify the FK
ExecutionContext ec = ownerOP.getExecutionContext();
ObjectProvider elementSM = ec.findObjectProvider(element);
if (relationType == RelationType.ONE_TO_MANY_BI) {
// Set field in element to null (so it nulls the FK)
// TODO This is ManagedRelations - move into RelationshipManager
elementSM.replaceFieldMakeDirty(ownerMemberMetaData.getRelatedMemberMetaData(clr)[0].getAbsoluteFieldNumber(), null);
if (ownerOP.getExecutionContext().isFlushing()) {
elementSM.flush();
}
} else {
// Null the (external) FK in the element
updateElementFk(ownerOP, element, null, -1);
}
} else {
// Delete the element
ownerOP.getExecutionContext().deleteObjectInternal(element);
}
}
return true;
}
Aggregations