diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java index ac61e96d1..66ea1af2d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java @@ -66,6 +66,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_; import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications; +import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.model.Action; @@ -310,7 +311,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont } private void throwExceptionIfTargetDoesNotExist(final String controllerId) { - if (!targetRepository.existsByControllerId(controllerId)) { + if (!targetRepository.exists(TargetSpecifications.hasControllerId(controllerId))) { throw new EntityNotFoundException(Target.class, controllerId); } } @@ -367,9 +368,9 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont @Override public void deleteExistingTarget(@NotEmpty final String controllerId) { - final Target target = targetRepository.findByControllerId(controllerId) + final Target target = targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); - targetRepository.deleteById(target.getId()); + targetRepository.deleteById(target.getId()); } @Override @@ -738,7 +739,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont throw new InvalidTargetAttributeException(); } - final JpaTarget target = (JpaTarget) targetRepository.findByControllerId(controllerId) + final JpaTarget target = (JpaTarget) targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); // get the modifiable attribute map @@ -884,7 +885,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont @Override public Optional getByControllerId(final String controllerId) { - return targetRepository.findByControllerId(controllerId); + return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)).map(Target.class::cast); } @Override diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java index e564b40e0..37fd8222a 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java @@ -55,6 +55,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; +import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.jpa.utils.TenantConfigHelper; @@ -289,8 +290,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl .distinct().collect(Collectors.toList()); final List existingTargetIds = Lists.partition(providedTargetIds, Constants.MAX_ENTRIES_IN_STATEMENT) - .stream().map(targetRepository::filterNonExistingControllerIds).flatMap(List::stream) - .collect(Collectors.toList()); + .stream().map(ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids))) + .flatMap(List::stream).map(JpaTarget::getControllerId).collect(Collectors.toList()); final List targetEntities = assignmentStrategy.findTargetsForAssignment(existingTargetIds, distributionSetEntity.getId()); @@ -701,7 +702,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl } private void throwExceptionIfTargetDoesNotExist(final String controllerId) { - if (!targetRepository.existsByControllerId(controllerId)) { + if (!targetRepository.exists(TargetSpecifications.hasControllerId(controllerId))) { throw new EntityNotFoundException(Target.class, controllerId); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java index 721ea1fb9..5bab6afe5 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutGroupManagement.java @@ -37,6 +37,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_; import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup; import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup_; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; +import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus; @@ -232,9 +233,11 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement { // in case of status ready the action has not been created yet and // the relation information between target and rollout-group is // stored in the #TargetRolloutGroup. - return targetRepository.findByRolloutTargetGroupRolloutGroupId(rolloutGroupId, page); + return JpaTargetManagement.convertPage( + targetRepository.findAll(TargetSpecifications.isInRolloutGroup(rolloutGroupId), page), page); } - return targetRepository.findByActionsRolloutGroupId(rolloutGroupId, page); + return JpaTargetManagement.convertPage( + targetRepository.findAll(TargetSpecifications.isInActionRolloutGroup(rolloutGroupId), page), page); } private static boolean isRolloutStatusReady(final RolloutGroup rolloutGroup) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java index c09da659c..178cf9d72 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetManagement.java @@ -144,11 +144,11 @@ public class JpaTargetManagement implements TargetManagement { @Override public Optional getByControllerID(final String controllerId) { - return targetRepository.findByControllerId(controllerId); + return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)).map(Target.class::cast); } private JpaTarget getByControllerIdAndThrowIfNotFound(final String controllerId) { - return targetRepository.findByControllerId(controllerId).map(JpaTarget.class::cast) + return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); } @@ -342,7 +342,7 @@ public class JpaTargetManagement implements TargetManagement { @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public void delete(final Collection targetIDs) { - final List targets = targetRepository.findAllById(targetIDs); + final List targets = targetRepository.findAll(TargetSpecifications.hasIdIn(targetIDs)); if (targets.size() < targetIDs.size()) { throw new EntityNotFoundException(Target.class, targetIDs, @@ -373,7 +373,9 @@ public class JpaTargetManagement implements TargetManagement { public Page findByAssignedDistributionSet(final Pageable pageReq, final long distributionSetID) { throwEntityNotFoundIfDsDoesNotExist(distributionSetID); - return targetRepository.findByAssignedDistributionSetId(pageReq, distributionSetID); + return convertPage( + targetRepository.findAll(TargetSpecifications.hasAssignedDistributionSet(distributionSetID), pageReq), + pageReq); } @Override @@ -399,7 +401,7 @@ public class JpaTargetManagement implements TargetManagement { } } - private static Page convertPage(final Page findAll, final Pageable pageable) { + public static Page convertPage(final Page findAll, final Pageable pageable) { return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements()); } @@ -410,7 +412,9 @@ public class JpaTargetManagement implements TargetManagement { @Override public Page findByInstalledDistributionSet(final Pageable pageReq, final long distributionSetID) { throwEntityNotFoundIfDsDoesNotExist(distributionSetID); - return targetRepository.findByInstalledDistributionSetId(pageReq, distributionSetID); + return convertPage( + targetRepository.findAll(TargetSpecifications.hasInstalledDistributionSet(distributionSetID), pageReq), + pageReq); } @Override @@ -432,7 +436,8 @@ public class JpaTargetManagement implements TargetManagement { @Override public Page findByUpdateStatus(final Pageable pageable, final TargetUpdateStatus status) { - return targetRepository.findByUpdateStatus(pageable, status); + return convertPage(targetRepository.findAll(TargetSpecifications.hasTargetUpdateStatus(status), pageable), + pageable); } @Override @@ -515,8 +520,8 @@ public class JpaTargetManagement implements TargetManagement { allTargets.stream().map(Target::getControllerId).collect(Collectors.toList())); } - final List alreadyAssignedTargets = targetRepository.findByTagNameAndControllerIdIn(tagName, - controllerIds); + final List alreadyAssignedTargets = targetRepository.findAll( + TargetSpecifications.hasTagName(tagName).and(TargetSpecifications.hasControllerIdIn(controllerIds))); // all are already assigned -> unassign if (alreadyAssignedTargets.size() == allTargets.size()) { @@ -633,21 +638,21 @@ public class JpaTargetManagement implements TargetManagement { public long countByAssignedDistributionSet(final long distId) { throwEntityNotFoundIfDsDoesNotExist(distId); - return targetRepository.countByAssignedDistributionSetId(distId); + return targetRepository.count(TargetSpecifications.hasAssignedDistributionSet(distId)); } @Override public long countByInstalledDistributionSet(final long distId) { throwEntityNotFoundIfDsDoesNotExist(distId); - return targetRepository.countByInstalledDistributionSetId(distId); + return targetRepository.count(TargetSpecifications.hasInstalledDistributionSet(distId)); } @Override public boolean existsByInstalledOrAssignedDistributionSet(final long distId) { throwEntityNotFoundIfDsDoesNotExist(distId); - return targetRepository.existsByInstalledOrAssignedDistributionSet(distId); + return targetRepository.exists(TargetSpecifications.hasInstalledOrAssignedDistributionSet(distId)); } @Override @@ -733,7 +738,7 @@ public class JpaTargetManagement implements TargetManagement { public Page findByTag(final Pageable pageable, final long tagId) { throwEntityNotFoundExceptionIfTagDoesNotExist(tagId); - return convertPage(targetRepository.findByTag(pageable, tagId), pageable); + return convertPage(targetRepository.findAll(TargetSpecifications.hasTag(tagId), pageable), pageable); } private void throwEntityNotFoundExceptionIfTagDoesNotExist(final Long tagId) { @@ -782,7 +787,7 @@ public class JpaTargetManagement implements TargetManagement { @Override public List get(final Collection ids) { - return Collections.unmodifiableList(targetRepository.findAllById(ids)); + return Collections.unmodifiableList(targetRepository.findAll(TargetSpecifications.hasIdIn(ids))); } @Override @@ -824,12 +829,13 @@ public class JpaTargetManagement implements TargetManagement { @Override public boolean existsByControllerId(final String controllerId) { - return targetRepository.existsByControllerId(controllerId); + return targetRepository.exists(TargetSpecifications.hasControllerId(controllerId)); } @Override public Page findByControllerAttributesRequested(final Pageable pageReq) { - return targetRepository.findByRequestControllerAttributesIsTrue(pageReq); + return convertPage(targetRepository.findAll(TargetSpecifications.hasRequestControllerAttributesTrue(), pageReq), + pageReq); } } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTagManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTagManagement.java index 368e7833d..67dd3eb83 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTagManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetTagManagement.java @@ -25,6 +25,7 @@ import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag; import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility; import org.eclipse.hawkbit.repository.jpa.specifications.TagSpecification; +import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetTag; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; @@ -154,7 +155,7 @@ public class JpaTargetTagManagement implements TargetTagManagement { @Override public Page findByTarget(final Pageable pageable, final String controllerId) { - if (!targetRepository.existsByControllerId(controllerId)) { + if (!targetRepository.exists(TargetSpecifications.hasControllerId(controllerId))) { throw new EntityNotFoundException(Target.class, controllerId); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OfflineDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OfflineDsAssignmentStrategy.java index ee3042df1..9130b713f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OfflineDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OfflineDsAssignmentStrategy.java @@ -62,7 +62,7 @@ public class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { public List findTargetsForAssignment(final List controllerIDs, final long setId) { final Function, List> mapper; if (isMultiAssignmentsEnabled()) { - mapper = targetRepository::findAllByControllerId; + mapper = ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids)); } else { mapper = ids -> targetRepository.findAll(SpecificationsBuilder.combineWithAnd( Arrays.asList(TargetSpecifications.hasControllerIdAndAssignedDistributionSetIdNot(ids, setId), diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OnlineDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OnlineDsAssignmentStrategy.java index 7c67ab117..1d2d14079 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OnlineDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OnlineDsAssignmentStrategy.java @@ -32,7 +32,6 @@ import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult; -import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetWithActionType; import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder; @@ -98,7 +97,7 @@ public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { List findTargetsForAssignment(final List controllerIDs, final long setId) { final Function, List> mapper; if (isMultiAssignmentsEnabled()) { - mapper = targetRepository::findAllByControllerId; + mapper = ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids)); } else { mapper = ids -> targetRepository .findAll(TargetSpecifications.hasControllerIdAndAssignedDistributionSetIdNot(ids, setId)); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetRepository.java index 474920f76..0746d509f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/TargetRepository.java @@ -10,24 +10,27 @@ package org.eclipse.hawkbit.repository.jpa; import java.util.Collection; import java.util.List; -import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; import javax.persistence.EntityManager; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; -import org.eclipse.hawkbit.repository.model.DistributionSet; -import org.eclipse.hawkbit.repository.model.Tag; +import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import org.springframework.lang.NonNull; import org.springframework.transaction.annotation.Transactional; /** @@ -80,28 +83,6 @@ public interface TargetRepository extends BaseEntityRepository, @Param("set") JpaDistributionSet set, @Param("lastModifiedAt") Long modifiedAt, @Param("lastModifiedBy") String modifiedBy, @Param("targets") Collection targets); - /** - * Loads {@link Target} by given ID. - * - * @param controllerID - * to search for - * @return found {@link Target} or null if not found. - */ - Optional findByControllerId(String controllerID); - - @Query("SELECT t.controllerAttributes FROM JpaTarget t WHERE t.controllerId=:controllerId") - Map getControllerAttributes(@Param("controllerId") String controllerId); - - /** - * Checks if target with given id exists. - * - * @param controllerId - * to check - * @return true if target with given id exists - */ - @Query("SELECT CASE WHEN COUNT(t)>0 THEN 'true' ELSE 'false' END FROM JpaTarget t WHERE t.controllerId=:controllerId") - boolean existsByControllerId(@Param("controllerId") String controllerId); - /** * Deletes the {@link Target}s with the given target IDs. * @@ -114,165 +95,116 @@ public interface TargetRepository extends BaseEntityRepository, @Query("DELETE FROM JpaTarget t WHERE t.id IN ?1") void deleteByIdIn(Collection targetIDs); - /** - * Finds {@link Target}s by assigned {@link Tag}. - * - * @param page - * pages query and sorting information - * - * @param tagId - * to be found - * @return page of found targets - */ - @Query(value = "SELECT DISTINCT t FROM JpaTarget t JOIN t.tags tt WHERE tt.id = :tag") - Page findByTag(Pageable page, @Param("tag") Long tagId); - - /** - * Finds all {@link Target}s based on given {@link Target#getControllerId()} - * list and assigned {@link Tag#getName()}. - * - * @param tag - * to search for - * @param controllerIds - * to search for - * @return {@link List} of found {@link Target}s. - */ - @Query(value = "SELECT DISTINCT t from JpaTarget t JOIN t.tags tt WHERE tt.name = :tagname AND t.controllerId IN :targets") - List findByTagNameAndControllerIdIn(@Param("tagname") String tag, - @Param("targets") Collection controllerIds); - - /** - * Used by UI to filter based on selected status. - * - * @param pageable - * for page configuration - * @param status - * to filter for - * - * @return found targets - */ - Page findByUpdateStatus(Pageable pageable, TargetUpdateStatus status); - - /** - * retrieves the {@link Target}s which has the {@link DistributionSet} - * installed with the given ID. - * - * @param pageable - * parameter - * @param setID - * the ID of the {@link DistributionSet} - * @return the found {@link Target}s - */ - Page findByInstalledDistributionSetId(Pageable pageable, Long setID); - - /** - * Finds all targets that have defined {@link DistributionSet} assigned. - * - * @param pageable - * for page configuration - * @param setID - * is the ID of the {@link DistributionSet} to filter for. - * - * @return page of found targets - */ - Page findByAssignedDistributionSetId(Pageable pageable, Long setID); - - /** - * retrieves {@link Target}s where - * {@link JpaTarget#isRequestControllerAttributes()}. - * - * @param pageReq - * page parameter - * - * @return the found {@link Target}s - * - */ - Page findByRequestControllerAttributesIsTrue(Pageable pageable); - - /** - * Counts number of targets with given distribution set Id. - * - * @param distId - * to search for - * - * @return number of found {@link Target}s. - */ - Long countByAssignedDistributionSetId(Long distId); - - /** - * Counts number of targets with given distribution set Id. - * - * @param distId - * to search for - * @return number of found {@link Target}s. - */ - Long countByInstalledDistributionSetId(Long distId); - - /** - * Checks if there is already a {@link Target} that has the given distribution set Id assigned or installed. - * - * @param distId - * to check - * @return true if a {@link Target} exists. - */ - @Query("SELECT CASE WHEN COUNT(t)>0 THEN 'true' ELSE 'false' END FROM JpaTarget t WHERE t.installedDistributionSet.id=:distId OR t.assignedDistributionSet.id=:distId") - boolean existsByInstalledOrAssignedDistributionSet(@Param("distId") Long distId); - /** * Finds all {@link Target}s in the repository. * - * @return {@link List} of {@link Target}s + * Calls version with (empty) spec to allow injecting further specs * - * @see org.springframework.data.repository.CrudRepository#findAll() + * @return {@link List} of {@link Target}s */ @Override - List findAll(); + @NonNull + default List findAll() { + return this.findAll(Specification.where(null)); + } + /** + * Finds all {@link Target}s in the repository sorted. + * + * Calls version with (empty) spec to allow injecting further specs + * + * @param sort instructions to sort result by + * @return {@link List} of {@link Target}s + */ @Override - // Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477 - @Query("SELECT t FROM JpaTarget t WHERE t.id IN ?1") - List findAllById(Iterable ids); + @NonNull + default Iterable findAll(@NonNull Sort sort) { + return this.findAll(Specification.where(null), sort); + } /** - * Finds all targets for the given list of controller IDs. - * - * @param controllerIds - * The controller IDs to look for. - * - * @return The list of matching targets. + * Finds a page of {@link Target}s in the repository. + * + * Calls version with (empty) spec to allow injecting further specs + * + * @param pageable paging context + * @return {@link List} of {@link Target}s */ - @Query("SELECT t FROM JpaTarget t WHERE t.controllerId IN ?1") - List findAllByControllerId(Iterable controllerIds); + @Override + @NonNull + default Page findAll(@NonNull Pageable pageable) { + return this.findAll(Specification.where(null), pageable); + } /** - * - * Finds all targets of a rollout group. - * - * @param rolloutGroupId - * the ID of the rollout group - * @param page - * the page request parameter - * @return a page of all targets related to a rollout group + * Finds {@link Target}s in the repository matching a list of ids. + * + * Calls version based on spec to allow injecting further specs + * + * @param ids ids to filter for + * @return {@link List} of {@link Target}s */ - Page findByRolloutTargetGroupRolloutGroupId(Long rolloutGroupId, Pageable page); + @Override + @NonNull + default List findAllById(Iterable ids) { + final List collectedIds = StreamSupport.stream(ids.spliterator(), true).collect(Collectors.toList()); + return this.findAll(Specification.where(TargetSpecifications.hasIdIn(collectedIds))); + } /** - * Finds all targets related to a target rollout group stored for a specific - * rollout. - * - * @param rolloutGroupId - * the rollout group the targets should belong to - * @param page - * the page request parameter - * @return a page of all targets related to a rollout group + * Finds {@link Target} in the repository matching an id. + * + * Calls version based on spec to allow injecting further specs + * + * @param id id to filter for + * @return {@link Optional} of {@link Target} */ - Page findByActionsRolloutGroupId(Long rolloutGroupId, Pageable page); + @Override + @NonNull + default Optional findById(@NonNull Long id) { + return this.findOne(Specification.where(TargetSpecifications.hasId(id))); + } + + /** + * Checks whether {@link Target} in the repository matching an id exists or not. + * + * Calls version based on spec to allow injecting further specs + * + * @param id id to check for + * @return true if target with id exists + */ + @Override + default boolean existsById(@NonNull Long id) { + return this.exists(TargetSpecifications.hasId(id)); + } + + /** + * Checks whether {@link Target} in the repository matching a spec exists or not. + * + * @param spec to check for existence + * @return true if target with id exists + */ + default boolean exists(@NonNull Specification spec) { + return this.count(spec) > 0; + } + + /** + * Count number of {@link Target}s in the repository. + * + * Calls version with an empty spec to allow injecting further specs + * + * @return number of targets in the repository + */ + @Override + default long count() { + return this.count(Specification.where(null)); + } /** * Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety * reasons (this is a "delete everything" query after all) we add the tenant - * manually to query even if this will by done by {@link EntityManager} - * anyhow. The DB should take care of optimizing this away. + * manually to query even if this will by done by {@link EntityManager} anyhow. + * The DB should take care of optimizing this away. * * @param tenant * to delete data from @@ -281,14 +213,4 @@ public interface TargetRepository extends BaseEntityRepository, @Transactional @Query("DELETE FROM JpaTarget t WHERE t.tenant = :tenant") void deleteByTenant(@Param("tenant") String tenant); - - /** - * Filters a given list of controllerIds and returns only the existing IDs. - * - * @param controllerIds - * The IDs to be filtered - * @return only the existing controllerIds - */ - @Query("SELECT t.controllerId FROM JpaTarget t WHERE t.controllerId IN ?1") - List filterNonExistingControllerIds(Iterable controllerIds); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java index f7f94682f..c0ebed849 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/specifications/TargetSpecifications.java @@ -68,6 +68,64 @@ public final class TargetSpecifications { }; } + /** + * {@link Specification} for retrieving {@link Target}s by controllerId + * + * @param controllerID + * to search for + * + * @return the {@link Target} {@link Specification} + */ + public static Specification hasControllerId(final String controllerID) { + return (targetRoot, query, cb) -> cb.equal(targetRoot.get(JpaTarget_.controllerId), controllerID); + } + + /** + * {@link Specification} for retrieving {@link Target}s by controllerId + * + * @param controllerIDs + * to search for + * + * @return the {@link Target} {@link Specification} + */ + public static Specification hasControllerIdIn(final Collection controllerIDs) { + return (targetRoot, query, cb) -> targetRoot.get(JpaTarget_.controllerId).in(controllerIDs); + } + + /** + * {@link Specification} for retrieving {@link Target}s by controllerId + * + * @param id + * to search for + * + * @return the {@link Target} {@link Specification} + */ + public static Specification hasId(final Long id) { + return (targetRoot, query, cb) -> cb.equal(targetRoot.get(JpaTarget_.id), id); + } + + /** + * {@link Specification} for retrieving {@link Target}s by controllerId + * + * @param ids + * to search for + * + * @return the {@link Target} {@link Specification} + */ + public static Specification hasIdIn(final Collection ids) { + return (targetRoot, query, cb) -> targetRoot.get(JpaTarget_.id).in(ids); + } + + /** + * {@link Specification} for retrieving {@link Target}s that have the request + * controller attributes flag set + * + * @return the {@link Target} {@link Specification} + */ + public static Specification hasRequestControllerAttributesTrue() { + return (targetRoot, query, cb) -> cb.equal(targetRoot.get(JpaTarget_.requestControllerAttributes), true); + } + /** * {@link Specification} for retrieving {@link JpaTarget}s including * {@link JpaTarget#getAssignedDistributionSet()}. @@ -87,7 +145,7 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s by "equal to given + * {@link Specification} for retrieving {@link Target}s by "equal to any given * {@link TargetUpdateStatus}". * * @param updateStatus @@ -100,8 +158,21 @@ public final class TargetSpecifications { } /** - * {@link Specification} for retrieving {@link Target}s by "not equal to - * given {@link TargetUpdateStatus}". + * {@link Specification} for retrieving {@link Target}s by "equal to given + * {@link TargetUpdateStatus}". + * + * @param updateStatus + * to be filtered on + * + * @return the {@link Target} {@link Specification} + */ + public static Specification hasTargetUpdateStatus(final TargetUpdateStatus updateStatus) { + return (targetRoot, query, cb) -> cb.equal(targetRoot.get(JpaTarget_.updateStatus), updateStatus); + } + + /** + * {@link Specification} for retrieving {@link Target}s by "not equal to given + * {@link TargetUpdateStatus}". * * @param updateStatus * to be filtered on @@ -189,11 +260,7 @@ public final class TargetSpecifications { * @return the {@link Target} {@link Specification} */ public static Specification hasInstalledOrAssignedDistributionSet(@NotNull final Long distributionId) { - return (targetRoot, query, cb) -> cb.or( - cb.equal(targetRoot.get(JpaTarget_.installedDistributionSet).get(JpaDistributionSet_.id), - distributionId), - cb.equal(targetRoot. get(JpaTarget_.assignedDistributionSet) - .get(JpaDistributionSet_.id), distributionId)); + return hasInstalledDistributionSet(distributionId).or(hasAssignedDistributionSet(distributionId)); } /** @@ -214,6 +281,22 @@ public final class TargetSpecifications { cb.isNull(targetRoot. get(JpaTarget_.assignedDistributionSet)))); } + /** + * {@link Specification} for retrieving {@link Target}s based on a + * {@link TargetTag} name. + * + * @param tagName + * to search for + * + * @return the {@link Target} {@link Specification} + */ + public static Specification hasTagName(final String tagName) { + return (targetRoot, query, cb) -> { + final SetJoin join = targetRoot.join(JpaTarget_.tags); + return cb.equal(join.get(JpaTargetTag_.name), tagName); + }; + } + /** * {@link Specification} for retrieving {@link Target}s by "has no tag * names"or "has at least on of the given tag names". @@ -289,6 +372,37 @@ public final class TargetSpecifications { }; } + /** + * {@link Specification} for retrieving {@link Target}s that are in a given + * {@link RolloutGroup} + * + * @param group + * the {@link RolloutGroup} + * @return the {@link Target} {@link Specification} + */ + public static Specification isInRolloutGroup(final Long group) { + return (targetRoot, query, cb) -> { + final ListJoin targetGroupJoin = targetRoot + .join(JpaTarget_.rolloutTargetGroup); + return cb.equal(targetGroupJoin.get(RolloutTargetGroup_.rolloutGroup).get(JpaRolloutGroup_.id), group); + }; + } + + /** + * {@link Specification} for retrieving {@link Target}s that are in an action + * for a given {@link RolloutGroup} + * + * @param group + * the {@link RolloutGroup} + * @return the {@link Target} {@link Specification} + */ + public static Specification isInActionRolloutGroup(final Long group) { + return (targetRoot, query, cb) -> { + final ListJoin targetActionJoin = targetRoot.join(JpaTarget_.actions); + return cb.equal(targetActionJoin.get(JpaAction_.rolloutGroup).get(JpaRolloutGroup_.id), group); + }; + } + /** * {@link Specification} for retrieving {@link Target}s that are not in the * given {@link RolloutGroup}s @@ -347,7 +461,7 @@ public final class TargetSpecifications { * {@link Specification} for retrieving {@link Target}s by tag. * * @param tagId - * the ID of the distribution set which must be assigned + * the ID of the tag that should be to be assigned to target * @return the {@link Target} {@link Specification} */ public static Specification hasTag(final Long tagId) {