Search in sources :

Example 26 with DbJoin

use of org.apache.cayenne.map.DbJoin in project cayenne by apache.

the class DataContext method currentSnapshot.

/**
 * Returns a DataRow reflecting current, possibly uncommitted, object state.
 * <p>
 * <strong>Warning:</strong> This method will return a partial snapshot if
 * an object or one of its related objects that propagate their keys to this
 * object have temporary ids. DO NOT USE this method if you expect a DataRow
 * to represent a complete object state.
 * </p>
 *
 * @since 1.1
 */
public DataRow currentSnapshot(final Persistent object) {
    // for a HOLLOW object return snapshot from cache
    if (object.getPersistenceState() == PersistenceState.HOLLOW && object.getObjectContext() != null) {
        return getObjectStore().getSnapshot(object.getObjectId());
    }
    ObjEntity entity = getEntityResolver().getObjEntity(object);
    final ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(entity.getName());
    final DataRow snapshot = new DataRow(10);
    snapshot.setEntityName(entity.getName());
    descriptor.visitProperties(new PropertyVisitor() {

        public boolean visitAttribute(AttributeProperty property) {
            ObjAttribute objAttr = property.getAttribute();
            // processing compound attributes correctly
            snapshot.put(objAttr.getDbAttributePath(), property.readPropertyDirectly(object));
            return true;
        }

        public boolean visitToMany(ToManyProperty property) {
            // do nothing
            return true;
        }

        public boolean visitToOne(ToOneProperty property) {
            ObjRelationship rel = property.getRelationship();
            // if target doesn't propagates its key value, skip it
            if (rel.isSourceIndependentFromTargetChange()) {
                return true;
            }
            Object targetObject = property.readPropertyDirectly(object);
            if (targetObject == null) {
                return true;
            }
            // to avoid unneeded fault triggering
            if (targetObject instanceof Fault) {
                DataRow storedSnapshot = getObjectStore().getSnapshot(object.getObjectId());
                if (storedSnapshot == null) {
                    throw new CayenneRuntimeException("No matching objects found for ObjectId %s" + ". Object may have been deleted externally.", object.getObjectId());
                }
                DbRelationship dbRel = rel.getDbRelationships().get(0);
                for (DbJoin join : dbRel.getJoins()) {
                    String key = join.getSourceName();
                    snapshot.put(key, storedSnapshot.get(key));
                }
                return true;
            }
            // target is resolved and we have an FK->PK to it,
            // so extract it from target...
            Persistent target = (Persistent) targetObject;
            Map<String, Object> idParts = target.getObjectId().getIdSnapshot();
            // this method.
            if (idParts.isEmpty()) {
                return true;
            }
            DbRelationship dbRel = rel.getDbRelationships().get(0);
            Map<String, Object> fk = dbRel.srcFkSnapshotWithTargetSnapshot(idParts);
            snapshot.putAll(fk);
            return true;
        }
    });
    // process object id map
    // we should ignore any object id values if a corresponding attribute
    // is a part of relationship "toMasterPK", since those values have been
    // set above when db relationships where processed.
    Map<String, Object> thisIdParts = object.getObjectId().getIdSnapshot();
    if (thisIdParts != null) {
        // put only those that do not exist in the map
        for (Map.Entry<String, Object> entry : thisIdParts.entrySet()) {
            String nextKey = entry.getKey();
            if (!snapshot.containsKey(nextKey)) {
                snapshot.put(nextKey, entry.getValue());
            }
        }
    }
    return snapshot;
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) ObjAttribute(org.apache.cayenne.map.ObjAttribute) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) Fault(org.apache.cayenne.Fault) Persistent(org.apache.cayenne.Persistent) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) DataRow(org.apache.cayenne.DataRow) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty) ObjEntity(org.apache.cayenne.map.ObjEntity) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) DbRelationship(org.apache.cayenne.map.DbRelationship) DbJoin(org.apache.cayenne.map.DbJoin) DataObject(org.apache.cayenne.DataObject) Map(java.util.Map) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor)

Example 27 with DbJoin

use of org.apache.cayenne.map.DbJoin in project cayenne by apache.

the class DbGenerator method prepareDbEntities.

/**
 * Helper method that orders DbEntities to satisfy referential constraints
 * and returns an ordered list. It also filters out DerivedDbEntities.
 */
private void prepareDbEntities(Collection<DbEntity> excludedEntities) {
    if (excludedEntities == null) {
        excludedEntities = Collections.emptyList();
    }
    List<DbEntity> tables = new ArrayList<>();
    List<DbEntity> tablesWithAutoPk = new ArrayList<>();
    for (DbEntity nextEntity : map.getDbEntities()) {
        // tables with no columns are not included
        if (nextEntity.getAttributes().size() == 0) {
            logObj.info("Skipping entity with no attributes: " + nextEntity.getName());
            continue;
        }
        // check if this entity is explicitly excluded
        if (excludedEntities.contains(nextEntity)) {
            continue;
        }
        // tables with invalid DbAttributes are not included
        boolean invalidAttributes = false;
        for (final DbAttribute attr : nextEntity.getAttributes()) {
            if (attr.getType() == TypesMapping.NOT_DEFINED) {
                logObj.info("Skipping entity, attribute type is undefined: " + nextEntity.getName() + "." + attr.getName());
                invalidAttributes = true;
                break;
            }
        }
        if (invalidAttributes) {
            continue;
        }
        tables.add(nextEntity);
        // check if an automatic PK generation can be potentially supported
        // in this entity. For now simply check that the key is not
        // propagated
        Iterator<DbRelationship> relationships = nextEntity.getRelationships().iterator();
        // create a copy of the original PK list,
        // since the list will be modified locally
        List<DbAttribute> pkAttributes = new ArrayList<>(nextEntity.getPrimaryKeys());
        while (pkAttributes.size() > 0 && relationships.hasNext()) {
            DbRelationship nextRelationship = relationships.next();
            if (!nextRelationship.isToMasterPK()) {
                continue;
            }
            // so
            for (DbJoin join : nextRelationship.getJoins()) {
                pkAttributes.remove(join.getSource());
            }
        }
        // is not propagated via relationship
        if (pkAttributes.size() > 0) {
            tablesWithAutoPk.add(nextEntity);
        }
    }
    // sort table list
    if (tables.size() > 1) {
        EntitySorter sorter = new AshwoodEntitySorter();
        sorter.setEntityResolver(new EntityResolver(Collections.singleton(map)));
        sorter.sortDbEntities(tables, false);
    }
    this.dbEntitiesInInsertOrder = tables;
    this.dbEntitiesRequiringAutoPK = tablesWithAutoPk;
}
Also used : EntitySorter(org.apache.cayenne.map.EntitySorter) AshwoodEntitySorter(org.apache.cayenne.ashwood.AshwoodEntitySorter) DbEntity(org.apache.cayenne.map.DbEntity) AshwoodEntitySorter(org.apache.cayenne.ashwood.AshwoodEntitySorter) DbRelationship(org.apache.cayenne.map.DbRelationship) ArrayList(java.util.ArrayList) DbAttribute(org.apache.cayenne.map.DbAttribute) DbJoin(org.apache.cayenne.map.DbJoin) EntityResolver(org.apache.cayenne.map.EntityResolver)

Example 28 with DbJoin

use of org.apache.cayenne.map.DbJoin in project cayenne by apache.

the class FlattenedArcKey method eagerJoinSnapshot.

private Map<String, Object> eagerJoinSnapshot() {
    List<DbRelationship> relList = relationship.getDbRelationships();
    if (relList.size() != 2) {
        throw new CayenneRuntimeException("Only single-step flattened relationships are supported in this operation: %s", relationship);
    }
    DbRelationship firstDbRel = relList.get(0);
    DbRelationship secondDbRel = relList.get(1);
    // here ordering of ids is determined by 'relationship', so use id1, id2
    // instead of orderedIds
    Map<String, ?> sourceId = id1.getSourceId().getIdSnapshot();
    Map<String, ?> destinationId = id2.getSourceId().getIdSnapshot();
    Map<String, Object> snapshot = new HashMap<>(sourceId.size() + destinationId.size(), 1);
    for (DbJoin join : firstDbRel.getJoins()) {
        snapshot.put(join.getTargetName(), sourceId.get(join.getSourceName()));
    }
    for (DbJoin join : secondDbRel.getJoins()) {
        snapshot.put(join.getSourceName(), destinationId.get(join.getTargetName()));
    }
    return snapshot;
}
Also used : HashMap(java.util.HashMap) DbRelationship(org.apache.cayenne.map.DbRelationship) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) DbJoin(org.apache.cayenne.map.DbJoin)

Example 29 with DbJoin

use of org.apache.cayenne.map.DbJoin in project cayenne by apache.

the class DropRelationshipToModelIT method testForeignKey.

@Test
public void testForeignKey() throws Exception {
    dropTableIfPresent("NEW_TABLE");
    dropTableIfPresent("NEW_TABLE2");
    assertTokensAndExecute(0, 0);
    DbEntity dbEntity1 = new DbEntity("NEW_TABLE");
    DbAttribute e1col1 = new DbAttribute("ID", Types.INTEGER, dbEntity1);
    e1col1.setMandatory(true);
    e1col1.setPrimaryKey(true);
    dbEntity1.addAttribute(e1col1);
    DbAttribute e1col2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity1);
    e1col2.setMaxLength(10);
    e1col2.setMandatory(false);
    dbEntity1.addAttribute(e1col2);
    map.addDbEntity(dbEntity1);
    DbEntity dbEntity2 = new DbEntity("NEW_TABLE2");
    DbAttribute e2col1 = new DbAttribute("ID", Types.INTEGER, dbEntity2);
    e2col1.setMandatory(true);
    e2col1.setPrimaryKey(true);
    dbEntity2.addAttribute(e2col1);
    DbAttribute e2col2 = new DbAttribute("FK", Types.INTEGER, dbEntity2);
    dbEntity2.addAttribute(e2col2);
    DbAttribute e2col3 = new DbAttribute("NAME", Types.VARCHAR, dbEntity2);
    e2col3.setMaxLength(10);
    dbEntity2.addAttribute(e2col3);
    map.addDbEntity(dbEntity2);
    // create db relationships
    DbRelationship rel1To2 = new DbRelationship("rel1To2");
    rel1To2.setSourceEntity(dbEntity1);
    rel1To2.setTargetEntityName(dbEntity2);
    rel1To2.setToMany(true);
    rel1To2.addJoin(new DbJoin(rel1To2, e1col1.getName(), e2col2.getName()));
    dbEntity1.addRelationship(rel1To2);
    DbRelationship rel2To1 = new DbRelationship("rel2To1");
    rel2To1.setSourceEntity(dbEntity2);
    rel2To1.setTargetEntityName(dbEntity1);
    rel2To1.setToMany(false);
    rel2To1.addJoin(new DbJoin(rel2To1, e2col2.getName(), e1col1.getName()));
    dbEntity2.addRelationship(rel2To1);
    assertSame(rel1To2, rel2To1.getReverseRelationship());
    assertSame(rel2To1, rel1To2.getReverseRelationship());
    assertTokensAndExecute(3, 0);
    assertTokensAndExecute(0, 0);
    // create ObjEntities
    ObjEntity objEntity1 = new ObjEntity("NewTable");
    objEntity1.setDbEntity(dbEntity1);
    ObjAttribute oatr1 = new ObjAttribute("name");
    oatr1.setDbAttributePath(e1col2.getName());
    oatr1.setType("java.lang.String");
    objEntity1.addAttribute(oatr1);
    map.addObjEntity(objEntity1);
    ObjEntity objEntity2 = new ObjEntity("NewTable2");
    objEntity2.setDbEntity(dbEntity2);
    ObjAttribute o2a1 = new ObjAttribute("name");
    o2a1.setDbAttributePath(e2col3.getName());
    o2a1.setType("java.lang.String");
    objEntity2.addAttribute(o2a1);
    map.addObjEntity(objEntity2);
    // create ObjRelationships
    assertEquals(0, objEntity1.getRelationships().size());
    assertEquals(0, objEntity2.getRelationships().size());
    ObjRelationship objRel1To2 = new ObjRelationship("objRel1To2");
    objRel1To2.addDbRelationship(rel1To2);
    objRel1To2.setSourceEntity(objEntity1);
    objRel1To2.setTargetEntityName(objEntity2);
    objEntity1.addRelationship(objRel1To2);
    ObjRelationship objRel2To1 = new ObjRelationship("objRel2To1");
    objRel2To1.addDbRelationship(rel2To1);
    objRel2To1.setSourceEntity(objEntity2);
    objRel2To1.setTargetEntityName(objEntity1);
    objEntity2.addRelationship(objRel2To1);
    assertEquals(1, objEntity1.getRelationships().size());
    assertEquals(1, objEntity2.getRelationships().size());
    assertSame(objRel1To2, objRel2To1.getReverseRelationship());
    assertSame(objRel2To1, objRel1To2.getReverseRelationship());
    // remove relationship and fk from model, merge to db and read to model
    dbEntity2.removeRelationship(rel2To1.getName());
    dbEntity1.removeRelationship(rel1To2.getName());
    dbEntity2.removeAttribute(e2col2.getName());
    List<MergerToken> tokens = createMergeTokens();
    /**
     * Drop Relationship NEW_TABLE2->NEW_TABLE To DB
     * Drop Column NEW_TABLE2.FK To DB
     */
    assertTokens(tokens, 2, 0);
    for (MergerToken token : tokens) {
        if (token.getDirection().isToDb()) {
            execute(token);
        }
    }
    assertTokensAndExecute(0, 0);
    dbEntity2.addRelationship(rel2To1);
    dbEntity1.addRelationship(rel1To2);
    dbEntity2.addAttribute(e2col2);
    // try do use the merger to remove the relationship in the model
    tokens = createMergeTokens();
    assertTokens(tokens, 2, 0);
    // TODO: reversing the following two tokens should also reverse the
    // order
    MergerToken token0 = tokens.get(0).createReverse(mergerFactory());
    MergerToken token1 = tokens.get(1).createReverse(mergerFactory());
    if (!(token0 instanceof DropRelationshipToModel && token1 instanceof DropColumnToModel || token1 instanceof DropRelationshipToModel && token0 instanceof DropColumnToModel)) {
        fail();
    }
    execute(token0);
    execute(token1);
    // check after merging
    assertNull(dbEntity2.getAttribute(e2col2.getName()));
    assertEquals(0, dbEntity1.getRelationships().size());
    assertEquals(0, dbEntity2.getRelationships().size());
    assertEquals(0, objEntity1.getRelationships().size());
    assertEquals(0, objEntity2.getRelationships().size());
    // clear up
    dbEntity1.removeRelationship(rel1To2.getName());
    dbEntity2.removeRelationship(rel2To1.getName());
    map.removeObjEntity(objEntity1.getName(), true);
    map.removeDbEntity(dbEntity1.getName(), true);
    map.removeObjEntity(objEntity2.getName(), true);
    map.removeDbEntity(dbEntity2.getName(), true);
    resolver.refreshMappingCache();
    assertNull(map.getObjEntity(objEntity1.getName()));
    assertNull(map.getDbEntity(dbEntity1.getName()));
    assertNull(map.getObjEntity(objEntity2.getName()));
    assertNull(map.getDbEntity(dbEntity2.getName()));
    assertFalse(map.getDbEntities().contains(dbEntity1));
    assertFalse(map.getDbEntities().contains(dbEntity2));
    assertTokensAndExecute(2, 0);
    assertTokensAndExecute(0, 0);
}
Also used : ObjEntity(org.apache.cayenne.map.ObjEntity) ObjRelationship(org.apache.cayenne.map.ObjRelationship) DbEntity(org.apache.cayenne.map.DbEntity) ObjAttribute(org.apache.cayenne.map.ObjAttribute) DbRelationship(org.apache.cayenne.map.DbRelationship) DbAttribute(org.apache.cayenne.map.DbAttribute) MergerToken(org.apache.cayenne.dbsync.merge.token.MergerToken) DbJoin(org.apache.cayenne.map.DbJoin) Test(org.junit.Test)

Example 30 with DbJoin

use of org.apache.cayenne.map.DbJoin in project cayenne by apache.

the class DefaultObjectNameGeneratorTest method makeRelationship.

private DbRelationship makeRelationship(String srcEntity, String srcKey, String targetEntity, String targetKey, boolean toMany) {
    DbRelationship relationship = new DbRelationship();
    relationship.addJoin(new DbJoin(relationship, srcKey, targetKey));
    relationship.setToMany(toMany);
    relationship.setSourceEntity(new DbEntity(srcEntity));
    relationship.setTargetEntityName(targetEntity);
    return relationship;
}
Also used : DbEntity(org.apache.cayenne.map.DbEntity) DbRelationship(org.apache.cayenne.map.DbRelationship) DbJoin(org.apache.cayenne.map.DbJoin)

Aggregations

DbJoin (org.apache.cayenne.map.DbJoin)49 DbRelationship (org.apache.cayenne.map.DbRelationship)35 DbEntity (org.apache.cayenne.map.DbEntity)24 DbAttribute (org.apache.cayenne.map.DbAttribute)18 ObjRelationship (org.apache.cayenne.map.ObjRelationship)14 ObjAttribute (org.apache.cayenne.map.ObjAttribute)12 ObjEntity (org.apache.cayenne.map.ObjEntity)11 ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)9 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)8 ArrayList (java.util.ArrayList)7 AttributeProperty (org.apache.cayenne.reflect.AttributeProperty)7 PropertyVisitor (org.apache.cayenne.reflect.PropertyVisitor)7 ToManyProperty (org.apache.cayenne.reflect.ToManyProperty)7 ToOneProperty (org.apache.cayenne.reflect.ToOneProperty)7 HashMap (java.util.HashMap)6 Test (org.junit.Test)6 QuotingStrategy (org.apache.cayenne.dba.QuotingStrategy)5 EJBQLException (org.apache.cayenne.ejbql.EJBQLException)5 HashSet (java.util.HashSet)4 List (java.util.List)3