use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.
the class SelectQueryMetadata method buildEntityResultForColumn.
/**
* Collect metadata for column that will be unwrapped to full entity in the final SQL
* (possibly including joint prefetch).
* This information will be used to correctly create Persistent object back from raw result.
*
* This method is actually repeating logic of
* {@link org.apache.cayenne.access.translator.select.DefaultSelectTranslator#appendQueryColumns}.
* Here we don't care about intermediate joins and few other things so it's shorter.
* Logic of these methods should be unified and simplified, possibly to a single source of metadata,
* generated only once and used everywhere.
*
* @param query original query
* @param column full object column
* @param resolver entity resolver to get ObjEntity and ClassDescriptor
* @return Entity result
*/
private EntityResult buildEntityResultForColumn(SelectQuery<?> query, Property<?> column, EntityResolver resolver) {
final EntityResult result = new EntityResult(column.getType());
// Collecting visitor for ObjAttributes and toOne relationships
PropertyVisitor visitor = new PropertyVisitor() {
public boolean visitAttribute(AttributeProperty property) {
ObjAttribute oa = property.getAttribute();
Iterator<CayenneMapEntry> dbPathIterator = oa.getDbPathIterator();
while (dbPathIterator.hasNext()) {
CayenneMapEntry pathPart = dbPathIterator.next();
if (pathPart instanceof DbAttribute) {
result.addDbField(pathPart.getName(), pathPart.getName());
}
}
return true;
}
public boolean visitToMany(ToManyProperty property) {
return true;
}
public boolean visitToOne(ToOneProperty property) {
DbRelationship dbRel = property.getRelationship().getDbRelationships().get(0);
List<DbJoin> joins = dbRel.getJoins();
for (DbJoin join : joins) {
if (!join.getSource().isPrimaryKey()) {
result.addDbField(join.getSource().getName(), join.getSource().getName());
}
}
return true;
}
};
ObjEntity oe = resolver.getObjEntity(column.getType());
DbEntity table = oe.getDbEntity();
// Additionally collect PKs
for (DbAttribute dba : table.getPrimaryKeys()) {
result.addDbField(dba.getName(), dba.getName());
}
ClassDescriptor descriptor = resolver.getClassDescriptor(oe.getName());
descriptor.visitAllProperties(visitor);
// Collection columns for joint prefetch
if (query.getPrefetchTree() != null) {
for (PrefetchTreeNode prefetch : query.getPrefetchTree().adjacentJointNodes()) {
// for each prefetch add columns from the target entity
Expression prefetchExp = ExpressionFactory.exp(prefetch.getPath());
ASTDbPath dbPrefetch = (ASTDbPath) oe.translateToDbPath(prefetchExp);
DbRelationship r = findRelationByPath(table, dbPrefetch);
if (r == null) {
throw new CayenneRuntimeException("Invalid joint prefetch '%s' for entity: %s", prefetch, oe.getName());
}
// go via target OE to make sure that Java types are mapped correctly...
ObjRelationship targetRel = (ObjRelationship) prefetchExp.evaluate(oe);
ObjEntity targetEntity = targetRel.getTargetEntity();
prefetch.setEntityName(targetRel.getSourceEntity().getName());
String labelPrefix = dbPrefetch.getPath();
Set<String> seenNames = new HashSet<>();
for (ObjAttribute oa : targetEntity.getAttributes()) {
Iterator<CayenneMapEntry> dbPathIterator = oa.getDbPathIterator();
while (dbPathIterator.hasNext()) {
Object pathPart = dbPathIterator.next();
if (pathPart instanceof DbAttribute) {
DbAttribute attribute = (DbAttribute) pathPart;
if (seenNames.add(attribute.getName())) {
result.addDbField(labelPrefix + '.' + attribute.getName(), labelPrefix + '.' + attribute.getName());
}
}
}
}
// append remaining target attributes such as keys
DbEntity targetDbEntity = r.getTargetEntity();
for (DbAttribute attribute : targetDbEntity.getAttributes()) {
if (seenNames.add(attribute.getName())) {
result.addDbField(labelPrefix + '.' + attribute.getName(), labelPrefix + '.' + attribute.getName());
}
}
}
}
return result;
}
use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.
the class SelectQueryPrefetchRouterAction method startDisjointPrefetch.
public boolean startDisjointPrefetch(PrefetchTreeNode node) {
// don't do anything to root
if (node == query.getPrefetchTree()) {
return true;
}
String prefetchPath = node.getPath();
// find last relationship
Iterator<CayenneMapEntry> it = classDescriptor.getEntity().resolvePathComponents(prefetchPath);
ObjRelationship relationship = null;
while (it.hasNext()) {
relationship = (ObjRelationship) it.next();
}
if (relationship == null) {
throw new CayenneRuntimeException("Invalid prefetch '%s' for entity '%s'", prefetchPath, classDescriptor.getEntity().getName());
}
// chain query and entity qualifiers
Expression queryQualifier = query.getQualifier();
Expression entityQualifier = classDescriptor.getEntityInheritanceTree().qualifierForEntityAndSubclasses();
if (entityQualifier != null) {
queryQualifier = (queryQualifier != null) ? queryQualifier.andExp(entityQualifier) : entityQualifier;
}
// create and configure PrefetchSelectQuery
PrefetchSelectQuery prefetchQuery = new PrefetchSelectQuery(prefetchPath, relationship);
prefetchQuery.setStatementFetchSize(query.getStatementFetchSize());
prefetchQuery.setQualifier(classDescriptor.getEntity().translateToRelatedEntity(queryQualifier, prefetchPath));
if (relationship.isSourceIndependentFromTargetChange()) {
// setup extra result columns to be able to relate result rows to the parent
// result objects.
prefetchQuery.addResultPath("db:" + relationship.getReverseDbRelationshipPath());
}
// pass prefetch subtree to enable joint prefetches...
prefetchQuery.setPrefetchTree(node);
// route...
prefetchQuery.route(router, resolver, null);
return true;
}
use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.
the class PersistentDescriptor method indexAddedProperty.
void indexAddedProperty(PropertyDescriptor property) {
if (property instanceof AttributeProperty) {
AttributeProperty attributeProperty = (AttributeProperty) property;
ObjAttribute attribute = attributeProperty.getAttribute();
if (attribute.isPrimaryKey()) {
if (idProperties == null) {
idProperties = new ArrayList<>(2);
}
idProperties.add(attributeProperty);
}
} else if (property instanceof ArcProperty) {
ObjRelationship relationship = ((ArcProperty) property).getRelationship();
ObjRelationship reverseRelationship = relationship.getReverseRelationship();
if (reverseRelationship != null && "java.util.Map".equals(reverseRelationship.getCollectionType())) {
if (mapArcProperties == null) {
mapArcProperties = new ArrayList<>(2);
}
mapArcProperties.add((ArcProperty) property);
}
}
}
use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.
the class RelationshipFault method updateReverse.
// see if reverse relationship is to-one and we can connect source to
// results....
protected void updateReverse(List<E> resolved) {
EntityResolver resolver = relationshipOwner.getObjectContext().getEntityResolver();
ObjEntity sourceEntity = resolver.getObjEntity(relationshipOwner.getObjectId().getEntityName());
ObjRelationship relationship = sourceEntity.getRelationship(relationshipName);
ObjRelationship reverse = relationship.getReverseRelationship();
if (reverse != null && !reverse.isToMany()) {
PropertyDescriptor property = resolver.getClassDescriptor(reverse.getSourceEntity().getName()).getProperty(reverse.getName());
for (Object o : resolved) {
property.writePropertyDirectly(o, null, relationshipOwner);
}
}
}
use of org.apache.cayenne.map.ObjRelationship in project cayenne by apache.
the class ObjRelationshipHandlerTest method testLoad.
@Test
public void testLoad() throws Exception {
final DataMap map = new DataMap();
ObjEntity entity = new ObjEntity("ArtGroup");
map.addObjEntity(entity);
assertEquals(0, entity.getRelationships().size());
parse("obj-relationship", new HandlerFactory() {
@Override
public NamespaceAwareNestedTagHandler createHandler(NamespaceAwareNestedTagHandler parent) {
return new ObjRelationshipHandler(parent, map);
}
});
assertEquals(1, entity.getRelationships().size());
ObjRelationship relationship = entity.getRelationship("artistArray");
assertNotNull(relationship);
assertEquals(DeleteRule.CASCADE, relationship.getDeleteRule());
assertEquals("java.util.Map", relationship.getCollectionType());
assertEquals("artistName", relationship.getMapKey());
assertEquals("Artist", relationship.getTargetEntityName());
assertTrue(relationship.isUsedForLocking());
}
Aggregations