Search in sources :

Example 71 with Persistent

use of org.apache.cayenne.Persistent in project cayenne by apache.

the class DataDomainInsertBucket method createPermIds.

void createPermIds(DbEntityClassDescriptor descriptor, Collection<Persistent> objects) {
    if (objects.isEmpty()) {
        return;
    }
    ObjEntity objEntity = descriptor.getEntity();
    DbEntity entity = descriptor.getDbEntity();
    DataNode node = parent.getDomain().lookupDataNode(entity.getDataMap());
    boolean supportsGeneratedKeys = node.getAdapter().supportsGeneratedKeys();
    PkGenerator pkGenerator = node.getAdapter().getPkGenerator();
    for (Persistent object : objects) {
        ObjectId id = object.getObjectId();
        if (id == null || !id.isTemporary()) {
            continue;
        }
        // modify replacement id directly...
        Map<String, Object> idMap = id.getReplacementIdMap();
        boolean autoPkDone = false;
        for (DbAttribute dbAttr : entity.getPrimaryKeys()) {
            String dbAttrName = dbAttr.getName();
            if (idMap.containsKey(dbAttrName)) {
                continue;
            }
            // handle meaningful PK
            ObjAttribute objAttr = objEntity.getAttributeForDbAttribute(dbAttr);
            if (objAttr != null) {
                Object value = descriptor.getClassDescriptor().getProperty(objAttr.getName()).readPropertyDirectly(object);
                if (value != null) {
                    Class<?> javaClass = objAttr.getJavaClass();
                    if (javaClass.isPrimitive() && value instanceof Number && ((Number) value).intValue() == 0) {
                    // primitive 0 has to be treated as NULL, or
                    // otherwise we can't generate PK for POJO's
                    } else {
                        idMap.put(dbAttrName, value);
                        continue;
                    }
                }
            }
            // skip db-generated
            if (supportsGeneratedKeys && dbAttr.isGenerated()) {
                continue;
            }
            // skip propagated
            if (isPropagated(dbAttr)) {
                continue;
            }
            // already in this loop, we must bail out.
            if (autoPkDone) {
                throw new CayenneRuntimeException("Primary Key autogeneration only works for a single attribute.");
            }
            // finally, use database generation mechanism
            try {
                Object pkValue = pkGenerator.generatePk(node, dbAttr);
                idMap.put(dbAttrName, pkValue);
                autoPkDone = true;
            } catch (Exception ex) {
                throw new CayenneRuntimeException("Error generating PK: %s", ex, ex.getMessage());
            }
        }
    }
}
Also used : ObjAttribute(org.apache.cayenne.map.ObjAttribute) ObjectId(org.apache.cayenne.ObjectId) DbAttribute(org.apache.cayenne.map.DbAttribute) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) Persistent(org.apache.cayenne.Persistent) PkGenerator(org.apache.cayenne.dba.PkGenerator) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) ObjEntity(org.apache.cayenne.map.ObjEntity) DbEntity(org.apache.cayenne.map.DbEntity)

Example 72 with Persistent

use of org.apache.cayenne.Persistent in project cayenne by apache.

the class DataDomainInsertBucket method appendQueriesInternal.

@Override
void appendQueriesInternal(Collection<Query> queries) {
    DataDomainDBDiffBuilder diffBuilder = new DataDomainDBDiffBuilder();
    EntitySorter sorter = parent.getDomain().getEntitySorter();
    sorter.sortDbEntities(dbEntities, false);
    for (DbEntity dbEntity : dbEntities) {
        Collection<DbEntityClassDescriptor> descriptors = descriptorsByDbEntity.get(dbEntity);
        InsertBatchQuery batch = new InsertBatchQuery(dbEntity, 27);
        for (DbEntityClassDescriptor descriptor : descriptors) {
            diffBuilder.reset(descriptor);
            List<Persistent> objects = objectsByDescriptor.get(descriptor.getClassDescriptor());
            if (objects.isEmpty()) {
                continue;
            }
            checkReadOnly(descriptor.getEntity());
            createPermIds(descriptor, objects);
            sorter.sortObjectsForEntity(descriptor.getEntity(), objects, false);
            for (Persistent o : objects) {
                Map<String, Object> snapshot = diffBuilder.buildDBDiff(parent.objectDiff(o.getObjectId()));
                // values so creating an empty changes map
                if (snapshot == null) {
                    snapshot = new HashMap<>();
                }
                batch.add(snapshot, o.getObjectId());
            }
        }
        queries.add(batch);
    }
}
Also used : EntitySorter(org.apache.cayenne.map.EntitySorter) DbEntity(org.apache.cayenne.map.DbEntity) InsertBatchQuery(org.apache.cayenne.query.InsertBatchQuery) Persistent(org.apache.cayenne.Persistent)

Example 73 with Persistent

use of org.apache.cayenne.Persistent in project cayenne by apache.

the class DataDomainSyncBucket method postprocess.

void postprocess() {
    if (!objectsByDescriptor.isEmpty()) {
        CompoundDiff result = parent.getResultDiff();
        Map<ObjectId, DataRow> modifiedSnapshots = parent.getResultModifiedSnapshots();
        Collection<ObjectId> deletedIds = parent.getResultDeletedIds();
        for (Map.Entry<ClassDescriptor, List<Persistent>> entry : objectsByDescriptor.entrySet()) {
            ClassDescriptor descriptor = entry.getKey();
            for (Persistent object : entry.getValue()) {
                ObjectId id = object.getObjectId();
                ObjectId finalId;
                // record id change and update attributes for generated ids
                if (id.isReplacementIdAttached()) {
                    Map<String, Object> replacement = id.getReplacementIdMap();
                    for (AttributeProperty property : descriptor.getIdProperties()) {
                        Object value = replacement.get(property.getAttribute().getDbAttributeName());
                        // if the id wasn't generated. We may need to optimize it...
                        if (value != null) {
                            property.writePropertyDirectly(object, null, value);
                        }
                    }
                    ObjectId replacementId = id.createReplacementId();
                    result.add(new NodeIdChangeOperation(id, replacementId));
                    // DataRowCache has no notion of replaced id...
                    if (!id.isTemporary()) {
                        deletedIds.add(id);
                    }
                    finalId = replacementId;
                } else if (id.isTemporary()) {
                    throw new CayenneRuntimeException("Temporary ID hasn't been replaced on commit: %s", object);
                } else {
                    finalId = id;
                }
                // do not take the snapshot until generated columns are processed (see code above)
                DataRow dataRow = parent.getContext().currentSnapshot(object);
                if (object instanceof DataObject) {
                    DataObject dataObject = (DataObject) object;
                    dataRow.setReplacesVersion(dataObject.getSnapshotVersion());
                    dataObject.setSnapshotVersion(dataRow.getVersion());
                }
                modifiedSnapshots.put(finalId, dataRow);
                // update Map reverse relationships
                for (ArcProperty arc : descriptor.getMapArcProperties()) {
                    ToManyMapProperty reverseArc = (ToManyMapProperty) arc.getComplimentaryReverseArc();
                    // must resolve faults... hopefully for to-one this will not cause extra fetches...
                    Object source = arc.readProperty(object);
                    if (source != null && !reverseArc.isFault(source)) {
                        remapTarget(reverseArc, source, object);
                    }
                }
            }
        }
    }
}
Also used : NodeIdChangeOperation(org.apache.cayenne.graph.NodeIdChangeOperation) ArcProperty(org.apache.cayenne.reflect.ArcProperty) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) ObjectId(org.apache.cayenne.ObjectId) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) ToManyMapProperty(org.apache.cayenne.reflect.ToManyMapProperty) Persistent(org.apache.cayenne.Persistent) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) DataRow(org.apache.cayenne.DataRow) DataObject(org.apache.cayenne.DataObject) ArrayList(java.util.ArrayList) List(java.util.List) DataObject(org.apache.cayenne.DataObject) HashMap(java.util.HashMap) Map(java.util.Map) CompoundDiff(org.apache.cayenne.graph.CompoundDiff)

Example 74 with Persistent

use of org.apache.cayenne.Persistent in project cayenne by apache.

the class DataRowStore method snapshotsUpdatedForObjects.

/**
 * Updates cached snapshots for the list of objects.
 *
 * @since 1.2
 */
void snapshotsUpdatedForObjects(List<Persistent> objects, List<? extends DataRow> snapshots, boolean refresh) {
    int size = objects.size();
    // sanity check
    if (size != snapshots.size()) {
        throw new IllegalArgumentException("Counts of objects and corresponding snapshots do not match. " + "Objects count: " + objects.size() + ", snapshots count: " + snapshots.size());
    }
    Map<ObjectId, DataRow> modified = null;
    Object eventPostedBy = null;
    for (int i = 0; i < size; i++) {
        Persistent object = objects.get(i);
        // skip null objects... possible since 3.0 in some EJBQL results
        if (object == null) {
            continue;
        }
        // skip HOLLOW objects as they likely were created from partial snapshots
        if (object.getPersistenceState() == PersistenceState.HOLLOW) {
            continue;
        }
        ObjectId oid = object.getObjectId();
        // add snapshots if refresh is forced, or if a snapshot is
        // missing
        DataRow cachedSnapshot = this.snapshots.get(oid);
        if (refresh || cachedSnapshot == null) {
            DataRow newSnapshot = snapshots.get(i);
            if (cachedSnapshot != null) {
                // use old snapshot if no changes occurred
                if (object instanceof DataObject && cachedSnapshot.equals(newSnapshot)) {
                    ((DataObject) object).setSnapshotVersion(cachedSnapshot.getVersion());
                    continue;
                } else {
                    newSnapshot.setReplacesVersion(cachedSnapshot.getVersion());
                }
            }
            if (modified == null) {
                modified = new HashMap<>();
                eventPostedBy = object.getObjectContext().getGraphManager();
            }
            modified.put(oid, newSnapshot);
        }
    }
    if (modified != null) {
        processSnapshotChanges(eventPostedBy, modified, Collections.<ObjectId>emptyList(), Collections.<ObjectId>emptyList(), Collections.<ObjectId>emptyList());
    }
}
Also used : DataObject(org.apache.cayenne.DataObject) ObjectId(org.apache.cayenne.ObjectId) DataObject(org.apache.cayenne.DataObject) Persistent(org.apache.cayenne.Persistent) DataRow(org.apache.cayenne.DataRow)

Example 75 with Persistent

use of org.apache.cayenne.Persistent in project cayenne by apache.

the class DataRowUtils method isToOneTargetModified.

/**
 * Checks if an object has its to-one relationship target modified in memory.
 */
static boolean isToOneTargetModified(ArcProperty property, Persistent object, ObjectDiff diff) {
    if (object.getPersistenceState() != PersistenceState.MODIFIED || diff == null) {
        return false;
    }
    if (property.isFault(object)) {
        return false;
    }
    Persistent toOneTarget = (Persistent) property.readPropertyDirectly(object);
    ObjectId currentId = (toOneTarget != null) ? toOneTarget.getObjectId() : null;
    // this would cover NEW objects (what are the other cases of temp id??)
    if (currentId != null && currentId.isTemporary()) {
        return true;
    }
    if (!diff.containsArcSnapshot(property.getName())) {
        return false;
    }
    ObjectId targetId = diff.getArcSnapshotValue(property.getName());
    return !Util.nullSafeEquals(currentId, targetId);
}
Also used : ObjectId(org.apache.cayenne.ObjectId) Persistent(org.apache.cayenne.Persistent)

Aggregations

Persistent (org.apache.cayenne.Persistent)88 ObjectId (org.apache.cayenne.ObjectId)38 Test (org.junit.Test)32 ArrayList (java.util.ArrayList)17 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)17 ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)17 DataObject (org.apache.cayenne.DataObject)13 Map (java.util.Map)12 ObjEntity (org.apache.cayenne.map.ObjEntity)10 EJBQLQuery (org.apache.cayenne.query.EJBQLQuery)10 AttributeProperty (org.apache.cayenne.reflect.AttributeProperty)10 DataRow (org.apache.cayenne.DataRow)8 PropertyVisitor (org.apache.cayenne.reflect.PropertyVisitor)8 ToManyProperty (org.apache.cayenne.reflect.ToManyProperty)8 ToOneProperty (org.apache.cayenne.reflect.ToOneProperty)8 Collection (java.util.Collection)7 HashMap (java.util.HashMap)7 ObjectContext (org.apache.cayenne.ObjectContext)6 DbEntity (org.apache.cayenne.map.DbEntity)6 List (java.util.List)5