public static Specification<User> byKeyword(String keyword, String role, String active){ return (Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> { List<Predicate> predicates = new ArrayList<>(); if (StringUtils.hasText(keyword)) { predicates.add( cb.or( cb.like(root.get(User_.email), "%" + keyword + "%"), cb.like(root.get(User_.username), "%" + keyword + "%") )); } if (StringUtils.hasText(role) && !"ALL".equals(role)) { ListJoin<User, String> roleJoin = root.join(User_.roles); predicates.add(cb.equal(roleJoin, role)); } if (StringUtils.hasText(active)) { predicates.add(cb.equal(root.get(User_.active), Boolean.valueOf(active))); } return cb.and(predicates.toArray(new Predicate[predicates.size()])); }; }
public static Specification<HarvestReport> hasEndOfHuntingReportAndFieldsSpeciesIsPermitSpecies(final Long fieldsId) { return (root, query, cb) -> { final Subquery<Integer> permitQuery = query.subquery(Integer.class); final Root<HarvestPermit> permitRoot = permitQuery.from(HarvestPermit.class); final ListJoin<HarvestPermit, HarvestPermitSpeciesAmount> speciesAmounts = permitRoot.join(HarvestPermit_.speciesAmounts); final Path<GameSpecies> speciesAmountsSpecies = speciesAmounts.get(HarvestPermitSpeciesAmount_.gameSpecies); final Subquery<Integer> fieldsQuery = query.subquery(Integer.class); final Root<HarvestReportFields> fieldsRoot = fieldsQuery.from(HarvestReportFields.class); final Predicate permitSpeciesEqualToFieldsSpecies = cb.and( cb.equal(fieldsRoot.get(HarvestReportFields_.id), fieldsId), cb.equal(fieldsRoot.get(HarvestReportFields_.species), speciesAmountsSpecies)); final Predicate fieldsExists = cb.exists(fieldsQuery.select(cb.literal(1)).where(permitSpeciesEqualToFieldsSpecies)); return cb.exists(permitQuery .select(cb.literal(1)) .where(cb.and( cb.equal(permitRoot.join(HarvestPermit_.endOfHuntingReport), permitQuery.correlate(root)), fieldsExists)) ); }; }
@Override public Page<Target> findTargetsOfRolloutGroupByRsql(final Pageable pageable, final Long rolloutGroupId, final String rsqlParam) { throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId); final Specification<JpaTarget> rsqlSpecification = RSQLUtility.parse(rsqlParam, TargetFields.class, virtualPropertyReplacer); return convertTPage(targetRepository.findAll((root, query, criteriaBuilder) -> { final ListJoin<JpaTarget, RolloutTargetGroup> rolloutTargetJoin = root.join(JpaTarget_.rolloutTargetGroup); return criteriaBuilder.and(rsqlSpecification.toPredicate(root, query, criteriaBuilder), criteriaBuilder.equal( rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup).get(JpaRolloutGroup_.id), rolloutGroupId)); }, pageable), pageable); }
@Override public Page<String> findMessagesByActionStatusId(final Pageable pageable, final Long actionStatusId) { final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaQuery<Long> countMsgQuery = cb.createQuery(Long.class); final Root<JpaActionStatus> countMsgQueryFrom = countMsgQuery.distinct(true).from(JpaActionStatus.class); final ListJoin<JpaActionStatus, String> cJoin = countMsgQueryFrom.joinList("messages", JoinType.LEFT); countMsgQuery.select(cb.count(cJoin)) .where(cb.equal(countMsgQueryFrom.get(JpaActionStatus_.id), actionStatusId)); final Long totalCount = entityManager.createQuery(countMsgQuery).getSingleResult(); final CriteriaQuery<String> msgQuery = cb.createQuery(String.class); final Root<JpaActionStatus> as = msgQuery.from(JpaActionStatus.class); final ListJoin<JpaActionStatus, String> join = as.joinList("messages", JoinType.LEFT); final CriteriaQuery<String> selMsgQuery = msgQuery.select(join); selMsgQuery.where(cb.equal(as.get(JpaActionStatus_.id), actionStatusId)); final List<String> result = entityManager.createQuery(selMsgQuery).setFirstResult(pageable.getOffset()) .setMaxResults(pageable.getPageSize()).getResultList().stream().collect(Collectors.toList()); return new PageImpl<>(result, pageable, totalCount); }
public List<Product> findForPurchaseCustomerPremium() { // main query on products CriteriaQuery<Product> query = em.getCriteriaBuilder().createQuery(Product.class); Root<Product> from = query.from(Product.class); // subquery on product ids Subquery<Long> subQuery = query.subquery(Long.class); Root<Customer> subFrom = subQuery.from(Customer.class); ListJoin<Customer, Purchase> joinPurchase = subFrom.join(Customer_.purchases); ListJoin<Purchase, Product> joinProduct = joinPurchase.join(Purchase_.products); // Explicitly add to SELECT clause; otherwise, throws Error Code: 30000 SQLSyntaxErrorException subQuery.select(joinProduct.get(Product_.id)).distinct(true); subQuery.where(em.getCriteriaBuilder().equal(subFrom.get(Customer_.premium), true)); query.select(from); query.where(em.getCriteriaBuilder().in(from.get(Product_.id)).value(subQuery)); return em.createQuery(query).getResultList(); }
public Map<Customer, Double> sumPriceByPurchaseCustomer() { // Create "tuple" query for use with groupBy; otherwise, throws PersistenceException: Exception [EclipseLink-6051] CriteriaQuery<Tuple> query = em.getCriteriaBuilder().createTupleQuery(); Root<Customer> from = query.from(Customer.class); ListJoin<Customer, Purchase> joinPurchase = from.join(Customer_.purchases); ListJoin<Purchase, Product> joinProduct = joinPurchase.join(Purchase_.products); query.multiselect(from.get(BaseModel_.id), em.getCriteriaBuilder().sum(joinProduct.get(Product_.price))); query.groupBy(from.get(BaseModel_.id)); List<Tuple> results = em.createQuery(query).getResultList(); Map<Customer, Double> ret = new HashMap<>(); for (Tuple result : results) { Object[] arr = result.toArray(); ret.put(customerService.findById((Long)arr[0]), ((Double)arr[1])); } return ret; }
public Reservation getByProviderRequestWithPessimisticWriteLock(String requesterNsa, String providerNsa, String correlationId) { CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<Reservation> query = builder.createQuery(Reservation.class); Root<Reservation> root = query.from(Reservation.class); ListJoin<Reservation, NsiV2Message> providerRequests = root.join(Reservation_.providerRequests); query.where(builder.and( builder.equal(providerRequests.get(NsiV2Message_.requesterNsa), requesterNsa), builder.equal(providerRequests.get(NsiV2Message_.providerNsa), providerNsa), builder.equal(providerRequests.get(NsiV2Message_.correlationId), correlationId), builder.equal(providerRequests.get(NsiV2Message_.role), NsiV2Message.Role.REQUESTER), builder.equal(providerRequests.get(NsiV2Message_.type), NsiV2Message.Type.REQUEST))); return entityManager.createQuery(query).setLockMode(LockModeType.PESSIMISTIC_WRITE).getSingleResult(); }
@Override public QueryFilter<SemanticDescriptor> byService(long serviceId) { ListJoin<SemanticDescriptor, DataManipulationService> services = root .join(SemanticDescriptor_.describedServices); Predicate predicate = criteriaBuilder.equal(services.get(DataManipulationService_.id), serviceId); return constructQueryFilter(predicate); }
/** * @param installedTargetId * the targetID which is installed to a distribution set to * search for. * @return the specification to search for a distribution set which is * installed to the given targetId */ public static Specification<JpaDistributionSet> installedTarget(final String installedTargetId) { return (dsRoot, query, cb) -> { final ListJoin<JpaDistributionSet, JpaTarget> installedTargetJoin = dsRoot .join(JpaDistributionSet_.installedAtTargets, JoinType.INNER); return cb.equal(installedTargetJoin.get(JpaTarget_.controllerId), installedTargetId); }; }
/** * @param assignedTargetId * the targetID which is assigned to a distribution set to search * for. * @return the specification to search for a distribution set which is * assigned to the given targetId */ public static Specification<JpaDistributionSet> assignedTarget(final String assignedTargetId) { return (dsRoot, query, cb) -> { final ListJoin<JpaDistributionSet, JpaTarget> assignedTargetJoin = dsRoot .join(JpaDistributionSet_.assignedToTargets, JoinType.INNER); return cb.equal(assignedTargetJoin.get(JpaTarget_.controllerId), assignedTargetId); }; }
/** * {@link Specification} for retrieving {@link Target}s that don't have the * given distribution set in their action history * * @param distributionSetId * the ID of the distribution set which must not be assigned * @return the {@link Target} {@link Specification} */ public static Specification<JpaTarget> hasNotDistributionSetInActions(final Long distributionSetId) { return (targetRoot, query, cb) -> { final ListJoin<JpaTarget, JpaAction> actionsJoin = targetRoot.join(JpaTarget_.actions, JoinType.LEFT); actionsJoin.on(cb.equal(actionsJoin.get(JpaAction_.distributionSet).get(JpaDistributionSet_.id), distributionSetId)); return cb.isNull(actionsJoin.get(JpaAction_.id)); }; }
/** * {@link Specification} for retrieving {@link Target}s that are not in the * given {@link RolloutGroup}s * * @param groups * the {@link RolloutGroup}s * @return the {@link Target} {@link Specification} */ public static Specification<JpaTarget> isNotInRolloutGroups(final Collection<Long> groups) { return (targetRoot, query, cb) -> { final ListJoin<JpaTarget, RolloutTargetGroup> rolloutTargetJoin = targetRoot .join(JpaTarget_.rolloutTargetGroup, JoinType.LEFT); final Predicate inRolloutGroups = rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup) .get(JpaRolloutGroup_.id).in(groups); rolloutTargetJoin.on(inRolloutGroups); return cb.isNull(rolloutTargetJoin.get(RolloutTargetGroup_.target)); }; }
/** * {@link Specification} for retrieving {@link Target}s that have no Action * of the {@link RolloutGroup}. * * @param group * the {@link RolloutGroup} * @return the {@link Target} {@link Specification} */ public static Specification<JpaTarget> hasNoActionInRolloutGroup(final Long group) { return (targetRoot, query, cb) -> { final ListJoin<JpaTarget, RolloutTargetGroup> rolloutTargetJoin = targetRoot .join(JpaTarget_.rolloutTargetGroup, JoinType.INNER); rolloutTargetJoin.on( cb.equal(rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup).get(JpaRolloutGroup_.id), group)); final ListJoin<JpaTarget, JpaAction> actionsJoin = targetRoot.join(JpaTarget_.actions, JoinType.LEFT); actionsJoin.on(cb.equal(actionsJoin.get(JpaAction_.rolloutGroup).get(JpaRolloutGroup_.id), group)); return cb.isNull(actionsJoin.get(JpaAction_.id)); }; }
@Override public Page<TargetWithActionStatus> findAllTargetsOfRolloutGroupWithActionStatus(final Pageable pageRequest, final Long rolloutGroupId) { throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId); final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); final CriteriaQuery<Object[]> query = cb.createQuery(Object[].class); final CriteriaQuery<Long> countQuery = cb.createQuery(Long.class); final Root<RolloutTargetGroup> targetRoot = query.distinct(true).from(RolloutTargetGroup.class); final Join<RolloutTargetGroup, JpaTarget> targetJoin = targetRoot.join(RolloutTargetGroup_.target); final ListJoin<RolloutTargetGroup, JpaAction> actionJoin = targetRoot.join(RolloutTargetGroup_.actions, JoinType.LEFT); final Root<RolloutTargetGroup> countQueryFrom = countQuery.distinct(true).from(RolloutTargetGroup.class); countQueryFrom.join(RolloutTargetGroup_.target); countQueryFrom.join(RolloutTargetGroup_.actions, JoinType.LEFT); countQuery.select(cb.count(countQueryFrom)).where(cb .equal(countQueryFrom.get(RolloutTargetGroup_.rolloutGroup).get(JpaRolloutGroup_.id), rolloutGroupId)); final Long totalCount = entityManager.createQuery(countQuery).getSingleResult(); final CriteriaQuery<Object[]> multiselect = query.multiselect(targetJoin, actionJoin.get(JpaAction_.status)) .where(cb.equal(targetRoot.get(RolloutTargetGroup_.rolloutGroup).get(JpaRolloutGroup_.id), rolloutGroupId)); final List<TargetWithActionStatus> targetWithActionStatus = entityManager.createQuery(multiselect) .setFirstResult(pageRequest.getOffset()).setMaxResults(pageRequest.getPageSize()).getResultList() .stream().map(o -> new TargetWithActionStatus((Target) o[0], (Action.Status) o[1])) .collect(Collectors.toList()); return new PageImpl<>(targetWithActionStatus, pageRequest, totalCount); }
@Override public ResolvedPermissions resolveSourceConfigPermissions( AuthorizedUserEntity etlUser, SourceConfigEntity entity) { EntityManager entityManager = getEntityManager(); CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Tuple> q = cb.createQuery(Tuple.class); Root<SourceConfigGroupMembership> groupMembership = q.from(SourceConfigGroupMembership.class); q.select( cb.tuple( cb.greatest(cb.selectCase().when(cb.equal(groupMembership.get(SourceConfigGroupMembership_.groupRead), true), 1).otherwise(0).as(Integer.class)), cb.greatest(cb.selectCase().when(cb.equal(groupMembership.get(SourceConfigGroupMembership_.groupWrite), true), 1).otherwise(0).as(Integer.class)), cb.greatest(cb.selectCase().when(cb.equal(groupMembership.get(SourceConfigGroupMembership_.groupExecute), true), 1).otherwise(0).as(Integer.class)) )); ListJoin<EtlGroup, AuthorizedUserEntity> join = groupMembership.join(SourceConfigGroupMembership_.group).join(EtlGroup_.users); q.where( cb.and( cb.equal(groupMembership.get(SourceConfigGroupMembership_.sourceConfig).get(SourceConfigEntity_.id), entity.getId()), cb.equal(join.get(AuthorizedUserEntity_.id), etlUser.getId()) ) ); q.groupBy(groupMembership.get(SourceConfigGroupMembership_.sourceConfig).get(SourceConfigEntity_.id)); List<Tuple> resultList = entityManager.createQuery(q).getResultList(); if (resultList.isEmpty()) { return new ResolvedPermissions(false, false, false); } else { Tuple result = resultList.get(0); return new ResolvedPermissions(result.get(0, Integer.class) == 1, result.get(1, Integer.class) == 1, result.get(2, Integer.class) == 1); } }
@Override public ResolvedPermissions resolveDestinationPermissions( AuthorizedUserEntity etlUser, DestinationEntity entity) { EntityManager entityManager = getEntityManager(); CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<Tuple> q = cb.createQuery(Tuple.class); Root<DestinationGroupMembership> groupMembership = q.from(DestinationGroupMembership.class); q.select( cb.tuple( cb.greatest(cb.selectCase().when(cb.equal(groupMembership.get(DestinationGroupMembership_.groupRead), true), 1).otherwise(0).as(Integer.class)), cb.greatest(cb.selectCase().when(cb.equal(groupMembership.get(DestinationGroupMembership_.groupWrite), true), 1).otherwise(0).as(Integer.class)), cb.greatest(cb.selectCase().when(cb.equal(groupMembership.get(DestinationGroupMembership_.groupExecute), true), 1).otherwise(0).as(Integer.class)) )); ListJoin<EtlGroup, AuthorizedUserEntity> join = groupMembership.join(DestinationGroupMembership_.group).join(EtlGroup_.users); q.where( cb.and( cb.equal(groupMembership.get(DestinationGroupMembership_.destination).get(DestinationEntity_.id), entity.getId()), cb.equal(join.get(AuthorizedUserEntity_.id), etlUser.getId()) ) ); q.groupBy(groupMembership.get(DestinationGroupMembership_.destination).get(DestinationEntity_.id)); TypedQuery<Tuple> typedQuery = entityManager.createQuery(q); List<Tuple> resultList = typedQuery.getResultList(); if (resultList.isEmpty()) { return new ResolvedPermissions(false, false, false); } else { Tuple result = resultList.get(0); return new ResolvedPermissions(result.get(0, Integer.class) == 1, result.get(1, Integer.class) == 1, result.get(2, Integer.class) == 1); } }
private void testJoin() { CriteriaBuilder cb = repository.getCriteriaBuilder(); CriteriaQuery<ProductEntity> cq = cb.createQuery(ProductEntity.class); Root<ProductEntity> products = cq.from(ProductEntity.class); ListJoin<ProductEntity, SubProductEntity> joinSubProducts = products.join(ProductEntity_.subProducts); cq.where(cb.equal(joinSubProducts.get(SubProductEntity_.name), "sp1")); // List<Product> ps = repository.executeQuery(cq); assertEquals(1, ps.size()); assertEquals("p2", ps.get(0).getName()); assertEquals("sp1", ps.get(0).getSubProducts().get(0).getName()); }
public Reservation getByProviderRequestWithPessimisticWriteLock(Long providerRequestId) { CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<Reservation> query = builder.createQuery(Reservation.class); Root<Reservation> root = query.from(Reservation.class); ListJoin<Reservation, NsiV2Message> providerRequests = root.join(Reservation_.providerRequests); query.where(builder.equal(providerRequests.get(NsiV2Message_.id), providerRequestId)); return entityManager.createQuery(query).setLockMode(LockModeType.PESSIMISTIC_WRITE).getSingleResult(); }
@Override public <Y> ListJoin<X, Y> join(ListAttribute<? super X, Y> list) { // TODO Auto-generated method stub return null; }
@Override public <Y> ListJoin<X, Y> join(ListAttribute<? super X, Y> list, JoinType jt) { // TODO Auto-generated method stub return null; }
@Override public <X, Y> ListJoin<X, Y> joinList(String attributeName) { // TODO Auto-generated method stub return null; }
@Override public <X, Y> ListJoin<X, Y> joinList(String attributeName, JoinType jt) { // TODO Auto-generated method stub return null; }
@Override public <X, T, E extends T> ListJoin<X, E> treat(ListJoin<X, T> join, Class<E> type) { // TODO Auto-generated method stub return null; }
@Override public Slice<AssignedSoftwareModule> findAllOrderBySetAssignmentAndModuleNameAscModuleVersionAsc( final Pageable pageable, final Long orderByDistributionId, final String searchText, final Long typeId) { final List<AssignedSoftwareModule> resultList = new ArrayList<>(); final int pageSize = pageable.getPageSize(); final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); // get the assigned software modules final CriteriaQuery<JpaSoftwareModule> assignedQuery = cb.createQuery(JpaSoftwareModule.class); final Root<JpaSoftwareModule> assignedRoot = assignedQuery.from(JpaSoftwareModule.class); assignedQuery.distinct(true); final ListJoin<JpaSoftwareModule, JpaDistributionSet> assignedDsJoin = assignedRoot .join(JpaSoftwareModule_.assignedTo); // build the specifications and then to predicates necessary by the // given filters final Predicate[] specPredicate = specificationsToPredicate(buildSpecificationList(searchText, typeId), assignedRoot, assignedQuery, cb, cb.equal(assignedDsJoin.get(JpaDistributionSet_.id), orderByDistributionId)); // if we have some predicates then add it to the where clause of the // multi select assignedQuery.where(specPredicate); assignedQuery.orderBy(cb.asc(assignedRoot.get(JpaSoftwareModule_.name)), cb.asc(assignedRoot.get(JpaSoftwareModule_.version))); // don't page the assigned query on database, we need all assigned // software modules to filter // them out in the unassigned query final List<JpaSoftwareModule> assignedSoftwareModules = entityManager.createQuery(assignedQuery) .getResultList(); // map result if (pageable.getOffset() < assignedSoftwareModules.size()) { assignedSoftwareModules .subList(pageable.getOffset(), Math.min(assignedSoftwareModules.size(), pageable.getPageSize())) .forEach(sw -> resultList.add(new AssignedSoftwareModule(sw, true))); } if (assignedSoftwareModules.size() >= pageSize) { return new SliceImpl<>(resultList); } // get the unassigned software modules final CriteriaQuery<JpaSoftwareModule> unassignedQuery = cb.createQuery(JpaSoftwareModule.class); unassignedQuery.distinct(true); final Root<JpaSoftwareModule> unassignedRoot = unassignedQuery.from(JpaSoftwareModule.class); Predicate[] unassignedSpec; if (!assignedSoftwareModules.isEmpty()) { unassignedSpec = specificationsToPredicate(buildSpecificationList(searchText, typeId), unassignedRoot, unassignedQuery, cb, cb.not(unassignedRoot.get(JpaSoftwareModule_.id).in( assignedSoftwareModules.stream().map(SoftwareModule::getId).collect(Collectors.toList())))); } else { unassignedSpec = specificationsToPredicate(buildSpecificationList(searchText, typeId), unassignedRoot, unassignedQuery, cb); } unassignedQuery.where(unassignedSpec); unassignedQuery.orderBy(cb.asc(unassignedRoot.get(JpaSoftwareModule_.name)), cb.asc(unassignedRoot.get(JpaSoftwareModule_.version))); final List<JpaSoftwareModule> unassignedSoftwareModules = entityManager.createQuery(unassignedQuery) .setFirstResult(Math.max(0, pageable.getOffset() - assignedSoftwareModules.size())) .setMaxResults(pageSize).getResultList(); // map result unassignedSoftwareModules.forEach(sw -> resultList.add(new AssignedSoftwareModule(sw, false))); return new SliceImpl<>(resultList); }
@Override @SuppressWarnings("unchecked") public <X, T, E extends T> ListJoin<X, E> treat(ListJoin<X, T> join, Class<E> type) { // return ( (ListJoinImplementor) join ).treatAs( type ); throw new NotYetImplementedException( ); }
@Override public <Y> ListJoin<T, Y> join( ListAttribute<? super T, Y> arg0 ) { // TODO Auto-generated method stub return null; }
@Override public <Y> ListJoin<T, Y> join( ListAttribute<? super T, Y> arg0, JoinType arg1 ) { // TODO Auto-generated method stub return null; }
@Override public <X, Y> ListJoin<X, Y> joinList( String arg0 ) { // TODO Auto-generated method stub return null; }
@Override public <X, Y> ListJoin<X, Y> joinList( String arg0, JoinType arg1 ) { // TODO Auto-generated method stub return null; }
/** * Specification which joins all necessary tables to retrieve the dependency * between a target and a local file assignment through the assigned action * of the target. All actions are included, not only active actions. * * @param controllerId * the target to verify if the given artifact is currently * assigned or had been assigned * @param sha1Hash * of the local artifact to check wherever the target had ever * been assigned * @return a specification to use with spring JPA */ public static Specification<JpaAction> hasTargetAssignedArtifact(final String controllerId, final String sha1Hash) { return (actionRoot, query, criteriaBuilder) -> { final Join<JpaAction, JpaDistributionSet> dsJoin = actionRoot.join(JpaAction_.distributionSet); final SetJoin<JpaDistributionSet, JpaSoftwareModule> modulesJoin = dsJoin.join(JpaDistributionSet_.modules); final ListJoin<JpaSoftwareModule, JpaArtifact> artifactsJoin = modulesJoin .join(JpaSoftwareModule_.artifacts); return criteriaBuilder.and(criteriaBuilder.equal(artifactsJoin.get(JpaArtifact_.sha1Hash), sha1Hash), criteriaBuilder.equal(actionRoot.get(JpaAction_.target).get(JpaTarget_.controllerId), controllerId)); }; }
/** * Specification which joins all necessary tables to retrieve the dependency * between a target and a local file assignment through the assigned action * of the target. All actions are included, not only active actions. * * @param targetId * the target to verify if the given artifact is currently * assigned or had been assigned * @param sha1Hash * of the local artifact to check wherever the target had ever * been assigned * @return a specification to use with spring JPA */ public static Specification<JpaAction> hasTargetAssignedArtifact(final Long targetId, final String sha1Hash) { return (actionRoot, query, criteriaBuilder) -> { final Join<JpaAction, JpaDistributionSet> dsJoin = actionRoot.join(JpaAction_.distributionSet); final SetJoin<JpaDistributionSet, JpaSoftwareModule> modulesJoin = dsJoin.join(JpaDistributionSet_.modules); final ListJoin<JpaSoftwareModule, JpaArtifact> artifactsJoin = modulesJoin .join(JpaSoftwareModule_.artifacts); return criteriaBuilder.and(criteriaBuilder.equal(artifactsJoin.get(JpaArtifact_.sha1Hash), sha1Hash), criteriaBuilder.equal(actionRoot.get(JpaAction_.target).get(JpaTarget_.id), targetId)); }; }