public void getOrderLargerThan() { EntityManager em = createEntityManager(); ExpressionBuilder builder1 = new ExpressionBuilder(Order.class); ExpressionBuilder builder2 = new ExpressionBuilder(Order.class); Expression o1Quantity = builder1.get("quantity"); Expression o2Quantity = builder2.get("quantity"); Expression quantityComparison = o1Quantity.greaterThan(o2Quantity); Expression o2CustomerName = builder2.get("customer").get("name"); Expression nameComparison = o2CustomerName.equal("Jane Smith"); Expression whereClause = quantityComparison.and(nameComparison); ReadAllQuery raq = new ReadAllQuery(); raq.setSelectionCriteria(whereClause); raq.setReferenceClass(Order.class); raq.useDistinct(); List expectedResult = (List) getServerSession().executeQuery(raq); String ejbqlString = "SELECT DISTINCT o1 FROM OrderBean o1, OrderBean o2 WHERE o1.quantity > o2.quantity AND" + " o2.customer.name = 'Jane Smith' "; List result = em.createQuery(ejbqlString).getResultList(); // only 1 order Assert.assertEquals( "Get order larger than test failed: data validation error", result.size(), 1); Assert.assertTrue( "Get order larger than test failed", comparer.compareObjects(expectedResult, result)); }
protected Expression processPropertyTracedownTooneOptimized( Attribute<?, ?> attr, Expression builder, List<Parameter> parameters) { ConditionQuery subQuery = getTraceDownQuery(); Expression finalExp = null; for (PropertyCondition subPc : subQuery.getConditions()) { if (subPc.isReturnSimpleExpression()) { Expression subExp = subPc.processProperty(builder.get(getProp()), parameters); if (finalExp == null) { finalExp = subExp; } else { finalExp = finalExp.and(subExp); } } else { // low-performance query since an extra layer of exists added // but this is the only way to make it work. // this situation is rare. So we may do not need to optimize it Expression subBuilder = new ExpressionBuilder(); Expression subExp = subPc.processProperty(subBuilder, parameters); ReportQuery childQuery = formRelationReportQuery(attr, subBuilder); childQuery.retrievePrimaryKeys(); childQuery.setSelectionCriteria(subBuilder.equal(builder.get(getProp())).and(subExp)); if (finalExp == null) { finalExp = builder.exists(childQuery); } else { finalExp = finalExp.and(builder.exists(childQuery)); } } } return finalExp; }
/** * Iterate the set of variables declared in an outer scope and connect the inner variable * expression with the outer one. */ public Expression joinVariables(Set variables) { if ((outer == null) || (variables == null) || variables.isEmpty()) { // not an inner query or no variables to join return null; } Expression expr = null; for (Iterator i = variables.iterator(); i.hasNext(); ) { String name = (String) i.next(); VariableNode var = new VariableNode(name); Expression innerExpr = var.generateExpression(this); Expression outerExpr = var.generateExpression(outer); // Join them only if they are not the same. if (innerExpr != outerExpr) { Expression join = innerExpr.equal(outerExpr); expr = var.appendExpression(expr, join); } } return expr; }
/** * @param type * @param builder * @param parameters * @return a fully parameterized query. A default value for this query should be set to query at a * late time. */ public Expression processProperty(Expression builder, List<Parameter> parameters) { Attribute<?, ?> attr = getAttribute(); Operator op = getOperator(); ConditionQueryParameter p; // convenient expression, only used by simple case Expression exp = builder.get(getProp()); switch (op) { // Operator for primtive type first: lt, le, gt, ge, eq, ne, between, // notbetween, like(String), notlike(String), checked, unchecked // oneof(in(...)), notoneof(notin(...)) case lt: return processPropertyLt(attr, builder, parameters); case le: return processPropertyLe(attr, builder, parameters); case eq: return processPropertyEq(attr, builder, parameters); case gt: return processPropertyGt(attr, builder, parameters); case ge: return processPropertyGe(attr, builder, parameters); case ne: return processPropertyNe(attr, builder, parameters); case between: return processPropertyBetween(attr, builder, parameters); case notbetween: return processPropertyNotBetween(attr, builder, parameters); case like: return processPropertyLike(attr, builder, parameters); case notlike: return processPropertyNotLike(attr, builder, parameters); case oneof: return processPropertyOneof(attr, builder, parameters); case notoneof: // for direct follection. return processPropertyNotOneof(attr, builder, parameters); case checked: exp = exp.equal(true); return exp; case unchecked: exp = exp.equal(false); return exp; /** *************** The above is for comparison of primitive value */ // null, notnull are not primitive attr, only property with single // value case notnull: if (attr.isCollection()) { return this.processPropertyNotEmpty(attr, builder, parameters); } else { exp = exp.notNull(); return exp; } case isnull: if (attr.isCollection()) { return this.processPropertyEmpty(attr, builder, parameters); } else { if (JpaMetamodelHelper.isRelation(attr) && !JpaMetamodelHelper.isRelationOwner(attr)) { ExpressionBuilder main = new ExpressionBuilder(); ReportQuery subQuery = formRelationReportQuery(attr, main); subQuery.setSelectionCriteria(main.equal(builder.get(getProp()))); subQuery.addAttribute("id"); exp = builder.notExists(subQuery); } else { exp = exp.isNull(); } return exp; } // -----------------size operation for collection: size, sizegt, // sizelt, empty, notempty case size: // do not work for simple collection. // need test case for simple collection p = new ConditionQueryParameter(this, getQuery().getPrefix() + parameters.size()); parameters.add(p); if (JpaMetamodelHelper.isRelation(attr)) { exp = builder.size(getProp()).equal(builder.getParameter(p.getParamName())); } else { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=396892 exp = builder .subQuery(this.formSizeReportQuery(attr, builder)) .equal(builder.getParameter(p.getParamName())); } return exp; case sizeGt: p = new ConditionQueryParameter(this, getQuery().getPrefix() + parameters.size()); parameters.add(p); if (JpaMetamodelHelper.isRelation(attr)) { exp = builder.size(getProp()).greaterThan(builder.getParameter(p.getParamName())); } else { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=396892 exp = builder .subQuery(this.formSizeReportQuery(attr, builder)) .greaterThan(builder.getParameter(p.getParamName())); } return exp; case sizeLt: p = new ConditionQueryParameter(this, getQuery().getPrefix() + parameters.size()); parameters.add(p); if (JpaMetamodelHelper.isRelation(attr)) { exp = builder.size(getProp()).lessThan(builder.getParameter(p.getParamName())); } else { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=396892 exp = builder .subQuery(this.formSizeReportQuery(attr, builder)) .lessThan(builder.getParameter(p.getParamName())); } return exp; case empty: return this.processPropertyEmpty(attr, builder, parameters); case notempty: return this.processPropertyNotEmpty(attr, builder, parameters); case tracedown: if (attr.isCollection()) { if (isAllColllectionMode()) { return this.processPropertyTracedownToManyAll(attr, builder, parameters); } else if (isNoneColllectionMode()) { return this.processPropertyTracedownToManyNone(attr, builder, parameters); } else { return this.processPropertyTracedownToManySomeOptimized(attr, builder, parameters); } } else { return this.processPropertyTracedownTooneOptimized(attr, builder, parameters); } default: break; } return null; }