if (opsToInsert == null || opsToInsert.isEmpty()) {
return;
}
// All must be in same ExecutionContext
ExecutionContext ec = opsToInsert.get(0).getExecutionContext();
List<PutState> putStateList = Utils.newArrayList();
for (ObjectProvider op : opsToInsert) {
AbstractClassMetaData cmd = op.getClassMetaData();
// Create the Entity, and populate all fields that can be populated (this will omit any owned child objects
// if we don't have the key of this object yet).
StoreFieldManager fieldMgr =
new StoreFieldManager(op, EntityUtils.determineKind(cmd, ec));
op.provideFields(op.getClassMetaData().getAllMemberPositions(), fieldMgr);
// Make sure the Entity parent is set (if any)
Object assignedParentPk = fieldMgr.establishEntityGroup();
Entity entity = fieldMgr.getEntity();
if (!datastoreMgr.storageVersionAtLeast(StorageVersion.READ_OWNED_CHILD_KEYS_FROM_PARENTS)) {
// Older storage versions : store list positions in the element
DatastoreTable table = datastoreMgr.getDatastoreClass(op.getClassMetaData().getFullClassName(),
ec.getClassLoaderResolver());
Collection<JavaTypeMapping> orderMappings = table.getExternalOrderMappings().values();
for (JavaTypeMapping orderMapping : orderMappings) {
if (orderMapping instanceof IndexMapping) {
Object orderValue = op.getAssociatedValue(orderMapping);
if (orderValue != null) {
// Set order index on the entity
DatastoreField indexProp = orderMapping.getDatastoreMapping(0).getDatastoreField();
entity.setProperty(indexProp.getIdentifier().toString(), orderValue); // Is this indexed in the datastore?
} else {
// Element has been persisted and has the owner set, but not positioned, so leave til user does it
}
}
}
}
// Set version
handleVersioningBeforeWrite(op, entity, true, "inserting");
// Set discriminator
if (op.getClassMetaData().hasDiscriminatorStrategy()) {
DiscriminatorMetaData dismd = op.getClassMetaData().getDiscriminatorMetaDataRoot();
EntityUtils.setEntityProperty(entity, dismd,
EntityUtils.getDiscriminatorPropertyName(datastoreMgr.getIdentifierFactory(), dismd),
op.getClassMetaData().getDiscriminatorValue());
}
// Add Multi-tenancy discriminator if applicable
if (storeMgr.getStringProperty(PropertyNames.PROPERTY_TENANT_ID) != null) {
if ("true".equalsIgnoreCase(cmd.getValueForExtension("multitenancy-disable"))) {
// Don't bother with multitenancy for this class
}
else {
String name = storeMgr.getNamingFactory().getColumnName(cmd, ColumnType.MULTITENANCY_COLUMN);
EntityUtils.setEntityProperty(entity, cmd, name, storeMgr.getStringProperty(PropertyNames.PROPERTY_TENANT_ID));
}
}
// Update parent PK field on pojo
AbstractMemberMetaData parentPkMmd = datastoreMgr.getMetaDataForParentPK(cmd);
if (assignedParentPk != null) {
// we automatically assigned a parent to the entity so make sure that makes it back on to the pojo
op.replaceField(parentPkMmd.getAbsoluteFieldNumber(), assignedParentPk);
}
// Add the "state" for this put to the list.
putStateList.add(new PutState(op, fieldMgr, entity));
}
// PUT all entities in single call
if (!putStateList.isEmpty()) {
DatastoreTransaction txn = null;
AbstractClassMetaData acmd = null;
List<Entity> entityList = Utils.newArrayList();
for (PutState putState : putStateList) {
if (txn == null) {
txn = datastoreMgr.getDatastoreTransaction(ec);
}
if (acmd == null) {
acmd = putState.op.getClassMetaData();
}
entityList.add(putState.entity);
}
EntityUtils.putEntitiesIntoDatastore(ec, entityList);
for (PutState putState : putStateList) {
putState.op.setAssociatedValue(txn, putState.entity);
}
}
// Post-processing for all puts
for (PutState putState : putStateList) {
AbstractClassMetaData cmd = putState.op.getClassMetaData();
// Set the generated key back on the pojo. If the pk field is a Key just set it on the field directly.
// If the pk field is a String, convert the Key to a String, similarly for long.
// Assumes we only have a single pk member position
Object newId = null;
Class pkType = null;
boolean identityStrategyUsed = false;
if (cmd.pkIsDatastoreAttributed(storeMgr)) {
if (cmd.getIdentityType() == IdentityType.APPLICATION) {
// Assume only 1 PK field
identityStrategyUsed = true;
pkType = cmd.getMetaDataForManagedMemberAtAbsolutePosition(cmd.getPKMemberPositions()[0]).getType();
} else if (cmd.getIdentityType() == IdentityType.DATASTORE) {
identityStrategyUsed = true;
pkType = Key.class;
ColumnMetaData colmd = cmd.getIdentityMetaData().getColumnMetaData();
if (colmd != null) {
if ("varchar".equalsIgnoreCase(colmd.getJdbcType()) || "char".equalsIgnoreCase(colmd.getJdbcType())) {
pkType = String.class;
} else if ("integer".equalsIgnoreCase(colmd.getJdbcType()) || "numeric".equalsIgnoreCase(colmd.getJdbcType())) {
pkType = Long.class;
}
}
}
}
if (identityStrategyUsed) {
// Update the identity of the object with the datastore-assigned id
if (pkType.equals(Key.class)) {
newId = putState.entity.getKey();
} else if (pkType.equals(String.class)) {
if (MetaDataUtils.hasEncodedPKField(cmd)) {
newId = KeyFactory.keyToString(putState.entity.getKey());
} else {
newId = putState.entity.getKey().getName();
}
} else if (pkType.equals(Long.class) || pkType.equals(long.class)) {
newId = putState.entity.getKey().getId();
}
putState.op.setPostStoreNewObjectId(newId);
}
// Update relation fields (including cascade-persist etc)
if (putState.fieldMgr.storeRelations(KeyRegistry.getKeyRegistry(ec))) {
// PUT Entity into datastore with these changes
EntityUtils.putEntityIntoDatastore(ec, putState.entity);
}
putState.op.replaceAllLoadedSCOFieldsWithWrappers();
if (ec.getStatistics() != null) {
ec.getStatistics().incrementInsertCount();
}
}
}