@SuppressWarnings("unchecked") static <T> Expression<T> toExpressionRecursively(From<?, ?> from, PropertyPath property) { Bindable<?> propertyPathModel = null; Bindable<?> model = from.getModel(); String segment = property.getSegment(); if (model instanceof ManagedType) { /* * Required to keep support for EclipseLink 2.4.x. TODO: Remove once we drop that (probably Dijkstra M1) * See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=413892 */ propertyPathModel = (Bindable<?>) ((ManagedType<?>) model).getAttribute(segment); } else { propertyPathModel = from.get(segment).getModel(); } if (requiresJoin(propertyPathModel, model instanceof PluralAttribute) && !isAlreadyFetched(from, segment)) { Join<?, ?> join = getOrCreateJoin(from, segment); return (Expression<T>) (property.hasNext() ? toExpressionRecursively(join, property.next()) : join); } else { Path<Object> path = from.get(segment); return (Expression<T>) (property.hasNext() ? toExpressionRecursively(path, property.next()) : path); } }
@SuppressWarnings("unchecked") static <T> Expression<T> toExpressionRecursively(From<?, ?> from, PropertyPath property) { Bindable<?> propertyPathModel = null; if (from.getModel() instanceof ManagedType) { /* * Avoid calling from.get(...) because this triggers the generation of an inner-join instead * of and outer-join in eclipse-link. * See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=413892 */ propertyPathModel = (Bindable<?>) ((ManagedType<?>) from.getModel()).getAttribute(property.getSegment()); } else { propertyPathModel = from.get(property.getSegment()).getModel(); } if (property.isCollection() || requiresJoin(propertyPathModel)) { Join<?, ?> join = getOrCreateJoin(from, property.getSegment()); return (Expression<T>) (property.hasNext() ? toExpressionRecursively(join, property.next()) : join); } else { Path<Object> path = from.get(property.getSegment()); return (Expression<T>) (property.hasNext() ? toExpressionRecursively(path, property.next()) : path); } }
/** * @see DATAJPA-403 */ @Test public void reusesExistingJoinForExpression() { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<User> query = builder.createQuery(User.class); Root<User> from = query.from(User.class); PropertyPath managerFirstname = PropertyPath.from("manager.firstname", User.class); PropertyPath managerLastname = PropertyPath.from("manager.lastname", User.class); QueryUtils.toExpressionRecursively(from, managerLastname); QueryUtils.toExpressionRecursively(from, managerFirstname); assertThat(from.getJoins(), hasSize(1)); }
/** * @see DATAJPA-401 */ @Test public void doesNotCreateAJoinForNonOptionalAssociation() { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<Order> query = builder.createQuery(Order.class); Root<Order> root = query.from(Order.class); QueryUtils.toExpressionRecursively(root, PropertyPath.from("customer", Order.class)); }
/** * @see DATAJPA-454 */ @Test public void createsJoingToTraverseCollectionPath() { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<User> query = builder.createQuery(User.class); Root<User> root = query.from(User.class); QueryUtils.toExpressionRecursively(root, PropertyPath.from("colleaguesLastname", User.class)); assertThat(root.getJoins(), hasSize(1)); }
/** * @see DATAJPA-401 */ @Test public void createsJoinForOptionalAssociation() { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<User> query = builder.createQuery(User.class); Root<User> root = query.from(User.class); QueryUtils.toExpressionRecursively(root, PropertyPath.from("manager", User.class)); assertThat(root.getJoins(), hasSize(1)); }
/** * Creates a criteria API {@link javax.persistence.criteria.Order} from the given {@link Order}. * * @param order the order to transform into a JPA {@link javax.persistence.criteria.Order} * @param root the {@link Root} the {@link Order} expression is based on * @param cb the {@link CriteriaBuilder} to build the {@link javax.persistence.criteria.Order} * with * @return */ @SuppressWarnings("unchecked") private static javax.persistence.criteria.Order toJpaOrder( Order order, Root<?> root, CriteriaBuilder cb) { PropertyPath property = PropertyPath.from(order.getProperty(), root.getJavaType()); Expression<?> expression = toExpressionRecursively(root, property); if (order.isIgnoreCase() && String.class.equals(expression.getJavaType())) { Expression<String> lower = cb.lower((Expression<String>) expression); return order.isAscending() ? cb.asc(lower) : cb.desc(lower); } else { return order.isAscending() ? cb.asc(expression) : cb.desc(expression); } }
static Expression<Object> toExpressionRecursively(Path<Object> path, PropertyPath property) { Path<Object> result = path.get(property.getSegment()); return property.hasNext() ? toExpressionRecursively(result, property.next()) : result; }