@Transactional(readOnly = true) public Object doWork(Session session, ServiceFactory sf) { String[] link = new String[annotation.length]; String[] ann = new String[annotation.length]; QueryBuilder qb = new QueryBuilder(); qb.select("this"); qb.from(cls.getName(), "this"); // Joins for (int i = 0; i < ann.length; i++) { if (value[i] != null) { link[i] = qb.unique_alias("link"); ann[i] = link[i] + "_child"; qb.join("this.annotationLinks", link[i], false, fetch[i]); qb.join(link[i] + ".child", ann[i], false, fetch[i]); } } // fetch annotations for (int i = 0; i < fetchAnnotationsCopy.size(); i++) { qb.join("this.annotationLinks", "fetchannlink" + i, false, true); qb.join("fetchannlink" + i + ".child", "fetchannchild" + i, false, true); } qb.where(); for (int i = 0; i < fetchAnnotationsCopy.size(); i++) { qb.and("fetchannchild" + i + ".class = " + fetchAnnotationsCopy.get(i).getSimpleName()); } ids(qb, "this."); ownerOrGroup(cls, qb, "this."); createdOrModified(cls, qb, "this."); for (int j = 0; j < annotation.length; j++) { // Main criteria if (useNamespace) { notNullOrLikeOrEqual( qb, ann + ".ns", type[j], annotation[j].getNs(), useLike, values.caseSensitive); } // If the value of the annotation is null, we assume that we are not // actually searching for null annotations (whose nullability is // actually a by-product of polymorphism), instead we assume the // null acts like a wildcard, in which case this search has been // added to the fetchAnnotationsCopy collection above. if (value[j] != null) { notNullOrLikeOrEqual( qb, ann[j] + "." + path[j], type[j], value[j], useLike, values.caseSensitive); } annotatedBetween(qb, ann[j] + "."); annotatedBy(qb, ann[j] + "."); } // orderBy for (String orderBy : values.orderBy) { String orderByPath = orderByPath(orderBy); boolean ascending = orderByAscending(orderBy); qb.order("this." + orderByPath, ascending); } log.debug(qb.toString()); return qb.query(session).list(); }