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;
}
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);
}
}
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());
}
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());
}
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;
}
Aggregations