use of org.apache.cayenne.map.DbAttribute in project cayenne by apache.
the class DataDomainFlattenedBucket method addFlattenedDelete.
void addFlattenedDelete(DbEntity flattenedEntity, FlattenedArcKey flattenedDeleteInfo) {
DeleteBatchQuery relationDeleteQuery = flattenedDeleteQueries.get(flattenedEntity);
if (relationDeleteQuery == null) {
Collection<DbAttribute> pk = flattenedEntity.getPrimaryKeys();
List<DbAttribute> pkList = pk instanceof List ? (List<DbAttribute>) pk : new ArrayList<>(pk);
relationDeleteQuery = new DeleteBatchQuery(flattenedEntity, pkList, Collections.<String>emptySet(), 50);
relationDeleteQuery.setUsingOptimisticLocking(false);
flattenedDeleteQueries.put(flattenedEntity, relationDeleteQuery);
}
DataNode node = parent.getDomain().lookupDataNode(flattenedEntity.getDataMap());
List<Map<String, Object>> flattenedSnapshots = flattenedDeleteInfo.buildJoinSnapshotsForDelete(node);
if (!flattenedSnapshots.isEmpty()) {
for (Map<String, Object> flattenedSnapshot : flattenedSnapshots) {
relationDeleteQuery.add(flattenedSnapshot);
}
}
}
use of org.apache.cayenne.map.DbAttribute in project cayenne by apache.
the class DataDomainUpdateBucket method appendQueriesInternal.
@Override
void appendQueriesInternal(Collection<Query> queries) {
DataDomainDBDiffBuilder diffBuilder = new DataDomainDBDiffBuilder();
DataNodeSyncQualifierDescriptor qualifierBuilder = new DataNodeSyncQualifierDescriptor();
for (DbEntity dbEntity : dbEntities) {
Collection<DbEntityClassDescriptor> descriptors = descriptorsByDbEntity.get(dbEntity);
Map<Object, Query> batches = new LinkedHashMap<>();
for (DbEntityClassDescriptor descriptor : descriptors) {
ObjEntity entity = descriptor.getEntity();
diffBuilder.reset(descriptor);
qualifierBuilder.reset(descriptor);
boolean isRootDbEntity = entity.getDbEntity() == dbEntity;
for (Persistent o : objectsByDescriptor.get(descriptor.getClassDescriptor())) {
ObjectDiff diff = parent.objectDiff(o.getObjectId());
Map<String, Object> snapshot = diffBuilder.buildDBDiff(diff);
// check whether MODIFIED object has real db-level modifications
if (snapshot == null) {
continue;
}
// after we filtered out "fake" modifications, check if an
// attempt is made to modify a read only entity
checkReadOnly(entity);
Map<String, Object> qualifierSnapshot = qualifierBuilder.createQualifierSnapshot(diff);
// organize batches by the updated columns + nulls in qualifier
Set<String> snapshotSet = snapshot.keySet();
Set<String> nullQualifierNames = new HashSet<>();
for (Map.Entry<String, Object> entry : qualifierSnapshot.entrySet()) {
if (entry.getValue() == null) {
nullQualifierNames.add(entry.getKey());
}
}
List<Set<String>> batchKey = Arrays.asList(snapshotSet, nullQualifierNames);
UpdateBatchQuery batch = (UpdateBatchQuery) batches.get(batchKey);
if (batch == null) {
batch = new UpdateBatchQuery(dbEntity, qualifierBuilder.getAttributes(), updatedAttributes(dbEntity, snapshot), nullQualifierNames, 10);
batch.setUsingOptimisticLocking(qualifierBuilder.isUsingOptimisticLocking());
batches.put(batchKey, batch);
}
batch.add(qualifierSnapshot, snapshot, o.getObjectId());
// update replacement id with meaningful PK changes
if (isRootDbEntity) {
Map<String, Object> replacementId = o.getObjectId().getReplacementIdMap();
for (DbAttribute pk : dbEntity.getPrimaryKeys()) {
String name = pk.getName();
if (snapshot.containsKey(name) && !replacementId.containsKey(name)) {
replacementId.put(name, snapshot.get(name));
}
}
}
}
}
queries.addAll(batches.values());
}
}
use of org.apache.cayenne.map.DbAttribute in project cayenne by apache.
the class DataNodeSyncQualifierDescriptor method createQualifierSnapshot.
Map<String, Object> createQualifierSnapshot(ObjectDiff diff) {
int len = attributes.size();
Map<String, Object> map = new HashMap<>(len * 2);
for (int i = 0; i < len; i++) {
DbAttribute attribute = attributes.get(i);
if (!map.containsKey(attribute.getName())) {
Object value = valueTransformers.get(i).apply(diff);
map.put(attribute.getName(), value);
}
}
return map;
}
use of org.apache.cayenne.map.DbAttribute in project cayenne by apache.
the class DataNodeSyncQualifierDescriptor method reset.
void reset(DbEntityClassDescriptor descriptor) {
attributes = new ArrayList<>(3);
valueTransformers = new ArrayList<>(3);
usingOptimisticLocking = descriptor.getEntity().getLockType() == ObjEntity.LOCK_TYPE_OPTIMISTIC;
// master PK columns
if (descriptor.isMaster()) {
for (final DbAttribute attribute : descriptor.getDbEntity().getPrimaryKeys()) {
attributes.add(attribute);
valueTransformers.add(input -> {
ObjectId id = (ObjectId) input.getNodeId();
return id.getIdSnapshot().get(attribute.getName());
});
}
} else {
// TODO: andrus 12/23/2007 - only one step relationship is supported...
if (descriptor.getPathFromMaster().size() != 1) {
throw new CayenneRuntimeException("Only single step dependent relationships are currently supported. Actual path length: %d", descriptor.getPathFromMaster().size());
}
DbRelationship masterDependentDbRel = descriptor.getPathFromMaster().get(0);
if (masterDependentDbRel != null) {
for (final DbJoin dbAttrPair : masterDependentDbRel.getJoins()) {
DbAttribute dbAttribute = dbAttrPair.getTarget();
if (!attributes.contains(dbAttribute)) {
attributes.add(dbAttribute);
valueTransformers.add(input -> {
ObjectId id = (ObjectId) input.getNodeId();
return id.getIdSnapshot().get(dbAttrPair.getSourceName());
});
}
}
}
}
if (usingOptimisticLocking) {
for (final ObjAttribute attribute : descriptor.getEntity().getAttributes()) {
if (attribute.isUsedForLocking()) {
// only care about first step in a flattened attribute
DbAttribute dbAttribute = (DbAttribute) attribute.getDbPathIterator().next();
// only use qualifier if dbEntities match
if (dbAttribute.getEntity().equals(descriptor.getDbEntity()) && !attributes.contains(dbAttribute)) {
attributes.add(dbAttribute);
valueTransformers.add(input -> input.getSnapshotValue(attribute.getName()));
}
}
}
for (final ObjRelationship relationship : descriptor.getEntity().getRelationships()) {
if (relationship.isUsedForLocking()) {
// only care about the first DbRelationship
DbRelationship dbRelationship = relationship.getDbRelationships().get(0);
for (final DbJoin dbAttrPair : dbRelationship.getJoins()) {
DbAttribute dbAttribute = dbAttrPair.getSource();
// relationship transformers override attribute transformers for meaningful FK's...
// why meaningful FKs can go out of sync is another story (CAY-595)
int index = attributes.indexOf(dbAttribute);
if (index >= 0 && !dbAttribute.isForeignKey()) {
continue;
}
Function<ObjectDiff, Object> transformer = input -> {
ObjectId targetId = input.getArcSnapshotValue(relationship.getName());
return targetId != null ? targetId.getIdSnapshot().get(dbAttrPair.getTargetName()) : null;
};
if (index < 0) {
attributes.add(dbAttribute);
valueTransformers.add(transformer);
} else {
valueTransformers.set(index, transformer);
}
}
}
}
}
}
use of org.apache.cayenne.map.DbAttribute in project cayenne by apache.
the class ObjectResolver method createObjectId.
ObjectId createObjectId(DataRow dataRow, ObjEntity objEntity, String namePrefix) {
Collection<DbAttribute> pk = objEntity == this.descriptor.getEntity() ? this.primaryKey : objEntity.getDbEntity().getPrimaryKeys();
boolean prefix = namePrefix != null && namePrefix.length() > 0;
if (pk.size() == 1) {
DbAttribute attribute = pk.iterator().next();
String key = (prefix) ? namePrefix + attribute.getName() : attribute.getName();
Object val = dataRow.get(key);
// this is possible when processing left outer joint prefetches
if (val == null) {
if (!dataRow.containsKey(key)) {
throw new CayenneRuntimeException("No PK column '%s' found in data row.", key);
}
return null;
}
// PUT without a prefix
return new ObjectId(objEntity.getName(), attribute.getName(), val);
}
// ... handle generic case - PK.size > 1
Map<String, Object> idMap = new HashMap<>(pk.size() * 2);
for (final DbAttribute attribute : pk) {
String key = (prefix) ? namePrefix + attribute.getName() : attribute.getName();
Object val = dataRow.get(key);
// this is possible when processing left outer joint prefetches
if (val == null) {
if (!dataRow.containsKey(key)) {
throw new CayenneRuntimeException("No PK column '%s' found in data row.", key);
}
return null;
}
// PUT without a prefix
idMap.put(attribute.getName(), val);
}
return new ObjectId(objEntity.getName(), idMap);
}
Aggregations