Search in sources :

Example 1 with RelationshipQuery

use of org.apache.cayenne.query.RelationshipQuery in project cayenne by apache.

the class DataDomainQueryAction method interceptRelationshipQuery.

private boolean interceptRelationshipQuery() {
    if (query instanceof RelationshipQuery) {
        RelationshipQuery relationshipQuery = (RelationshipQuery) query;
        if (relationshipQuery.isRefreshing()) {
            return !DONE;
        }
        ObjRelationship relationship = relationshipQuery.getRelationship(domain.getEntityResolver());
        // check if we can derive target PK from FK...
        if (relationship.isSourceIndependentFromTargetChange()) {
            return !DONE;
        }
        // we can assume that there is one and only one DbRelationship as
        // we previously checked that "!isSourceIndependentFromTargetChange"
        DbRelationship dbRelationship = relationship.getDbRelationships().get(0);
        // FK pointing to a unique field that is a 'fake' PK (CAY-1755)...
        // It is not sufficient to generate target ObjectId.
        DbEntity targetEntity = dbRelationship.getTargetEntity();
        if (dbRelationship.getJoins().size() < targetEntity.getPrimaryKeys().size()) {
            return !DONE;
        }
        if (cache == null) {
            return !DONE;
        }
        DataRow sourceRow = cache.getCachedSnapshot(relationshipQuery.getObjectId());
        if (sourceRow == null) {
            return !DONE;
        }
        ObjectId targetId = sourceRow.createTargetObjectId(relationship.getTargetEntityName(), dbRelationship);
        // null id means that FK is null...
        if (targetId == null) {
            this.response = new GenericResponse(Collections.EMPTY_LIST);
            return DONE;
        }
        // target id resolution (unlike source) should be polymorphic
        DataRow targetRow = polymorphicRowFromCache(targetId);
        if (targetRow != null) {
            this.response = new GenericResponse(Collections.singletonList(targetRow));
            return DONE;
        }
        // create a fault
        if (context != null && relationship.isSourceDefiningTargetPrecenseAndType(domain.getEntityResolver())) {
            // prevent passing partial snapshots to ObjectResolver per
            // CAY-724.
            // Create a hollow object right here and skip object conversion
            // downstream
            this.noObjectConversion = true;
            Object object = context.findOrCreateObject(targetId);
            this.response = new GenericResponse(Collections.singletonList(object));
            return DONE;
        }
    }
    return !DONE;
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) DbEntity(org.apache.cayenne.map.DbEntity) RelationshipQuery(org.apache.cayenne.query.RelationshipQuery) ObjectId(org.apache.cayenne.ObjectId) GenericResponse(org.apache.cayenne.util.GenericResponse) DbRelationship(org.apache.cayenne.map.DbRelationship) EmbeddableObject(org.apache.cayenne.EmbeddableObject) DataRow(org.apache.cayenne.DataRow)

Example 2 with RelationshipQuery

use of org.apache.cayenne.query.RelationshipQuery in project cayenne by apache.

the class ToOneFault method doResolveFault.

Object doResolveFault(Persistent sourceObject, String relationshipName) {
    RelationshipQuery query = new RelationshipQuery(sourceObject.getObjectId(), relationshipName, false);
    List objects = sourceObject.getObjectContext().performQuery(query);
    if (objects.isEmpty()) {
        return null;
    } else if (objects.size() == 1) {
        return objects.get(0);
    } else {
        throw new CayenneRuntimeException("Error resolving to-one fault. " + "More than one object found. Source Id: %s, relationship: %s", sourceObject.getObjectId(), relationshipName);
    }
}
Also used : RelationshipQuery(org.apache.cayenne.query.RelationshipQuery) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) List(java.util.List)

Example 3 with RelationshipQuery

use of org.apache.cayenne.query.RelationshipQuery in project cayenne by apache.

the class DataContextRelationshipQueryIT method testRefreshingToOne.

@Test
public void testRefreshingToOne() throws Exception {
    createOneArtistOnePaintingDataSet();
    Painting p = Cayenne.objectForPK(context, Painting.class, 1);
    // resolve artist once before running non-refreshing query, to check that we do
    // not refresh the object
    Artist a = Cayenne.objectForPK(context, Artist.class, 1);
    long v = a.getSnapshotVersion();
    int writeCalls = a.getPropertyWrittenDirectly();
    assertEquals("a1", a.getArtistName());
    assertEquals(1, tArtist.update().set("ARTIST_NAME", "a2").where("ARTIST_ID", 1).execute());
    RelationshipQuery toOne = new RelationshipQuery(p.getObjectId(), Painting.TO_ARTIST.getName(), true);
    List<Artist> related = context.performQuery(toOne);
    assertEquals(1, related.size());
    assertTrue(related.contains(a));
    assertEquals("a2", a.getArtistName());
    assertTrue("Looks like relationship query didn't cause a snapshot refresh", v < a.getSnapshotVersion());
    assertTrue("Looks like relationship query didn't cause a snapshot refresh", writeCalls < a.getPropertyWrittenDirectly());
}
Also used : Artist(org.apache.cayenne.testdo.testmap.Artist) RelationshipQuery(org.apache.cayenne.query.RelationshipQuery) Painting(org.apache.cayenne.testdo.testmap.Painting) Test(org.junit.Test)

Example 4 with RelationshipQuery

use of org.apache.cayenne.query.RelationshipQuery in project cayenne by apache.

the class DataContextRelationshipQueryIT method testUnrefreshingToOne.

@Test
public void testUnrefreshingToOne() throws Exception {
    createOneArtistOnePaintingDataSet();
    Painting p = Cayenne.objectForPK(context, Painting.class, 1);
    // resolve artist once before running non-refreshing query, to check that we do
    // not refresh the object
    Artist a = Cayenne.objectForPK(context, Artist.class, 1);
    long v = a.getSnapshotVersion();
    int writeCalls = a.getPropertyWrittenDirectly();
    assertEquals("a1", a.getArtistName());
    assertEquals(1, tArtist.update().set("ARTIST_NAME", "a2").where("ARTIST_ID", 1).execute());
    RelationshipQuery toOne = new RelationshipQuery(p.getObjectId(), Painting.TO_ARTIST.getName(), false);
    List<Artist> related = context.performQuery(toOne);
    assertEquals(1, related.size());
    assertTrue(related.contains(a));
    assertEquals("a1", a.getArtistName());
    assertEquals(v, a.getSnapshotVersion());
    assertEquals("Looks like relationship query caused snapshot refresh", writeCalls, a.getPropertyWrittenDirectly());
}
Also used : Artist(org.apache.cayenne.testdo.testmap.Artist) RelationshipQuery(org.apache.cayenne.query.RelationshipQuery) Painting(org.apache.cayenne.testdo.testmap.Painting) Test(org.junit.Test)

Example 5 with RelationshipQuery

use of org.apache.cayenne.query.RelationshipQuery in project cayenne by apache.

the class ObjectContextQueryAction method interceptRelationshipQuery.

protected boolean interceptRelationshipQuery() {
    if (query instanceof RelationshipQuery) {
        RelationshipQuery relationshipQuery = (RelationshipQuery) query;
        if (!relationshipQuery.isRefreshing()) {
            if (targetContext == null && relationshipQuery.getRelationship(actingContext.getEntityResolver()).isToMany()) {
                return !DONE;
            }
            ObjectId id = relationshipQuery.getObjectId();
            Object object = actingContext.getGraphManager().getNode(id);
            if (object != null) {
                ClassDescriptor descriptor = actingContext.getEntityResolver().getClassDescriptor(id.getEntityName());
                if (!descriptor.isFault(object)) {
                    ArcProperty property = (ArcProperty) descriptor.getProperty(relationshipQuery.getRelationshipName());
                    if (!property.isFault(object)) {
                        Object related = property.readPropertyDirectly(object);
                        List result;
                        // null to-one
                        if (related == null) {
                            result = new ArrayList(1);
                        } else // to-many List
                        if (related instanceof List) {
                            result = (List) related;
                        } else // to-many Set
                        if (related instanceof Set) {
                            result = new ArrayList((Set) related);
                        } else // to-many Map
                        if (related instanceof Map) {
                            result = new ArrayList(((Map) related).values());
                        } else // non-null to-one
                        {
                            result = new ArrayList(1);
                            result.add(related);
                        }
                        this.response = new ListResponse(result);
                        return DONE;
                    }
                    /**
                     * Workaround for CAY-1183. If a Relationship query is being sent
                     * from child context, we assure that local object is not NEW and
                     * relationship - unresolved (this way exception will occur). This
                     * helps when faulting objects that were committed to parent
                     * context (this), but not to database. Checking type of context's
                     * channel is the only way to ensure that we are on the top level
                     * of context hierarchy (there might be more than one-level-deep
                     * nested contexts).
                     */
                    if (((Persistent) object).getPersistenceState() == PersistenceState.NEW && !(actingContext.getChannel() instanceof BaseContext)) {
                        this.response = new ListResponse();
                        return DONE;
                    }
                }
            }
        }
    }
    return !DONE;
}
Also used : BaseContext(org.apache.cayenne.BaseContext) ArcProperty(org.apache.cayenne.reflect.ArcProperty) Set(java.util.Set) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) RelationshipQuery(org.apache.cayenne.query.RelationshipQuery) ObjectId(org.apache.cayenne.ObjectId) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) Persistent(org.apache.cayenne.Persistent) Map(java.util.Map)

Aggregations

RelationshipQuery (org.apache.cayenne.query.RelationshipQuery)7 List (java.util.List)3 Test (org.junit.Test)3 ArrayList (java.util.ArrayList)2 ObjectId (org.apache.cayenne.ObjectId)2 DbEntity (org.apache.cayenne.map.DbEntity)2 Artist (org.apache.cayenne.testdo.testmap.Artist)2 Painting (org.apache.cayenne.testdo.testmap.Painting)2 Map (java.util.Map)1 Set (java.util.Set)1 BaseContext (org.apache.cayenne.BaseContext)1 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)1 DataRow (org.apache.cayenne.DataRow)1 EmbeddableObject (org.apache.cayenne.EmbeddableObject)1 Persistent (org.apache.cayenne.Persistent)1 DataDomain (org.apache.cayenne.access.DataDomain)1 DbAttribute (org.apache.cayenne.map.DbAttribute)1 DbRelationship (org.apache.cayenne.map.DbRelationship)1 ObjRelationship (org.apache.cayenne.map.ObjRelationship)1 ObjectIdQuery (org.apache.cayenne.query.ObjectIdQuery)1