Optimize UI queries (#1234)

* first iteration of query optimization for target and distribution set
* fixed type distribution set filter
* adapted all ui dataproviders to use repository count
* adapted test to not check target attributes within search query
* unified search behaviuor for ds and sm
* removed unneccessary count queries for some mgmt calls
* removed unneccessary type id proprty from ProxyDistributionSetInfo to minimize lazy fetches
* refactored mgmt classes
* removed duplication of name version filter
* fixed copy rollout compatibility check
* cleaned-up management left overs
* added index to rollouts table on tenant/status queries

Signed-off-by: Bogdan Bondar <Bogdan.Bondar@bosch.io>
This commit is contained in:
Bondar Bogdan
2022-03-23 09:08:56 +01:00
committed by GitHub
parent 681df6c1f1
commit c9eafbbc26
74 changed files with 1444 additions and 1617 deletions

View File

@@ -220,6 +220,13 @@ public class JpaArtifactManagement implements ArtifactManagement {
return localArtifactRepository.findBySoftwareModuleId(pageReq, swId);
}
@Override
public long countBySoftwareModule(final long swId) {
throwExceptionIfSoftwareModuleDoesNotExist(swId);
return localArtifactRepository.countBySoftwareModuleId(swId);
}
private void throwExceptionIfSoftwareModuleDoesNotExist(final Long swId) {
if (!softwareModuleRepository.existsById(swId)) {
throw new EntityNotFoundException(SoftwareModule.class, swId);

View File

@@ -12,6 +12,7 @@ import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationPrope
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
@@ -273,7 +274,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
if (target.getTargetType() != null) {
// we assume that list of assigned DS is less than MAX_ENTRIES_IN_STATEMENT
// we assume that list of assigned DS is less than
// MAX_ENTRIES_IN_STATEMENT
final Set<DistributionSetType> incompatibleDistSetTypes = distributionSetManagement.get(distSetIds).stream()
.map(DistributionSet::getType).collect(Collectors.toSet());
incompatibleDistSetTypes.removeAll(target.getTargetType().getCompatibleDistributionSetTypes());
@@ -309,8 +311,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
/**
* method assigns the {@link DistributionSet} to all {@link Target}s by their
* IDs with a specific {@link ActionType} and {@code forcetime}.
* method assigns the {@link DistributionSet} to all {@link Target}s by
* their IDs with a specific {@link ActionType} and {@code forcetime}.
*
*
* In case the update was executed offline (i.e. not managed by hawkBit) the
@@ -318,8 +320,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
* A. it ignores targets completely that are in
* {@link TargetUpdateStatus#PENDING}.<br/>
* B. it created completed actions.<br/>
* C. sets both installed and assigned DS on the target and switches the status
* to {@link TargetUpdateStatus#IN_SYNC} <br/>
* C. sets both installed and assigned DS on the target and switches the
* status to {@link TargetUpdateStatus#IN_SYNC} <br/>
* D. does not send a {@link TargetAssignDistributionSetEvent}.<br/>
*
* @param initiatedBy
@@ -404,9 +406,9 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
/**
* split tIDs length into max entries in-statement because many database have
* constraint of max entries in in-statements e.g. Oracle with maximum 1000
* elements, so we need to split the entries here and execute multiple
* split tIDs length into max entries in-statement because many database
* have constraint of max entries in in-statements e.g. Oracle with maximum
* 1000 elements, so we need to split the entries here and execute multiple
* statements
*/
private static List<List<Long>> getTargetEntitiesAsChunks(final List<JpaTarget> targetEntities) {
@@ -579,10 +581,10 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
return 0L;
}
final List<Action> targetAssignments = rolloutGroupActions.getContent().stream()
.map(action -> (JpaAction) action).map(this::closeActionIfSetWasAlreadyAssigned)
.filter(Objects::nonNull).map(this::startScheduledActionIfNoCancelationHasToBeHandledFirst)
.filter(Objects::nonNull).collect(Collectors.toList());
final List<Action> targetAssignments = rolloutGroupActions.getContent().stream().map(JpaAction.class::cast)
.map(this::closeActionIfSetWasAlreadyAssigned).filter(Objects::nonNull)
.map(this::startScheduledActionIfNoCancelationHasToBeHandledFirst).filter(Objects::nonNull)
.collect(Collectors.toList());
if (!targetAssignments.isEmpty()) {
onlineDsAssignmentStrategy.sendDeploymentEvents(distributionSetId, targetAssignments);
@@ -696,20 +698,15 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
final Pageable pageable) {
throwExceptionIfTargetDoesNotExist(controllerId);
final Specification<JpaAction> byTargetSpec = createSpecificationFor(controllerId, rsqlParam);
final Page<JpaAction> actions = actionRepository.findAll(byTargetSpec, pageable);
return convertAcPage(actions, pageable);
final List<Specification<JpaAction>> specList = Arrays.asList(
RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer, database),
byControllerIdSpec(controllerId));
return JpaManagementHelper.findAllWithCountBySpec(actionRepository, pageable, specList);
}
private Specification<JpaAction> createSpecificationFor(final String controllerId, final String rsqlParam) {
final Specification<JpaAction> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class,
virtualPropertyReplacer, database);
return (root, query, cb) -> cb.and(spec.toPredicate(root, query, cb),
cb.equal(root.get(JpaAction_.target).get(JpaTarget_.controllerId), controllerId));
}
private static Page<Action> convertAcPage(final Page<JpaAction> findAll, final Pageable pageable) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements());
private Specification<JpaAction> byControllerIdSpec(final String controllerId) {
return (root, query, cb) -> cb.equal(root.get(JpaAction_.target).get(JpaTarget_.controllerId), controllerId);
}
@Override
@@ -744,7 +741,11 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override
public long countActionsByTarget(final String rsqlParam, final String controllerId) {
throwExceptionIfTargetDoesNotExist(controllerId);
return actionRepository.count(createSpecificationFor(controllerId, rsqlParam));
final List<Specification<JpaAction>> specList = Arrays.asList(
RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer, database),
byControllerIdSpec(controllerId));
return JpaManagementHelper.countBySpec(actionRepository, specList);
}
private void throwExceptionIfTargetDoesNotExist(final String controllerId) {
@@ -776,24 +777,28 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override
public Page<ActionStatus> findActionStatusByAction(final Pageable pageReq, final long actionId) {
verifyActionExists(actionId);
return actionStatusRepository.findByActionId(pageReq, actionId);
}
private void verifyActionExists(final long actionId) {
if (!actionRepository.existsById(actionId)) {
throw new EntityNotFoundException(Action.class, actionId);
}
}
return actionStatusRepository.findByActionId(pageReq, actionId);
@Override
public long countActionStatusByAction(final long actionId) {
verifyActionExists(actionId);
return actionStatusRepository.countByActionId(actionId);
}
@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);
@@ -803,16 +808,25 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
final List<String> result = new ArrayList<>(entityManager.createQuery(selMsgQuery)
.setFirstResult((int) pageable.getOffset()).setMaxResults(pageable.getPageSize()).getResultList());
return new PageImpl<>(result, pageable, totalCount);
return new PageImpl<>(result, pageable, result.size());
}
@Override
public long countMessagesByActionStatusId(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));
return entityManager.createQuery(countMsgQuery).getSingleResult();
}
@Override
public Page<ActionStatus> findActionStatusAll(final Pageable pageable) {
return convertAcSPage(actionStatusRepository.findAll(pageable), pageable);
}
private static Page<ActionStatus> convertAcSPage(final Page<JpaActionStatus> findAll, final Pageable pageable) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements());
return JpaManagementHelper.findAllWithCountBySpec(actionStatusRepository, pageable, null);
}
@Override
@@ -844,7 +858,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override
public Slice<Action> findActionsAll(final Pageable pageable) {
return convertAcPage(actionRepository.findAll(pageable), pageable);
return JpaManagementHelper.findAllWithoutCountBySpec(actionRepository, pageable, null);
}
@Override
@@ -866,10 +880,10 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
return 0;
}
/*
* We use a native query here because Spring JPA does not support to specify a
* LIMIT clause on a DELETE statement. However, for this specific use case
* (action cleanup), we must specify a row limit to reduce the overall load on
* the database.
* We use a native query here because Spring JPA does not support to
* specify a LIMIT clause on a DELETE statement. However, for this
* specific use case (action cleanup), we must specify a row limit to
* reduce the overall load on the database.
*/
final int statusCount = status.size();

View File

@@ -8,7 +8,6 @@
*/
package org.eclipse.hawkbit.repository.jpa;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -17,12 +16,14 @@ import java.util.Optional;
import java.util.stream.Collectors;
import javax.persistence.EntityManager;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.repository.DistributionSetFields;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetMetadataFields;
import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
import org.eclipse.hawkbit.repository.QuotaManagement;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.builder.DistributionSetCreate;
@@ -50,7 +51,6 @@ import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder;
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSetTagAssignmentResult;
@@ -62,9 +62,9 @@ import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff;
@@ -148,7 +148,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Override
public Optional<DistributionSet> getWithDetails(final long distid) {
return distributionSetRepository.findOne(DistributionSetSpecification.byId(distid))
.map(d -> (DistributionSet) d);
.map(DistributionSet.class::cast);
}
@Override
@@ -337,101 +337,59 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
}
@Override
public Page<DistributionSet> findByDistributionSetFilter(final Pageable pageable,
public Slice<DistributionSet> findByDistributionSetFilter(final Pageable pageable,
final DistributionSetFilter distributionSetFilter) {
final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications(
distributionSetFilter);
return convertDsPage(findByCriteriaAPI(pageable, specList), pageable);
return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageable, specList);
}
private static Page<DistributionSet> convertDsPage(final Page<JpaDistributionSet> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
private static Slice<DistributionSet> convertDsPage(final Slice<JpaDistributionSet> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0);
}
/**
*
* @param distributionSetFilter
* had details of filters to be applied
* @return a single DistributionSet which is either installed or assigned to
* a specific target or {@code null}.
*/
private Optional<JpaDistributionSet> findDistributionSetsByFiltersAndInstalledOrAssignedTarget(
final DistributionSetFilter distributionSetFilter) {
@Override
public long countByDistributionSetFilter(@NotNull final DistributionSetFilter distributionSetFilter) {
final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications(
distributionSetFilter);
if (CollectionUtils.isEmpty(specList)) {
return Optional.empty();
}
return distributionSetRepository.findOne(SpecificationsBuilder.combineWithAnd(specList));
return JpaManagementHelper.countBySpec(distributionSetRepository, specList);
}
@Override
public Page<DistributionSet> findByCompleted(final Pageable pageReq, final Boolean complete) {
public Slice<DistributionSet> findByCompleted(final Pageable pageReq, final Boolean complete) {
return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageReq,
buildSpecsByComplete(complete));
}
List<Specification<JpaDistributionSet>> specList;
if (complete != null) {
specList = Arrays.asList(DistributionSetSpecification.isDeleted(false),
DistributionSetSpecification.isCompleted(complete));
} else {
specList = Collections.singletonList(DistributionSetSpecification.isDeleted(false));
}
return convertDsPage(findByCriteriaAPI(pageReq, specList), pageReq);
private List<Specification<JpaDistributionSet>> buildSpecsByComplete(final Boolean complete) {
return complete != null
? Arrays.asList(DistributionSetSpecification.isDeleted(false),
DistributionSetSpecification.isCompleted(complete))
: Collections.singletonList(DistributionSetSpecification.isDeleted(false));
}
@Override
public Page<DistributionSet> findByFilterAndAssignedInstalledDsOrderedByLinkTarget(final Pageable pageable,
final DistributionSetFilterBuilder distributionSetFilterBuilder, final String assignedOrInstalled) {
public long countByCompleted(final Boolean complete) {
return JpaManagementHelper.countBySpec(distributionSetRepository, buildSpecsByComplete(complete));
}
final DistributionSetFilter filterWithInstalledTargets = distributionSetFilterBuilder
.setInstalledTargetId(assignedOrInstalled).setAssignedTargetId(null).build();
final Optional<JpaDistributionSet> installedDS = findDistributionSetsByFiltersAndInstalledOrAssignedTarget(
filterWithInstalledTargets);
@Override
public Slice<DistributionSet> findByDistributionSetFilterOrderByLinkedTarget(final Pageable pageable,
final DistributionSetFilter distributionSetFilter, final String assignedOrInstalled) {
final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications(
distributionSetFilter);
specList.add(DistributionSetSpecification.orderedByLinkedTarget(assignedOrInstalled));
final DistributionSetFilter filterWithAssignedTargets = distributionSetFilterBuilder.setInstalledTargetId(null)
.setAssignedTargetId(assignedOrInstalled).build();
final Optional<JpaDistributionSet> assignedDS = findDistributionSetsByFiltersAndInstalledOrAssignedTarget(
filterWithAssignedTargets);
// remove default sort from pageable to not overwrite sorted spec
final OffsetBasedPageRequest unsortedPage = new OffsetBasedPageRequest(pageable.getOffset(),
pageable.getPageSize(), Sort.unsorted());
final DistributionSetFilter dsFilterWithNoTargetLinked = distributionSetFilterBuilder.setInstalledTargetId(null)
.setAssignedTargetId(null).build();
// first fine the distribution sets filtered by the given filter
// parameters
final Page<DistributionSet> findDistributionSetsByFilters = findByDistributionSetFilter(pageable,
dsFilterWithNoTargetLinked);
final List<DistributionSet> resultSet = new ArrayList<>(findDistributionSetsByFilters.getContent());
int orderIndex = 0;
if (installedDS.isPresent()) {
final boolean remove = resultSet.remove(installedDS.get());
if (!remove) {
resultSet.remove(resultSet.size() - 1);
}
resultSet.add(orderIndex, installedDS.get());
orderIndex++;
}
if (assignedDS.isPresent() && !assignedDS.equals(installedDS)) {
final boolean remove = resultSet.remove(assignedDS.get());
if (!remove) {
resultSet.remove(resultSet.size() - 1);
}
resultSet.add(orderIndex, assignedDS.get());
}
return new PageImpl<>(resultSet, pageable, findDistributionSetsByFilters.getTotalElements());
return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, unsortedPage, specList);
}
@Override
public Optional<DistributionSet> getByNameAndVersion(final String distributionName, final String version) {
final Specification<JpaDistributionSet> spec = DistributionSetSpecification
.equalsNameAndVersionIgnoreCase(distributionName, version);
return distributionSetRepository.findOne(spec).map(d -> (DistributionSet) d);
return distributionSetRepository.findOne(spec).map(DistributionSet.class::cast);
}
@@ -453,7 +411,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
assertMetaDataQuota(dsId, md.size());
final JpaDistributionSet set = touch(dsId);
final JpaDistributionSet set = JpaManagementHelper.touch(entityManager, distributionSetRepository,
(JpaDistributionSet) getValid(dsId));
return Collections.unmodifiableList(md.stream()
.map(meta -> distributionSetMetadataRepository
@@ -485,7 +444,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
toUpdate.setValue(md.getValue());
// touch it to update the lock revision because we are modifying the
// DS indirectly
touch(dsId);
JpaManagementHelper.touch(entityManager, distributionSetRepository, (JpaDistributionSet) getValid(dsId));
return distributionSetMetadataRepository.save(toUpdate);
}
@@ -498,72 +457,42 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
distributionSetId, key).orElseThrow(
() -> new EntityNotFoundException(DistributionSetMetadata.class, distributionSetId, key));
touch(metadata.getDistributionSet());
JpaManagementHelper.touch(entityManager, distributionSetRepository,
(JpaDistributionSet) metadata.getDistributionSet());
distributionSetMetadataRepository.deleteById(metadata.getId());
}
/**
* Method to get the latest distribution set based on DS ID after the
* metadata changes for that distribution set.
*
* @param ds
* is the DS to touch
*/
private JpaDistributionSet touch(final DistributionSet ds) {
// merge base distribution set so optLockRevision gets updated and audit
// log written because modifying metadata is modifying the base
// distribution set itself for auditing purposes.
final JpaDistributionSet result = entityManager.merge((JpaDistributionSet) ds);
result.setLastModifiedAt(0L);
return distributionSetRepository.save(result);
}
/**
* Method to get the latest distribution set based on DS ID after the
* metadata changes for that distribution set.
*
* @param distId
* of the DS to touch
*/
private JpaDistributionSet touch(final Long distId) {
return touch(getValid(distId));
}
@Override
public Page<DistributionSetMetadata> findMetaDataByDistributionSetId(final Pageable pageable,
final long distributionSetId) {
throwExceptionIfDistributionSetDoesNotExist(distributionSetId);
return convertMdPage(distributionSetMetadataRepository
.findAll((Specification<JpaDistributionSetMetadata>) (root, query, cb) -> cb.equal(
root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id),
distributionSetId), pageable),
pageable);
return JpaManagementHelper.findAllWithCountBySpec(distributionSetMetadataRepository, pageable,
Collections.singletonList(byDsIdSpec(distributionSetId)));
}
private Specification<JpaDistributionSetMetadata> byDsIdSpec(final long dsId) {
return (root, query, cb) -> cb
.equal(root.get(JpaDistributionSetMetadata_.distributionSet).get(JpaDistributionSet_.id), dsId);
}
@Override
public long countMetaDataByDistributionSetId(final long setId) {
throwExceptionIfDistributionSetDoesNotExist(setId);
return distributionSetMetadataRepository.countByDistributionSetId(setId);
}
@Override
public Page<DistributionSetMetadata> findMetaDataByDistributionSetIdAndRsql(final Pageable pageable,
final long distributionSetId, final String rsqlParam) {
throwExceptionIfDistributionSetDoesNotExist(distributionSetId);
final Specification<JpaDistributionSetMetadata> spec = RSQLUtility.buildRsqlSpecification(rsqlParam,
DistributionSetMetadataFields.class, virtualPropertyReplacer, database);
final List<Specification<JpaDistributionSetMetadata>> specList = Arrays
.asList(RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetMetadataFields.class,
virtualPropertyReplacer, database), byDsIdSpec(distributionSetId));
return convertMdPage(
distributionSetMetadataRepository
.findAll((Specification<JpaDistributionSetMetadata>) (root, query, cb) -> cb.and(
cb.equal(root.get(JpaDistributionSetMetadata_.distributionSet)
.get(JpaDistributionSet_.id), distributionSetId),
spec.toPredicate(root, query, cb)), pageable),
pageable);
}
private static Page<DistributionSetMetadata> convertMdPage(final Page<JpaDistributionSetMetadata> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
return JpaManagementHelper.findAllWithCountBySpec(distributionSetMetadataRepository, pageable, specList);
}
@Override
@@ -571,7 +500,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
throwExceptionIfDistributionSetDoesNotExist(setId);
return distributionSetMetadataRepository.findById(new DsMetadataCompositeKey(setId, key))
.map(dmd -> (DistributionSetMetadata) dmd);
.map(DistributionSetMetadata.class::cast);
}
@Override
@@ -611,19 +540,14 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
specList.add(spec);
}
if (distributionSetFilter.getType() != null) {
spec = DistributionSetSpecification.byType(distributionSetFilter.getType());
if (distributionSetFilter.getTypeId() != null) {
spec = DistributionSetSpecification.byType(distributionSetFilter.getTypeId());
specList.add(spec);
}
if (!StringUtils.isEmpty(distributionSetFilter.getSearchText())) {
spec = DistributionSetSpecification.likeNameOrDescriptionOrVersion(distributionSetFilter.getSearchText());
specList.add(spec);
}
if (!StringUtils.isEmpty(distributionSetFilter.getFilterString())) {
final String[] dsFilterNameAndVersionEntries = getDsFilterNameAndVersionEntries(
distributionSetFilter.getFilterString().trim());
final String[] dsFilterNameAndVersionEntries = JpaManagementHelper
.getFilterNameAndVersionEntries(distributionSetFilter.getSearchText().trim());
spec = DistributionSetSpecification.likeNameAndVersion(dsFilterNameAndVersionEntries[0],
dsFilterNameAndVersionEntries[1]);
specList.add(spec);
@@ -645,19 +569,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
return specList;
}
// the format of filter string is 'name:version'. 'name' and 'version'
// fields follow the starts_with semantic, that changes to equal for 'name'
// field when the semicolon is present
private static String[] getDsFilterNameAndVersionEntries(final String filterString) {
final int semicolonIndex = filterString.indexOf(':');
final String dsFilterName = semicolonIndex != -1 ? filterString.substring(0, semicolonIndex)
: (filterString + "%");
final String dsFilterVersion = semicolonIndex != -1 ? (filterString.substring(semicolonIndex + 1) + "%") : "%";
return new String[] { !StringUtils.isEmpty(dsFilterName) ? dsFilterName : "%", dsFilterVersion };
}
private void assertDistributionSetIsNotAssignedToTargets(final Long distributionSet) {
if (actionRepository.countByDistributionSetId(distributionSet) > 0) {
throw new EntityReadOnlyException(String.format(
@@ -672,26 +583,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
return isNoTagActive || isAtLeastOneTagActive;
}
/**
* executes findAll with the given {@link DistributionSet}
* {@link Specification}s.
*
* @param pageable
* paging parameter
* @param specList
* list of @link {@link Specification}
* @return the page with the found {@link DistributionSet}
*/
private Page<JpaDistributionSet> findByCriteriaAPI(final Pageable pageable,
final List<Specification<JpaDistributionSet>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return distributionSetRepository.findAll(pageable);
}
return distributionSetRepository.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable);
}
private void checkAndThrowIfDistributionSetMetadataAlreadyExists(final DsMetadataCompositeKey metadataId) {
if (distributionSetMetadataRepository.existsById(metadataId)) {
throw new EntityAlreadyExistsException(
@@ -769,7 +660,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
public Page<DistributionSet> findByTag(final Pageable pageable, final long tagId) {
throwEntityNotFoundExceptionIfDsTagDoesNotExist(tagId);
return convertDsPage(distributionSetRepository.findByTag(pageable, tagId), pageable);
return JpaManagementHelper.convertPage(distributionSetRepository.findByTag(pageable, tagId), pageable);
}
@@ -783,28 +674,27 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
public Page<DistributionSet> findByRsqlAndTag(final Pageable pageable, final String rsqlParam, final long tagId) {
throwEntityNotFoundExceptionIfDsTagDoesNotExist(tagId);
final Specification<JpaDistributionSet> spec = RSQLUtility.buildRsqlSpecification(rsqlParam,
DistributionSetFields.class, virtualPropertyReplacer, database);
final List<Specification<JpaDistributionSet>> specList = Arrays.asList(
RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetFields.class, virtualPropertyReplacer,
database),
DistributionSetSpecification.hasTag(tagId), DistributionSetSpecification.isDeleted(false));
return convertDsPage(findByCriteriaAPI(pageable, Arrays.asList(spec, DistributionSetSpecification.hasTag(tagId),
DistributionSetSpecification.isDeleted(false))), pageable);
return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, pageable, specList);
}
@Override
public Slice<DistributionSet> findAll(final Pageable pageable) {
return convertDsPage(
distributionSetRepository.findAllWithoutCount(DistributionSetSpecification.isDeleted(false), pageable),
pageable);
return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, pageable,
Collections.singletonList(DistributionSetSpecification.isDeleted(false)));
}
@Override
public Page<DistributionSet> findByRsql(final Pageable pageable, final String rsqlParam) {
final Specification<JpaDistributionSet> spec = RSQLUtility.buildRsqlSpecification(rsqlParam,
DistributionSetFields.class, virtualPropertyReplacer, database);
final List<Specification<JpaDistributionSet>> specList = Arrays.asList(RSQLUtility
.buildRsqlSpecification(rsqlParam, DistributionSetFields.class, virtualPropertyReplacer, database),
DistributionSetSpecification.isDeleted(false));
return convertDsPage(
findByCriteriaAPI(pageable, Arrays.asList(spec, DistributionSetSpecification.isDeleted(false))),
pageable);
return JpaManagementHelper.findAllWithCountBySpec(distributionSetRepository, pageable, specList);
}
@Override

View File

@@ -31,7 +31,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
@@ -125,7 +124,7 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage
@Override
public Slice<DistributionSetTag> findAll(final Pageable pageable) {
return convertDsPage(distributionSetTagRepository.findAllWithoutCount(pageable), pageable);
return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetTagRepository, pageable, null);
}
@Override
@@ -133,7 +132,8 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage
final Specification<JpaDistributionSetTag> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TagFields.class,
virtualPropertyReplacer, database);
return convertDsPage(distributionSetTagRepository.findAll(spec, pageable), pageable);
return JpaManagementHelper.findAllWithCountBySpec(distributionSetTagRepository, pageable,
Collections.singletonList(spec));
}
@Override
@@ -142,18 +142,8 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage
throw new EntityNotFoundException(DistributionSet.class, setId);
}
return convertDsPage(distributionSetTagRepository.findAll(TagSpecification.ofDistributionSet(setId), pageable),
pageable);
}
private static Page<DistributionSetTag> convertDsPage(final Page<JpaDistributionSetTag> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
private static Slice<DistributionSetTag> convertDsPage(final Slice<JpaDistributionSetTag> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0);
return JpaManagementHelper.findAllWithCountBySpec(distributionSetTagRepository, pageable,
Collections.singletonList(TagSpecification.ofDistributionSet(setId)));
}
@Override
@@ -178,7 +168,7 @@ public class JpaDistributionSetTagManagement implements DistributionSetTagManage
@Override
public Optional<DistributionSetTag> get(final long id) {
return distributionSetTagRepository.findById(id).map(dst -> (DistributionSetTag) dst);
return distributionSetTagRepository.findById(id).map(DistributionSetTag.class::cast);
}
@Override

View File

@@ -35,17 +35,14 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetTypeSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
@@ -227,17 +224,18 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana
@Override
public Page<DistributionSetType> findByRsql(final Pageable pageable, final String rsqlParam) {
return convertPage(
findByCriteriaAPI(pageable,
Arrays.asList(RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetTypeFields.class,
virtualPropertyReplacer, database), DistributionSetTypeSpecification.isDeleted(false))),
pageable);
return JpaManagementHelper
.findAllWithCountBySpec(distributionSetTypeRepository, pageable,
Arrays.asList(
RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetTypeFields.class,
virtualPropertyReplacer, database),
DistributionSetTypeSpecification.isDeleted(false)));
}
@Override
public Slice<DistributionSetType> findAll(final Pageable pageable) {
return convertPage(distributionSetTypeRepository
.findAllWithoutCount(DistributionSetTypeSpecification.isDeleted(false), pageable), pageable);
return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetTypeRepository, pageable,
Collections.singletonList(DistributionSetTypeSpecification.isDeleted(false)));
}
@Override
@@ -280,14 +278,13 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana
if (distributionSetRepository.countByTypeId(typeId) > 0) {
toDelete.setDeleted(true);
distributionSetTypeRepository.save(toDelete);
}
else {
} else {
distributionSetTypeRepository.deleteById(typeId);
}
}
private void unassignDsTypeFromTargetTypes(long typeId) {
List<JpaTargetType> targetTypesByDsType = targetTypeRepository.findByDsType(typeId);
private void unassignDsTypeFromTargetTypes(final long typeId) {
final List<JpaTargetType> targetTypesByDsType = targetTypeRepository.findByDsType(typeId);
targetTypesByDsType.forEach(targetType -> {
targetType.removeDistributionSetType(typeId);
targetTypeRepository.save(targetType);
@@ -318,26 +315,6 @@ public class JpaDistributionSetTypeManagement implements DistributionSetTypeMana
}
}
private static Page<DistributionSetType> convertPage(final Page<JpaDistributionSetType> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
private static Slice<DistributionSetType> convertPage(final Slice<JpaDistributionSetType> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0);
}
private Page<JpaDistributionSetType> findByCriteriaAPI(final Pageable pageable,
final List<Specification<JpaDistributionSetType>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return distributionSetTypeRepository.findAll(pageable);
}
return distributionSetTypeRepository.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable);
}
@Override
@Transactional
@Retryable(include = {

View File

@@ -0,0 +1,98 @@
/**
* Copyright (c) 2022 Bosch.IO GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.jpa;
import java.util.Collections;
import java.util.List;
import javax.persistence.EntityManager;
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/**
* A collection of static helper methods for the management classes
*/
public final class JpaManagementHelper {
private JpaManagementHelper() {
}
public static <T, J extends T> Page<T> findAllWithCountBySpec(final JpaSpecificationExecutor<J> repository,
final Pageable pageable, final List<Specification<J>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return convertPage(repository.findAll(Specification.where(null), pageable), pageable);
}
return convertPage(repository.findAll(combineWithAnd(specList), pageable), pageable);
}
public static <T, J extends T> Page<T> convertPage(final Page<J> jpaAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(jpaAll.getContent()), pageable, jpaAll.getTotalElements());
}
private static <J> Specification<J> combineWithAnd(final List<Specification<J>> specList) {
return specList.size() == 1 ? specList.get(0) : SpecificationsBuilder.combineWithAnd(specList);
}
public static <T, J extends T> Slice<T> findAllWithoutCountBySpec(final NoCountSliceRepository<J> repository,
final Pageable pageable, final List<Specification<J>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return convertPage(repository.findAllWithoutCount(pageable), pageable);
}
return convertPage(repository.findAllWithoutCount(combineWithAnd(specList), pageable), pageable);
}
public static <T, J extends T> Slice<T> convertPage(final Slice<J> jpaAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(jpaAll.getContent()), pageable, 0);
}
public static <J> long countBySpec(final JpaSpecificationExecutor<J> repository,
final List<Specification<J>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return repository.count(Specification.where(null));
}
return repository.count(combineWithAnd(specList));
}
public static <J extends AbstractJpaBaseEntity> J touch(final EntityManager entityManager,
final CrudRepository<J, ?> repository, final J entity) {
// merge base entity so optLockRevision gets updated and audit
// log written because modifying e.g. metadata is modifying the base
// entity itself for auditing purposes.
final J result = entityManager.merge(entity);
result.setLastModifiedAt(0L);
return repository.save(result);
}
// the format of filter string is 'name:version'. 'name' and 'version'
// fields follow the starts_with semantic, that changes to equal for 'name'
// field when the semicolon is present
public static String[] getFilterNameAndVersionEntries(final String filterString) {
final int semicolonIndex = filterString.indexOf(':');
final String filterName = semicolonIndex != -1 ? filterString.substring(0, semicolonIndex)
: (filterString + "%");
final String filterVersion = semicolonIndex != -1 ? (filterString.substring(semicolonIndex + 1) + "%") : "%";
return new String[] { !StringUtils.isEmpty(filterName) ? filterName : "%", filterVersion };
}
}

View File

@@ -55,7 +55,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
@@ -575,7 +574,7 @@ public class JpaRolloutExecutor implements RolloutExecutor {
final PageRequest pageRequest = PageRequest.of(0, Math.toIntExact(limit));
final List<Long> readyGroups = RolloutHelper.getGroupsByStatusIncludingGroup(rollout.getRolloutGroups(),
RolloutGroupStatus.READY, group);
final Page<Target> targets = targetManagement.findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible(
final Slice<Target> targets = targetManagement.findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible(
pageRequest, readyGroups, targetFilter, rollout.getDistributionSet().getType());
createAssignmentOfTargetsToGroup(targets, group);
@@ -585,8 +584,8 @@ public class JpaRolloutExecutor implements RolloutExecutor {
}
/**
* Schedules a group of the rollout. Scheduled Actions are created to achieve
* this. The creation of those Actions is allowed to fail.
* Schedules a group of the rollout. Scheduled Actions are created to
* achieve this. The creation of those Actions is allowed to fail.
*/
private boolean scheduleRolloutGroup(final JpaRollout rollout, final JpaRolloutGroup group) {
final long targetsInGroup = rolloutTargetGroupRepository.countByRolloutGroup(group);
@@ -634,8 +633,8 @@ public class JpaRolloutExecutor implements RolloutExecutor {
final ActionType actionType = rollout.getActionType();
final long forceTime = rollout.getForcedTime();
final Page<Target> targets = targetManagement.findByInRolloutGroupWithoutAction(pageRequest, groupId);
if (targets.getTotalElements() > 0) {
final Slice<Target> targets = targetManagement.findByInRolloutGroupWithoutAction(pageRequest, groupId);
if (targets.getNumberOfElements() > 0) {
createScheduledAction(targets.getContent(), distributionSet, actionType, forceTime, rollout, group);
}
@@ -643,14 +642,14 @@ public class JpaRolloutExecutor implements RolloutExecutor {
});
}
private void createAssignmentOfTargetsToGroup(final Page<Target> targets, final RolloutGroup group) {
private void createAssignmentOfTargetsToGroup(final Slice<Target> targets, final RolloutGroup group) {
targets.forEach(target -> rolloutTargetGroupRepository.save(new RolloutTargetGroup(group, target)));
}
/**
* Creates an action entry into the action repository. In case of existing
* scheduled actions the scheduled actions gets canceled. A scheduled action is
* created in-active.
* scheduled actions the scheduled actions gets canceled. A scheduled action
* is created in-active.
*/
private void createScheduledAction(final Collection<Target> targets, final DistributionSet distributionSet,
final ActionType actionType, final Long forcedTime, final Rollout rollout,

View File

@@ -8,6 +8,7 @@
*/
package org.eclipse.hawkbit.repository.jpa;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -104,15 +105,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
public Page<RolloutGroup> findByRollout(final Pageable pageable, final long rolloutId) {
throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId);
return convertPage(rolloutGroupRepository.findByRolloutId(rolloutId, pageable), pageable);
}
private static Page<RolloutGroup> convertPage(final Page<JpaRolloutGroup> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
private static Page<Target> convertTPage(final Page<JpaTarget> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
return JpaManagementHelper.convertPage(rolloutGroupRepository.findByRolloutId(rolloutId, pageable), pageable);
}
@Override
@@ -120,12 +113,12 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
final String rsqlParam) {
throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId);
final Specification<JpaRolloutGroup> specification = RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutGroupFields.class,
virtualPropertyReplacer, database);
final List<Specification<JpaRolloutGroup>> specList = Arrays.asList(
RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutGroupFields.class, virtualPropertyReplacer,
database),
(root, query, cb) -> cb.equal(root.get(JpaRolloutGroup_.rollout).get(JpaRollout_.id), rolloutId));
return convertPage(rolloutGroupRepository.findAll((root, query, criteriaBuilder) -> criteriaBuilder.and(
criteriaBuilder.equal(root.get(JpaRolloutGroup_.rollout).get(JpaRollout_.id), rolloutId),
specification.toPredicate(root, query, criteriaBuilder)), pageable), pageable);
return JpaManagementHelper.findAllWithCountBySpec(rolloutGroupRepository, pageable, specList);
}
private void throwEntityNotFoundExceptionIfRolloutDoesNotExist(final Long rolloutId) {
@@ -157,7 +150,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
rolloutGroup.setTotalTargetCountStatus(totalTargetCountStatus);
}
return convertPage(rolloutGroups, pageable);
return JpaManagementHelper.convertPage(rolloutGroups, pageable);
}
@Override
@@ -209,19 +202,18 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
@Override
public Page<Target> findTargetsOfRolloutGroupByRsql(final Pageable pageable, final long rolloutGroupId,
final String rsqlParam) {
throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId);
final Specification<JpaTarget> rsqlSpecification = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class,
virtualPropertyReplacer, database);
final List<Specification<JpaTarget>> specList = Arrays.asList(
RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database),
(root, query, cb) -> {
final ListJoin<JpaTarget, RolloutTargetGroup> rolloutTargetJoin = root
.join(JpaTarget_.rolloutTargetGroup);
return cb.equal(rolloutTargetJoin.get(RolloutTargetGroup_.rolloutGroup).get(JpaRolloutGroup_.id),
rolloutGroupId);
});
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);
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, specList);
}
@Override
@@ -233,11 +225,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 JpaTargetManagement.convertPage(
targetRepository.findAll(TargetSpecifications.isInRolloutGroup(rolloutGroupId), page), page);
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, page,
Collections.singletonList(TargetSpecifications.isInRolloutGroup(rolloutGroupId)));
}
return JpaTargetManagement.convertPage(
targetRepository.findAll(TargetSpecifications.isInActionRolloutGroup(rolloutGroupId), page), page);
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, page,
Collections.singletonList(TargetSpecifications.isInActionRolloutGroup(rolloutGroupId)));
}
private static boolean isRolloutStatusReady(final RolloutGroup rolloutGroup) {

View File

@@ -1,106 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.repository.jpa;
import java.util.Collections;
import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate;
import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout_;
import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.RolloutGroupConditions;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
/**
* A collection of static helper methods for the {@link JpaRolloutManagement}
*/
final class JpaRolloutHelper {
private JpaRolloutHelper() {
}
/**
* In case the given group is missing conditions or actions, they will be
* set from the supplied default conditions.
*
* @param create
* group to check
* @param conditions
* default conditions and actions
*/
static JpaRolloutGroup prepareRolloutGroupWithDefaultConditions(final RolloutGroupCreate create,
final RolloutGroupConditions conditions) {
final JpaRolloutGroup group = ((JpaRolloutGroupCreate) create).build();
if (group.getSuccessCondition() == null) {
group.setSuccessCondition(conditions.getSuccessCondition());
}
if (group.getSuccessConditionExp() == null) {
group.setSuccessConditionExp(conditions.getSuccessConditionExp());
}
if (group.getSuccessAction() == null) {
group.setSuccessAction(conditions.getSuccessAction());
}
if (group.getSuccessActionExp() == null) {
group.setSuccessActionExp(conditions.getSuccessActionExp());
}
if (group.getErrorCondition() == null) {
group.setErrorCondition(conditions.getErrorCondition());
}
if (group.getErrorConditionExp() == null) {
group.setErrorConditionExp(conditions.getErrorConditionExp());
}
if (group.getErrorAction() == null) {
group.setErrorAction(conditions.getErrorAction());
}
if (group.getErrorActionExp() == null) {
group.setErrorActionExp(conditions.getErrorActionExp());
}
return group;
}
/**
* Builds a {@link Specification} to search a rollout by name or
* description.
*
* @param searchText
* search string
* @param isDeleted
* <code>true</code> if deleted rollouts should be included in
* the search. Otherwise <code>false</code>
* @return criteria specification with a query for name or description of a
* rollout
*/
static Specification<JpaRollout> likeNameOrDescription(final String searchText, final boolean isDeleted) {
return (rolloutRoot, query, criteriaBuilder) -> {
final String searchTextToLower = searchText.toLowerCase();
return criteriaBuilder.and(criteriaBuilder.or(
criteriaBuilder.like(criteriaBuilder.lower(rolloutRoot.get(JpaRollout_.name)), searchTextToLower),
criteriaBuilder.like(criteriaBuilder.lower(rolloutRoot.get(JpaRollout_.description)),
searchTextToLower)),
criteriaBuilder.equal(rolloutRoot.get(JpaRollout_.deleted), isDeleted));
};
}
static Page<Rollout> convertPage(final Page<JpaRollout> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
static Slice<Rollout> convertPage(final Slice<JpaRollout> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0);
}
}

View File

@@ -12,6 +12,7 @@ import static org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate.a
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -41,13 +42,13 @@ import org.eclipse.hawkbit.repository.event.remote.entity.RolloutGroupCreatedEve
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate;
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.specifications.RolloutSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper;
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper;
@@ -160,8 +161,8 @@ public class JpaRolloutManagement implements RolloutManagement {
@Override
public Page<Rollout> findAll(final Pageable pageable, final boolean deleted) {
final Specification<JpaRollout> spec = RolloutSpecification.isDeletedWithDistributionSet(deleted);
return JpaRolloutHelper.convertPage(rolloutRepository.findAll(spec, pageable), pageable);
return JpaManagementHelper.findAllWithCountBySpec(rolloutRepository, pageable,
Collections.singletonList(RolloutSpecification.isDeletedWithDistributionSet(deleted)));
}
@Override
@@ -171,24 +172,12 @@ public class JpaRolloutManagement implements RolloutManagement {
RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutFields.class, virtualPropertyReplacer, database));
specList.add(RolloutSpecification.isDeletedWithDistributionSet(deleted));
return JpaRolloutHelper.convertPage(findByCriteriaAPI(pageable, specList), pageable);
}
/**
* Executes findAll with the given {@link Rollout} {@link Specification}s.
*/
private Page<JpaRollout> findByCriteriaAPI(final Pageable pageable,
final List<Specification<JpaRollout>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return rolloutRepository.findAll(pageable);
}
return rolloutRepository.findAll(SpecificationsBuilder.combineWithAnd(specList), pageable);
return JpaManagementHelper.findAllWithCountBySpec(rolloutRepository, pageable, specList);
}
@Override
public Optional<Rollout> get(final long rolloutId) {
return rolloutRepository.findById(rolloutId).map(r -> (Rollout) r);
return rolloutRepository.findById(rolloutId).map(Rollout.class::cast);
}
@Override
@@ -264,8 +253,7 @@ public class JpaRolloutManagement implements RolloutManagement {
// prepare the groups
final List<RolloutGroup> groups = groupList.stream()
.map(group -> JpaRolloutHelper.prepareRolloutGroupWithDefaultConditions(group, conditions))
.collect(Collectors.toList());
.map(group -> prepareRolloutGroupWithDefaultConditions(group, conditions)).collect(Collectors.toList());
groups.forEach(RolloutHelper::verifyRolloutGroupHasConditions);
RolloutHelper.verifyRemainingTargets(calculateRemainingTargets(groups, savedRollout.getTargetFilterQuery(),
@@ -307,6 +295,48 @@ public class JpaRolloutManagement implements RolloutManagement {
return rolloutRepository.save(savedRollout);
}
/**
* In case the given group is missing conditions or actions, they will be
* set from the supplied default conditions.
*
* @param create
* group to check
* @param conditions
* default conditions and actions
*/
private static JpaRolloutGroup prepareRolloutGroupWithDefaultConditions(final RolloutGroupCreate create,
final RolloutGroupConditions conditions) {
final JpaRolloutGroup group = ((JpaRolloutGroupCreate) create).build();
if (group.getSuccessCondition() == null) {
group.setSuccessCondition(conditions.getSuccessCondition());
}
if (group.getSuccessConditionExp() == null) {
group.setSuccessConditionExp(conditions.getSuccessConditionExp());
}
if (group.getSuccessAction() == null) {
group.setSuccessAction(conditions.getSuccessAction());
}
if (group.getSuccessActionExp() == null) {
group.setSuccessActionExp(conditions.getSuccessActionExp());
}
if (group.getErrorCondition() == null) {
group.setErrorCondition(conditions.getErrorCondition());
}
if (group.getErrorConditionExp() == null) {
group.setErrorConditionExp(conditions.getErrorConditionExp());
}
if (group.getErrorAction() == null) {
group.setErrorAction(conditions.getErrorAction());
}
if (group.getErrorActionExp() == null) {
group.setErrorActionExp(conditions.getErrorActionExp());
}
return group;
}
private void publishRolloutGroupCreatedEventAfterCommit(final RolloutGroup group, final Rollout rollout) {
afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher().publishEvent(
new RolloutGroupCreatedEvent(group, rollout.getId(), eventPublisherHolder.getApplicationId())));
@@ -456,7 +486,7 @@ public class JpaRolloutManagement implements RolloutManagement {
@Override
public long countByFilters(final String searchText) {
return rolloutRepository.count(JpaRolloutHelper.likeNameOrDescription(searchText, false));
return rolloutRepository.count(RolloutSpecification.likeName(searchText, false));
}
@Override
@@ -467,10 +497,10 @@ public class JpaRolloutManagement implements RolloutManagement {
@Override
public Slice<Rollout> findByFiltersWithDetailedStatus(final Pageable pageable, final String searchText,
final boolean deleted) {
final Slice<JpaRollout> findAll = findByCriteriaAPI(pageable,
Arrays.asList(JpaRolloutHelper.likeNameOrDescription(searchText, deleted)));
final Slice<Rollout> findAll = JpaManagementHelper.findAllWithoutCountBySpec(rolloutRepository, pageable,
Collections.singletonList(RolloutSpecification.likeName(searchText, deleted)));
setRolloutStatusDetails(findAll);
return JpaRolloutHelper.convertPage(findAll, pageable);
return findAll;
}
@Override
@@ -521,12 +551,11 @@ public class JpaRolloutManagement implements RolloutManagement {
}
@Override
public Page<Rollout> findAllWithDetailedStatus(final Pageable pageable, final boolean deleted) {
final Page<JpaRollout> rollouts;
final Specification<JpaRollout> spec = RolloutSpecification.isDeletedWithDistributionSet(deleted);
rollouts = rolloutRepository.findAll(spec, pageable);
public Slice<Rollout> findAllWithDetailedStatus(final Pageable pageable, final boolean deleted) {
final Slice<Rollout> rollouts = JpaManagementHelper.findAllWithoutCountBySpec(rolloutRepository, pageable,
Collections.singletonList(RolloutSpecification.isDeletedWithDistributionSet(deleted)));
setRolloutStatusDetails(rollouts);
return JpaRolloutHelper.convertPage(rollouts, pageable);
return rollouts;
}
@Override
@@ -579,7 +608,7 @@ public class JpaRolloutManagement implements RolloutManagement {
return fromCache;
}
private void setRolloutStatusDetails(final Slice<JpaRollout> rollouts) {
private void setRolloutStatusDetails(final Slice<Rollout> rollouts) {
final List<Long> rolloutIds = rollouts.getContent().stream().map(Rollout::getId).collect(Collectors.toList());
final Map<Long, List<TotalTargetCountActionStatus>> allStatesForRollout = getStatusCountItemForRollout(
rolloutIds);
@@ -588,7 +617,7 @@ public class JpaRolloutManagement implements RolloutManagement {
rollouts.forEach(rollout -> {
final TotalTargetCountStatus totalTargetCountStatus = new TotalTargetCountStatus(
allStatesForRollout.get(rollout.getId()), rollout.getTotalTargets(), rollout.getActionType());
rollout.setTotalTargetCountStatus(totalTargetCountStatus);
((JpaRollout) rollout).setTotalTargetCountStatus(totalTargetCountStatus);
});
}
}

View File

@@ -58,7 +58,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule_;
import org.eclipse.hawkbit.repository.jpa.model.SwMetadataCompositeKey;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.specifications.SoftwareModuleSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.AssignedSoftwareModule;
@@ -70,7 +69,6 @@ import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
@@ -183,7 +181,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
specList.add(SoftwareModuleSpecification.equalType(typeId));
specList.add(SoftwareModuleSpecification.isDeletedFalse());
return convertSmPage(findByCriteriaAPI(pageable, specList), pageable);
return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleRepository, pageable, specList);
}
private void throwExceptionIfSoftwareModuleTypeDoesNotExist(final Long typeId) {
@@ -192,23 +190,9 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
}
}
private static Slice<SoftwareModule> convertSmPage(final Slice<JpaSoftwareModule> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0);
}
private static Page<SoftwareModule> convertSmPage(final Page<JpaSoftwareModule> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
private static Page<SoftwareModuleMetadata> convertSmMdPage(final Page<JpaSoftwareModuleMetadata> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
@Override
public Optional<SoftwareModule> get(final long id) {
return softwareModuleRepository.findById(id).map(sm -> (SoftwareModule) sm);
return softwareModuleRepository.findById(id).map(SoftwareModule.class::cast);
}
@Override
@@ -224,15 +208,6 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
return distributionSetRepository.countByModulesId(moduleId) <= 0;
}
private Slice<JpaSoftwareModule> findByCriteriaAPI(final Pageable pageable,
final List<Specification<JpaSoftwareModule>> specList) {
return softwareModuleRepository.findAllWithoutCount(SpecificationsBuilder.combineWithAnd(specList), pageable);
}
private Long countSwModuleByCriteriaAPI(final List<Specification<JpaSoftwareModule>> specList) {
return softwareModuleRepository.count(SpecificationsBuilder.combineWithAnd(specList));
}
private void deleteGridFsArtifacts(final JpaSoftwareModule swModule) {
for (final Artifact localArtifact : swModule.getArtifacts()) {
artifactManagement.clearArtifactBinary(localArtifact.getSha1Hash(), swModule.getId());
@@ -276,29 +251,18 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
@Override
public Slice<SoftwareModule> findAll(final Pageable pageable) {
final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>(2);
specList.add(SoftwareModuleSpecification.isDeletedFalse());
specList.add(SoftwareModuleSpecification.fetchType());
Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse();
specList.add(spec);
spec = (root, query, cb) -> {
if (!query.getResultType().isAssignableFrom(Long.class)) {
root.fetch(JpaSoftwareModule_.type);
}
return cb.conjunction();
};
specList.add(spec);
return convertSmPage(findByCriteriaAPI(pageable, specList), pageable);
return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleRepository, pageable, specList);
}
@Override
public long count() {
final Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse();
return countSwModuleByCriteriaAPI(Arrays.asList(spec));
return JpaManagementHelper.countBySpec(softwareModuleRepository, Collections.singletonList(spec));
}
@Override
@@ -306,7 +270,8 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
final Specification<JpaSoftwareModule> spec = RSQLUtility.buildRsqlSpecification(rsqlParam,
SoftwareModuleFields.class, virtualPropertyReplacer, database);
return convertSmPage(softwareModuleRepository.findAll(spec, pageable), pageable);
return JpaManagementHelper.findAllWithCountBySpec(softwareModuleRepository, pageable,
Collections.singletonList(spec));
}
@Override
@@ -318,34 +283,28 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
@Override
public Slice<SoftwareModule> findByTextAndType(final Pageable pageable, final String searchText,
final Long typeId) {
final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>(4);
Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse();
specList.add(spec);
specList.add(SoftwareModuleSpecification.isDeletedFalse());
if (!StringUtils.isEmpty(searchText)) {
spec = SoftwareModuleSpecification.likeNameOrVersion(searchText);
specList.add(spec);
specList.add(buildSmSearchQuerySpec(searchText));
}
if (null != typeId) {
throwExceptionIfSoftwareModuleTypeDoesNotExist(typeId);
spec = SoftwareModuleSpecification.equalType(typeId);
specList.add(spec);
specList.add(SoftwareModuleSpecification.equalType(typeId));
}
spec = (root, query, cb) -> {
if (!query.getResultType().isAssignableFrom(Long.class)) {
root.fetch(JpaSoftwareModule_.type);
}
return cb.conjunction();
};
specList.add(SoftwareModuleSpecification.fetchType());
specList.add(spec);
return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleRepository, pageable, specList);
}
return convertSmPage(findByCriteriaAPI(pageable, specList), pageable);
private Specification<JpaSoftwareModule> buildSmSearchQuerySpec(final String searchText) {
final String[] smFilterNameAndVersionEntries = JpaManagementHelper
.getFilterNameAndVersionEntries(searchText.trim());
return SoftwareModuleSpecification.likeNameAndVersion(smFilterNameAndVersionEntries[0],
smFilterNameAndVersionEntries[1]);
}
@Override
@@ -392,8 +351,9 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
private List<Specification<JpaSoftwareModule>> buildSpecificationList(final String searchText, final Long typeId) {
final List<Specification<JpaSoftwareModule>> specList = Lists.newArrayListWithExpectedSize(3);
if (!StringUtils.isEmpty(searchText)) {
specList.add(SoftwareModuleSpecification.likeNameOrVersion(searchText));
specList.add(buildSmSearchQuerySpec(searchText));
}
if (typeId != null) {
throwExceptionIfSoftwareModuleTypeDoesNotExist(typeId);
@@ -413,15 +373,13 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
@Override
public long countByTextAndType(final String searchText, final Long typeId) {
final List<Specification<JpaSoftwareModule>> specList = new ArrayList<>(3);
Specification<JpaSoftwareModule> spec = SoftwareModuleSpecification.isDeletedFalse();
specList.add(spec);
if (!StringUtils.isEmpty(searchText)) {
spec = SoftwareModuleSpecification.likeNameOrVersion(searchText);
specList.add(spec);
specList.add(buildSmSearchQuerySpec(searchText));
}
if (null != typeId) {
@@ -431,7 +389,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
specList.add(spec);
}
return countSwModuleByCriteriaAPI(specList);
return JpaManagementHelper.countBySpec(softwareModuleRepository, specList);
}
@Override
@@ -506,7 +464,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
private static Stream<JpaSoftwareModuleMetadataCreate> createJpaMetadataCreateStream(
final Collection<SoftwareModuleMetadataCreate> create) {
return create.stream().map(c -> (JpaSoftwareModuleMetadataCreate) c);
return create.stream().map(JpaSoftwareModuleMetadataCreate.class::cast);
}
private SoftwareModuleMetadata saveMetadata(final JpaSoftwareModuleMetadataCreate create) {
@@ -522,7 +480,8 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
}
private void assertSoftwareModuleExists(final Long moduleId) {
touch(moduleId);
JpaManagementHelper.touch(entityManager, softwareModuleRepository, (JpaSoftwareModule) get(moduleId)
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, moduleId)));
}
/**
@@ -555,38 +514,11 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
update.getValue().ifPresent(metadata::setValue);
update.isTargetVisible().ifPresent(metadata::setTargetVisible);
touch(metadata.getSoftwareModule());
JpaManagementHelper.touch(entityManager, softwareModuleRepository,
(JpaSoftwareModule) metadata.getSoftwareModule());
return softwareModuleMetadataRepository.save(metadata);
}
/**
* Method to get the latest module based on ID after the metadata changes
* for that module.
*
* @param latestModule
* module to touch
*/
private JpaSoftwareModule touch(final SoftwareModule latestModule) {
// merge base distribution set so optLockRevision gets updated and audit
// log written because modifying metadata is modifying the base
// distribution set itself for auditing purposes.
final JpaSoftwareModule result = entityManager.merge((JpaSoftwareModule) latestModule);
result.setLastModifiedAt(0L);
return result;
}
/**
* Method to get the latest module based on ID after the metadata changes
* for that module.
*
* @param moduleId
* of the module to touch
*/
private JpaSoftwareModule touch(final Long moduleId) {
return touch(get(moduleId).orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, moduleId)));
}
@Override
@Transactional
@Retryable(include = {
@@ -595,7 +527,8 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
final JpaSoftwareModuleMetadata metadata = (JpaSoftwareModuleMetadata) getMetaDataBySoftwareModuleId(moduleId,
key).orElseThrow(() -> new EntityNotFoundException(SoftwareModuleMetadata.class, moduleId, key));
touch(metadata.getSoftwareModule());
JpaManagementHelper.touch(entityManager, softwareModuleRepository,
(JpaSoftwareModule) metadata.getSoftwareModule());
softwareModuleMetadataRepository.deleteById(metadata.getId());
}
@@ -608,35 +541,32 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
@Override
public Page<SoftwareModuleMetadata> findMetaDataByRsql(final Pageable pageable, final long softwareModuleId,
final String rsqlParam) {
throwExceptionIfSoftwareModuleDoesNotExist(softwareModuleId);
final Specification<JpaSoftwareModuleMetadata> spec = RSQLUtility.buildRsqlSpecification(rsqlParam,
SoftwareModuleMetadataFields.class, virtualPropertyReplacer, database);
return convertSmMdPage(
softwareModuleMetadataRepository
.findAll(
(root, query, cb) -> cb.and(
cb.equal(root.get(JpaSoftwareModuleMetadata_.softwareModule)
.get(JpaSoftwareModule_.id), softwareModuleId),
spec.toPredicate(root, query, cb)),
pageable),
pageable);
final List<Specification<JpaSoftwareModuleMetadata>> specList = Arrays
.asList(RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleMetadataFields.class,
virtualPropertyReplacer, database), bySmIdSpec(softwareModuleId));
return JpaManagementHelper.findAllWithCountBySpec(softwareModuleMetadataRepository, pageable, specList);
}
private static Page<SoftwareModuleMetadata> convertMdPage(final Page<JpaSoftwareModuleMetadata> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
private static Specification<JpaSoftwareModuleMetadata> bySmIdSpec(final long smId) {
return (root, query, cb) -> cb
.equal(root.get(JpaSoftwareModuleMetadata_.softwareModule).get(JpaSoftwareModule_.id), smId);
}
@Override
public Page<SoftwareModuleMetadata> findMetaDataBySoftwareModuleId(final Pageable pageable, final long swId) {
throwExceptionIfSoftwareModuleDoesNotExist(swId);
return convertMdPage(softwareModuleMetadataRepository.findAll(
(Specification<JpaSoftwareModuleMetadata>) (root, query, cb) -> cb
.equal(root.get(JpaSoftwareModuleMetadata_.softwareModule).get(JpaSoftwareModule_.id), swId),
pageable), pageable);
return JpaManagementHelper.findAllWithCountBySpec(softwareModuleMetadataRepository, pageable,
Collections.singletonList(bySmIdSpec(swId)));
}
@Override
public long countMetaDataBySoftwareModuleId(final long moduleId) {
throwExceptionIfSoftwareModuleDoesNotExist(moduleId);
return softwareModuleMetadataRepository.countBySoftwareModuleId(moduleId);
}
@Override
@@ -644,7 +574,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
throwExceptionIfSoftwareModuleDoesNotExist(moduleId);
return softwareModuleMetadataRepository.findById(new SwMetadataCompositeKey(moduleId, key))
.map(smmd -> (SoftwareModuleMetadata) smmd);
.map(SoftwareModuleMetadata.class::cast);
}
private static void throwMetadataKeyAlreadyExists(final String metadataKey) {
@@ -669,7 +599,7 @@ public class JpaSoftwareModuleManagement implements SoftwareModuleManagement {
final long moduleId) {
throwExceptionIfSoftwareModuleDoesNotExist(moduleId);
return convertMdPage(softwareModuleMetadataRepository.findBySoftwareModuleIdAndTargetVisible(
return JpaManagementHelper.convertPage(softwareModuleMetadataRepository.findBySoftwareModuleIdAndTargetVisible(
PageRequest.of(0, RepositoryConstants.MAX_META_DATA_COUNT), moduleId, true), pageable);
}

View File

@@ -29,10 +29,8 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
@@ -60,8 +58,7 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage
public JpaSoftwareModuleTypeManagement(final DistributionSetTypeRepository distributionSetTypeRepository,
final SoftwareModuleTypeRepository softwareModuleTypeRepository,
final VirtualPropertyReplacer virtualPropertyReplacer,
final SoftwareModuleRepository softwareModuleRepository,
final Database database) {
final SoftwareModuleRepository softwareModuleRepository, final Database database) {
this.distributionSetTypeRepository = distributionSetTypeRepository;
this.softwareModuleTypeRepository = softwareModuleTypeRepository;
this.virtualPropertyReplacer = virtualPropertyReplacer;
@@ -87,18 +84,16 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage
@Override
public Page<SoftwareModuleType> findByRsql(final Pageable pageable, final String rsqlParam) {
final Specification<JpaSoftwareModuleType> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleTypeFields.class,
virtualPropertyReplacer, database);
return convertPage(softwareModuleTypeRepository.findAll(spec, pageable), pageable);
return JpaManagementHelper.findAllWithCountBySpec(softwareModuleTypeRepository, pageable,
Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlParam, SoftwareModuleTypeFields.class,
virtualPropertyReplacer, database)));
}
@Override
public Slice<SoftwareModuleType> findAll(final Pageable pageable) {
return convertPage(softwareModuleTypeRepository.findAllWithoutCount(
(targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(JpaSoftwareModuleType_.deleted), false),
pageable), pageable);
return JpaManagementHelper.findAllWithoutCountBySpec(softwareModuleTypeRepository, pageable,
Collections.singletonList(
(smTypeRoot, query, cb) -> cb.equal(smTypeRoot.get(JpaSoftwareModuleType_.deleted), false)));
}
@Override
@@ -151,16 +146,6 @@ public class JpaSoftwareModuleTypeManagement implements SoftwareModuleTypeManage
return creates.stream().map(this::create).collect(Collectors.toList());
}
private static Page<SoftwareModuleType> convertPage(final Page<JpaSoftwareModuleType> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
private static Slice<SoftwareModuleType> convertPage(final Slice<JpaSoftwareModuleType> findAll,
final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0);
}
@Override
@Transactional
@Retryable(include = {

View File

@@ -8,11 +8,12 @@
*/
package org.eclipse.hawkbit.repository.jpa;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.QuotaManagement;
import org.eclipse.hawkbit.repository.TargetFields;
@@ -32,7 +33,6 @@ import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetFilterQuerySpecification;
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper;
@@ -47,14 +47,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
@@ -137,8 +136,8 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
}
@Override
public Page<TargetFilterQuery> findAll(final Pageable pageable) {
return convertPage(targetFilterQueryRepository.findAll(pageable), pageable);
public Slice<TargetFilterQuery> findAll(final Pageable pageable) {
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable, null);
}
@Override
@@ -151,70 +150,73 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
return targetFilterQueryRepository.countByAutoAssignDistributionSetId(autoAssignDistributionSetId);
}
private static Page<TargetFilterQuery> convertPage(final Page<JpaTargetFilterQuery> findAll,
final Pageable pageable) {
return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements());
@Override
public Slice<TargetFilterQuery> findByName(final Pageable pageable, final String name) {
if (StringUtils.isEmpty(name)) {
return findAll(pageable);
}
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable,
Collections.singletonList(TargetFilterQuerySpecification.likeName(name)));
}
@Override
public Page<TargetFilterQuery> findByName(final Pageable pageable, final String name) {
List<Specification<JpaTargetFilterQuery>> specList = Collections.emptyList();
if (!StringUtils.isEmpty(name)) {
specList = Collections.singletonList(TargetFilterQuerySpecification.likeName(name));
public long countByName(final String name) {
if (StringUtils.isEmpty(name)) {
return count();
}
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable);
return JpaManagementHelper.countBySpec(targetFilterQueryRepository,
Collections.singletonList(TargetFilterQuerySpecification.likeName(name)));
}
@Override
public Page<TargetFilterQuery> findByRsql(final Pageable pageable, final String rsqlFilter) {
List<Specification<JpaTargetFilterQuery>> specList = Collections.emptyList();
if (!StringUtils.isEmpty(rsqlFilter)) {
specList = Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlFilter,
TargetFilterQueryFields.class, virtualPropertyReplacer, database));
}
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable);
final List<Specification<JpaTargetFilterQuery>> specList = !StringUtils.isEmpty(rsqlFilter)
? Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlFilter,
TargetFilterQueryFields.class, virtualPropertyReplacer, database))
: Collections.emptyList();
return JpaManagementHelper.findAllWithCountBySpec(targetFilterQueryRepository, pageable, specList);
}
@Override
public Page<TargetFilterQuery> findByQuery(final Pageable pageable, final String query) {
List<Specification<JpaTargetFilterQuery>> specList = Collections.emptyList();
if (!StringUtils.isEmpty(query)) {
specList = Collections.singletonList(TargetFilterQuerySpecification.equalsQuery(query));
}
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable);
public Slice<TargetFilterQuery> findByQuery(final Pageable pageable, final String query) {
final List<Specification<JpaTargetFilterQuery>> specList = !StringUtils.isEmpty(query)
? Collections.singletonList(TargetFilterQuerySpecification.equalsQuery(query))
: Collections.emptyList();
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable, specList);
}
@Override
public Slice<TargetFilterQuery> findByAutoAssignDistributionSetId(@NotNull final Pageable pageable,
final long setId) {
final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId);
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable,
Collections.singletonList(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet)));
}
@Override
public Page<TargetFilterQuery> findByAutoAssignDSAndRsql(final Pageable pageable, final long setId,
final String rsqlFilter) {
final List<Specification<JpaTargetFilterQuery>> specList = Lists.newArrayListWithExpectedSize(2);
final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId);
final List<Specification<JpaTargetFilterQuery>> specList = Lists.newArrayListWithExpectedSize(2);
specList.add(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet));
if (!StringUtils.isEmpty(rsqlFilter)) {
specList.add(RSQLUtility.buildRsqlSpecification(rsqlFilter, TargetFilterQueryFields.class,
virtualPropertyReplacer, database));
}
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable);
return JpaManagementHelper.findAllWithCountBySpec(targetFilterQueryRepository, pageable, specList);
}
@Override
public Page<TargetFilterQuery> findWithAutoAssignDS(final Pageable pageable) {
final List<Specification<JpaTargetFilterQuery>> specList = Collections
.singletonList(TargetFilterQuerySpecification.withAutoAssignDS());
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable);
}
private Page<JpaTargetFilterQuery> findTargetFilterQueryByCriteriaAPI(final Pageable pageable,
final List<Specification<JpaTargetFilterQuery>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return targetFilterQueryRepository.findAll(pageable);
}
final Specification<JpaTargetFilterQuery> specs = SpecificationsBuilder.combineWithAnd(specList);
return targetFilterQueryRepository.findAll(specs, pageable);
public Slice<TargetFilterQuery> findWithAutoAssignDS(final Pageable pageable) {
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, pageable,
Collections.singletonList(TargetFilterQuerySpecification.withAutoAssignDS()));
}
@Override

View File

@@ -8,9 +8,6 @@
*/
package org.eclipse.hawkbit.repository.jpa;
import static org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications.orderedByLinkedDistributionSet;
import com.google.common.collect.Lists;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
@@ -21,11 +18,14 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.MapJoin;
import javax.persistence.criteria.Root;
import javax.validation.constraints.NotEmpty;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
@@ -53,7 +53,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
import org.eclipse.hawkbit.repository.jpa.model.TargetMetadataCompositeKey;
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -73,7 +72,6 @@ import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
@@ -82,10 +80,11 @@ import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import com.google.common.collect.Lists;
/**
* JPA implementation of {@link TargetManagement}.
*
@@ -185,7 +184,7 @@ public class JpaTargetManagement implements TargetManagement {
assertMetaDataQuota(target.getId(), md.size());
final JpaTarget updatedTarget = touch(target);
final JpaTarget updatedTarget = JpaManagementHelper.touch(entityManager, targetRepository, target);
final List<TargetMetadata> createdMetadata = Collections.unmodifiableList(md.stream()
.map(meta -> targetMetadataRepository
@@ -212,21 +211,6 @@ public class JpaTargetManagement implements TargetManagement {
TargetMetadata.class, Target.class, targetMetadataRepository::countByTargetId);
}
private JpaTarget touch(final JpaTarget target) {
// merge base target so optLockRevision gets updated and audit
// log written because modifying metadata is modifying the base
// target itself for auditing purposes.
final JpaTarget result = entityManager.merge(target);
result.setLastModifiedAt(0L);
return targetRepository.save(result);
}
private JpaTarget touch(final String controllerId) {
return touch(getByControllerIdAndThrowIfNotFound(controllerId));
}
@Override
@Transactional
@Retryable(include = {
@@ -240,7 +224,8 @@ public class JpaTargetManagement implements TargetManagement {
updatedMetadata.setValue(md.getValue());
// touch it to update the lock revision because we are modifying the
// target indirectly
final JpaTarget target = touch(controllerId);
final JpaTarget target = JpaManagementHelper.touch(entityManager, targetRepository,
getByControllerIdAndThrowIfNotFound(controllerId));
final JpaTargetMetadata matadata = targetMetadataRepository.save(updatedMetadata);
// target update event is set to ignore "lastModifiedAt" field so it is
// not send automatically within the touch() method
@@ -257,7 +242,8 @@ public class JpaTargetManagement implements TargetManagement {
final JpaTargetMetadata metadata = (JpaTargetMetadata) getMetaDataByControllerId(controllerId, key)
.orElseThrow(() -> new EntityNotFoundException(TargetMetadata.class, controllerId, key));
final JpaTarget target = touch(controllerId);
final JpaTarget target = JpaManagementHelper.touch(entityManager, targetRepository,
getByControllerIdAndThrowIfNotFound(controllerId));
targetMetadataRepository.deleteById(metadata.getId());
// target update event is set to ignore "lastModifiedAt" field so it is
// not send automatically within the touch() method
@@ -269,32 +255,32 @@ public class JpaTargetManagement implements TargetManagement {
public Page<TargetMetadata> findMetaDataByControllerId(final Pageable pageable, final String controllerId) {
final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId();
return convertMdPage(
targetMetadataRepository
.findAll(
(Specification<JpaTargetMetadata>) (root, query, cb) -> cb
.equal(root.get(JpaTargetMetadata_.target).get(JpaTarget_.id), targetId),
pageable),
pageable);
return JpaManagementHelper.findAllWithCountBySpec(targetMetadataRepository, pageable,
Collections.singletonList(metadataByTargetIdSpec(targetId)));
}
private static Page<TargetMetadata> convertMdPage(final Page<JpaTargetMetadata> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
private Specification<JpaTargetMetadata> metadataByTargetIdSpec(final Long targetId) {
return (root, query, cb) -> cb.equal(root.get(JpaTargetMetadata_.target).get(JpaTarget_.id), targetId);
}
@Override
public long countMetaDataByControllerId(@NotEmpty final String controllerId) {
final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId();
return JpaManagementHelper.countBySpec(targetMetadataRepository,
Collections.singletonList(metadataByTargetIdSpec(targetId)));
}
@Override
public Page<TargetMetadata> findMetaDataByControllerIdAndRsql(final Pageable pageable, final String controllerId,
final String rsqlParam) {
final Long targetId = getByControllerIdAndThrowIfNotFound(controllerId).getId();
final Specification<JpaTargetMetadata> spec = RSQLUtility.buildRsqlSpecification(rsqlParam,
TargetMetadataFields.class, virtualPropertyReplacer, database);
final List<Specification<JpaTargetMetadata>> specList = Arrays.asList(RSQLUtility
.buildRsqlSpecification(rsqlParam, TargetMetadataFields.class, virtualPropertyReplacer, database),
metadataByTargetIdSpec(targetId));
return convertMdPage(targetMetadataRepository.findAll((Specification<JpaTargetMetadata>) (root, query, cb) -> cb
.and(cb.equal(root.get(JpaTargetMetadata_.target).get(JpaTarget_.id), targetId),
spec.toPredicate(root, query, cb)),
pageable), pageable);
return JpaManagementHelper.findAllWithCountBySpec(targetMetadataRepository, pageable, specList);
}
@Override
@@ -306,7 +292,7 @@ public class JpaTargetManagement implements TargetManagement {
@Override
public Slice<Target> findAll(final Pageable pageable) {
return convertPage(targetRepository.findAllWithoutCount(pageable), pageable);
return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, null);
}
@Override
@@ -314,18 +300,16 @@ public class JpaTargetManagement implements TargetManagement {
final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId)
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId));
return findTargetsBySpec(RSQLUtility.buildRsqlSpecification(targetFilterQuery.getQuery(), TargetFields.class,
virtualPropertyReplacer, database), pageable);
return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable,
Collections.singletonList(RSQLUtility.buildRsqlSpecification(targetFilterQuery.getQuery(),
TargetFields.class, virtualPropertyReplacer, database)));
}
@Override
public Page<Target> findByRsql(final Pageable pageable, final String targetFilterQuery) {
return findTargetsBySpec(RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
virtualPropertyReplacer, database), pageable);
}
private Page<Target> findTargetsBySpec(final Specification<JpaTarget> spec, final Pageable pageable) {
return convertPage(targetRepository.findAll(spec, pageable), pageable);
public Slice<Target> findByRsql(final Pageable pageable, final String targetFilterQuery) {
return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable,
Collections.singletonList(RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
virtualPropertyReplacer, database)));
}
@Override
@@ -385,8 +369,8 @@ public class JpaTargetManagement implements TargetManagement {
public Page<Target> findByAssignedDistributionSet(final Pageable pageReq, final long distributionSetID) {
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetID);
return convertPage(targetRepository
.findAll(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId()), pageReq), pageReq);
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq,
Collections.singletonList(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId())));
}
@Override
@@ -394,31 +378,19 @@ public class JpaTargetManagement implements TargetManagement {
final String rsqlParam) {
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetID);
final Specification<JpaTarget> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class,
virtualPropertyReplacer, database);
final List<Specification<JpaTarget>> specList = Arrays.asList(
RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database),
TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId()));
return convertPage(
targetRepository
.findAll((Specification<JpaTarget>) (root, query,
cb) -> cb.and(TargetSpecifications.hasAssignedDistributionSet(validDistSet.getId())
.toPredicate(root, query, cb), spec.toPredicate(root, query, cb)),
pageReq),
pageReq);
}
public static Page<Target> convertPage(final Page<JpaTarget> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
private static Slice<Target> convertPage(final Slice<JpaTarget> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, 0);
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq, specList);
}
@Override
public Page<Target> findByInstalledDistributionSet(final Pageable pageReq, final long distributionSetID) {
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetID);
return convertPage(targetRepository
.findAll(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId()), pageReq), pageReq);
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq,
Collections.singletonList(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId())));
}
@Override
@@ -426,34 +398,29 @@ public class JpaTargetManagement implements TargetManagement {
final String rsqlParam) {
final DistributionSet validDistSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
final Specification<JpaTarget> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class,
virtualPropertyReplacer, database);
final List<Specification<JpaTarget>> specList = Arrays.asList(
RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database),
TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId()));
return convertPage(
targetRepository
.findAll((Specification<JpaTarget>) (root, query,
cb) -> cb.and(TargetSpecifications.hasInstalledDistributionSet(validDistSet.getId())
.toPredicate(root, query, cb), spec.toPredicate(root, query, cb)),
pageable),
pageable);
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, specList);
}
@Override
public Page<Target> findByUpdateStatus(final Pageable pageable, final TargetUpdateStatus status) {
return convertPage(targetRepository.findAll(TargetSpecifications.hasTargetUpdateStatus(status), pageable),
pageable);
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable,
Collections.singletonList(TargetSpecifications.hasTargetUpdateStatus(status)));
}
@Override
public Slice<Target> findByFilters(final Pageable pageable, final FilterParams filterParams) {
final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams);
return findByCriteriaAPI(pageable, specList);
return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, specList);
}
@Override
public long countByFilters(Collection<TargetUpdateStatus> status, Boolean overdueState, String searchText,
Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag,
String... tagNames) {
public long countByFilters(final Collection<TargetUpdateStatus> status, final Boolean overdueState,
final String searchText, final Long installedOrAssignedDistributionSetId,
final Boolean selectTargetWithNoTag, final String... tagNames) {
return countByFilters(new FilterParams(status, overdueState, searchText, installedOrAssignedDistributionSetId,
selectTargetWithNoTag, tagNames));
}
@@ -461,7 +428,7 @@ public class JpaTargetManagement implements TargetManagement {
@Override
public long countByFilters(final FilterParams filterParams) {
final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams);
return countByCriteriaAPI(specList);
return JpaManagementHelper.countBySpec(targetRepository, specList);
}
private List<Specification<JpaTarget>> buildSpecificationList(final FilterParams filterParams) {
@@ -479,8 +446,7 @@ public class JpaTargetManagement implements TargetManagement {
specList.add(TargetSpecifications.hasInstalledOrAssignedDistributionSet(validDistSet.getId()));
}
if (!StringUtils.isEmpty(filterParams.getFilterBySearchText())) {
specList.add(TargetSpecifications
.likeIdOrNameOrDescriptionOrAttributeValue(filterParams.getFilterBySearchText()));
specList.add(TargetSpecifications.likeControllerIdOrName(filterParams.getFilterBySearchText()));
}
if (hasTagsFilterActive(filterParams)) {
specList.add(TargetSpecifications.hasTags(filterParams.getFilterByTagNames(),
@@ -512,23 +478,6 @@ public class JpaTargetManagement implements TargetManagement {
return Boolean.TRUE.equals(filterParams.getSelectTargetWithNoTargetType());
}
private Slice<Target> findByCriteriaAPI(final Pageable pageable, final List<Specification<JpaTarget>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return convertPage(targetRepository.findAllWithoutCount(pageable), pageable);
}
return convertPage(
targetRepository.findAllWithoutCount(SpecificationsBuilder.combineWithAnd(specList), pageable),
pageable);
}
private Long countByCriteriaAPI(final List<Specification<JpaTarget>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return targetRepository.count();
}
return targetRepository.count(SpecificationsBuilder.combineWithAnd(specList));
}
@Override
@Transactional
@Retryable(include = {
@@ -585,8 +534,8 @@ public class JpaTargetManagement implements TargetManagement {
targetsWithoutSameType.forEach(target -> target.setTargetType(type));
final TargetTypeAssignmentResult result = new TargetTypeAssignmentResult(targetsWithSameType.size(),
Collections
.unmodifiableList(targetsWithoutSameType.stream().map(targetRepository::save).collect(Collectors.toList())),
Collections.unmodifiableList(
targetsWithoutSameType.stream().map(targetRepository::save).collect(Collectors.toList())),
Collections.emptyList(), type);
// no reason to persist the type
@@ -613,8 +562,8 @@ public class JpaTargetManagement implements TargetManagement {
.unmodifiableList(allTargets.stream().map(targetRepository::save).collect(Collectors.toList())), null);
}
private List<JpaTarget> findTargetsByInSpecification(Collection<String> controllerIds,
Specification<JpaTarget> specification) {
private List<JpaTarget> findTargetsByInSpecification(final Collection<String> controllerIds,
final Specification<JpaTarget> specification) {
return Lists.partition(new ArrayList<>(controllerIds), Constants.MAX_ENTRIES_IN_STATEMENT).stream()
.map(ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids).and(specification)))
.flatMap(List::stream).collect(Collectors.toList());
@@ -690,30 +639,14 @@ public class JpaTargetManagement implements TargetManagement {
@Override
public Slice<Target> findByFilterOrderByLinkedDistributionSet(final Pageable pageable,
final long orderByDistributionId, final FilterParams filterParams) {
Specification<JpaTarget> orderedFilterSpec = combineFiltersAndDsOrder(orderByDistributionId, filterParams);
// remove default sort from pageable to not overwrite sorted spec
final OffsetBasedPageRequest unsortedPage = new OffsetBasedPageRequest(pageable.getOffset(),
pageable.getPageSize(), Sort.unsorted());
return convertPage(targetRepository.findAllWithoutCount(orderedFilterSpec, unsortedPage), unsortedPage);
}
/**
* Applies orderedByLinkedDistributionSet spec for order and adds additional
* specs based on filters
*
* @param orderByDistributionId
* distribution set used for order
* @param filterParams
* filters to generate additional specs for
* @return specification combining order and filter specs
*/
private Specification<JpaTarget> combineFiltersAndDsOrder(final long orderByDistributionId,
final FilterParams filterParams) {
Specification<JpaTarget> orderedFilterSpec = orderedByLinkedDistributionSet(orderByDistributionId);
for (Specification<JpaTarget> spec : buildSpecificationList(filterParams)) {
orderedFilterSpec = orderedFilterSpec.and(spec);
}
return orderedFilterSpec;
final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams);
specList.add(TargetSpecifications.orderedByLinkedDistributionSet(orderByDistributionId));
return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, unsortedPage, specList);
}
@Override
@@ -739,55 +672,52 @@ public class JpaTargetManagement implements TargetManagement {
}
@Override
public Page<Target> findByTargetFilterQueryAndNonDSAndCompatible(final Pageable pageRequest,
public Slice<Target> findByTargetFilterQueryAndNonDSAndCompatible(final Pageable pageRequest,
final long distributionSetId, final String targetFilterQuery) {
final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
final Long distSetTypeId = jpaDistributionSet.getType().getId();
final Specification<JpaTarget> spec = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
virtualPropertyReplacer, database);
final Specification<JpaTarget> dsNotInActions = TargetSpecifications
.hasNotDistributionSetInActions(distributionSetId);
final Specification<JpaTarget> isCompatibleWithDsType = TargetSpecifications
.isCompatibleWithDistributionSetType(distSetTypeId);
final List<Specification<JpaTarget>> specList = Arrays.asList(
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer,
database),
TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId));
return findTargetsBySpec(spec.and(dsNotInActions).and(isCompatibleWithDsType), pageRequest);
return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageRequest, specList);
}
@Override
public Page<Target> findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible(final Pageable pageRequest,
public Slice<Target> findByTargetFilterQueryAndNotInRolloutGroupsAndCompatible(final Pageable pageRequest,
final Collection<Long> groups, final String targetFilterQuery, final DistributionSetType dsType) {
final List<Specification<JpaTarget>> specList = Arrays.asList(
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer,
database),
TargetSpecifications.isNotInRolloutGroups(groups),
TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()));
final Specification<JpaTarget> spec = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
virtualPropertyReplacer, database);
final Specification<JpaTarget> notInRolloutGroups = TargetSpecifications.isNotInRolloutGroups(groups);
final Specification<JpaTarget> isCompatibleWithDsType = TargetSpecifications
.isCompatibleWithDistributionSetType(dsType.getId());
return findTargetsBySpec((spec.and(notInRolloutGroups).and(isCompatibleWithDsType)), pageRequest);
return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageRequest, specList);
}
@Override
public Page<Target> findByInRolloutGroupWithoutAction(final Pageable pageRequest, final long group) {
public Slice<Target> findByInRolloutGroupWithoutAction(final Pageable pageRequest, final long group) {
if (!rolloutGroupRepository.existsById(group)) {
throw new EntityNotFoundException(RolloutGroup.class, group);
}
return findTargetsBySpec(
(root, cq, cb) -> TargetSpecifications.hasNoActionInRolloutGroup(group).toPredicate(root, cq, cb),
pageRequest);
return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageRequest,
Collections.singletonList(TargetSpecifications.hasNoActionInRolloutGroup(group)));
}
@Override
public long countByRsqlAndNotInRolloutGroupsAndCompatible(final Collection<Long> groups,
final String targetFilterQuery, final DistributionSetType dsType) {
final Specification<JpaTarget> spec = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
virtualPropertyReplacer, database);
final List<Specification<JpaTarget>> specList = Arrays.asList(spec,
final List<Specification<JpaTarget>> specList = Arrays.asList(
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer,
database),
TargetSpecifications.isNotInRolloutGroups(groups),
TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()));
return countByCriteriaAPI(specList);
return JpaManagementHelper.countBySpec(targetRepository, specList);
}
@Override
@@ -795,13 +725,13 @@ public class JpaTargetManagement implements TargetManagement {
final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
final Long distSetTypeId = jpaDistributionSet.getType().getId();
final Specification<JpaTarget> spec = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
virtualPropertyReplacer, database);
final List<Specification<JpaTarget>> specList = Arrays.asList(spec,
final List<Specification<JpaTarget>> specList = Arrays.asList(
RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer,
database),
TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId));
return countByCriteriaAPI(specList);
return JpaManagementHelper.countBySpec(targetRepository, specList);
}
@Override
@@ -825,7 +755,8 @@ public class JpaTargetManagement implements TargetManagement {
public Page<Target> findByTag(final Pageable pageable, final long tagId) {
throwEntityNotFoundExceptionIfTagDoesNotExist(tagId);
return convertPage(targetRepository.findAll(TargetSpecifications.hasTag(tagId), pageable), pageable);
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable,
Collections.singletonList(TargetSpecifications.hasTag(tagId)));
}
private void throwEntityNotFoundExceptionIfTagDoesNotExist(final Long tagId) {
@@ -836,15 +767,13 @@ public class JpaTargetManagement implements TargetManagement {
@Override
public Page<Target> findByRsqlAndTag(final Pageable pageable, final String rsqlParam, final long tagId) {
throwEntityNotFoundExceptionIfTagDoesNotExist(tagId);
final Specification<JpaTarget> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class,
virtualPropertyReplacer, database);
final List<Specification<JpaTarget>> specList = Arrays.asList(
RSQLUtility.buildRsqlSpecification(rsqlParam, TargetFields.class, virtualPropertyReplacer, database),
TargetSpecifications.hasTag(tagId));
return convertPage(targetRepository.findAll((Specification<JpaTarget>) (root, query, cb) -> cb.and(
TargetSpecifications.hasTag(tagId).toPredicate(root, query, cb), spec.toPredicate(root, query, cb)),
pageable), pageable);
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageable, specList);
}
@Override
@@ -852,23 +781,22 @@ public class JpaTargetManagement implements TargetManagement {
final TargetFilterQuery targetFilterQuery = targetFilterQueryRepository.findById(targetFilterQueryId)
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId));
final Specification<JpaTarget> specs = RSQLUtility.buildRsqlSpecification(targetFilterQuery.getQuery(),
TargetFields.class, virtualPropertyReplacer, database);
return targetRepository.count(specs);
return countByRsql(targetFilterQuery.getQuery());
}
@Override
public long countByRsql(final String targetFilterQuery) {
final Specification<JpaTarget> specs = RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
virtualPropertyReplacer, database);
return targetRepository.count(specs);
return JpaManagementHelper.countBySpec(targetRepository, Collections.singletonList(RSQLUtility
.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database)));
}
@Override
public long countByRsqlAndCompatible(final String targetFilterQuery, final Long dsTypeId) {
final Specification<JpaTarget> rsqlSpec = RSQLUtility.buildRsqlSpecification(targetFilterQuery,
TargetFields.class, virtualPropertyReplacer, database);
return targetRepository.count(rsqlSpec.and(TargetSpecifications.isCompatibleWithDistributionSetType(dsTypeId)));
final List<Specification<JpaTarget>> specList = Arrays.asList(RSQLUtility
.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database),
TargetSpecifications.isCompatibleWithDistributionSetType(dsTypeId));
return JpaManagementHelper.countBySpec(targetRepository, specList);
}
@Override
@@ -925,8 +853,8 @@ public class JpaTargetManagement implements TargetManagement {
@Override
public Page<Target> findByControllerAttributesRequested(final Pageable pageReq) {
return convertPage(targetRepository.findAll(TargetSpecifications.hasRequestControllerAttributesTrue(), pageReq),
pageReq);
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageReq,
Collections.singletonList(TargetSpecifications.hasRequestControllerAttributesTrue()));
}
}

View File

@@ -31,9 +31,7 @@ import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
@@ -106,14 +104,8 @@ public class JpaTargetTagManagement implements TargetTagManagement {
@Override
public Page<TargetTag> findByRsql(final Pageable pageable, final String rsqlParam) {
final Specification<JpaTargetTag> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TagFields.class, virtualPropertyReplacer,
database);
return convertTPage(targetTagRepository.findAll(spec, pageable), pageable);
}
private static Page<TargetTag> convertTPage(final Page<JpaTargetTag> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
return JpaManagementHelper.findAllWithCountBySpec(targetTagRepository, pageable, Collections.singletonList(
RSQLUtility.buildRsqlSpecification(rsqlParam, TagFields.class, virtualPropertyReplacer, database)));
}
@Override
@@ -140,7 +132,7 @@ public class JpaTargetTagManagement implements TargetTagManagement {
@Override
public Optional<TargetTag> get(final long id) {
return targetTagRepository.findById(id).map(tt -> (TargetTag) tt);
return targetTagRepository.findById(id).map(TargetTag.class::cast);
}
@Override
@@ -150,7 +142,7 @@ public class JpaTargetTagManagement implements TargetTagManagement {
@Override
public Page<TargetTag> findAll(final Pageable pageable) {
return convertTPage(targetTagRepository.findAll(pageable), pageable);
return JpaManagementHelper.findAllWithCountBySpec(targetTagRepository, pageable, null);
}
@Override
@@ -159,6 +151,7 @@ public class JpaTargetTagManagement implements TargetTagManagement {
throw new EntityNotFoundException(Target.class, controllerId);
}
return convertTPage(targetTagRepository.findAll(TagSpecification.ofTarget(controllerId), pageable), pageable);
return JpaManagementHelper.findAllWithCountBySpec(targetTagRepository, pageable,
Collections.singletonList(TagSpecification.ofTarget(controllerId)));
}
}

View File

@@ -8,6 +8,12 @@
*/
package org.eclipse.hawkbit.repository.jpa;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.repository.QuotaManagement;
import org.eclipse.hawkbit.repository.TargetTypeFields;
import org.eclipse.hawkbit.repository.TargetTypeManagement;
@@ -29,21 +35,14 @@ import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.domain.Slice;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* JPA implementation of {@link TargetTypeManagement}.
*
@@ -95,6 +94,11 @@ public class JpaTargetTypeManagement implements TargetTypeManagement {
return targetTypeRepository.count();
}
@Override
public long countByName(final String name) {
return targetTypeRepository.countByName(name);
}
@Override
@Transactional
@Retryable(include = {
@@ -127,21 +131,21 @@ public class JpaTargetTypeManagement implements TargetTypeManagement {
}
@Override
public Page<TargetType> findAll(final Pageable pageable) {
return convertPage(targetTypeRepository.findAll(pageable), pageable);
public Slice<TargetType> findAll(final Pageable pageable) {
return JpaManagementHelper.findAllWithoutCountBySpec(targetTypeRepository, pageable, null);
}
@Override
public Page<TargetType> findByRsql(final Pageable pageable, final String rsqlParam) {
final Specification<JpaTargetType> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, TargetTypeFields.class,
virtualPropertyReplacer, database);
return convertPage(targetTypeRepository.findAll(spec, pageable), pageable);
return JpaManagementHelper.findAllWithCountBySpec(targetTypeRepository, pageable,
Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlParam, TargetTypeFields.class,
virtualPropertyReplacer, database)));
}
@Override
public Page<TargetType> findByName(Pageable pageable, String name) {
return convertPage(targetTypeRepository.findAll(TargetTypeSpecification.likeName(name), pageable), pageable);
public Slice<TargetType> findByName(final Pageable pageable, final String name) {
return JpaManagementHelper.findAllWithoutCountBySpec(targetTypeRepository, pageable,
Collections.singletonList(TargetTypeSpecification.likeName(name)));
}
@Override
@@ -258,9 +262,4 @@ public class JpaTargetTypeManagement implements TargetTypeManagement {
QuotaHelper.assertAssignmentQuota(id, requested, quotaManagement.getMaxDistributionSetTypesPerTargetType(),
DistributionSetType.class, TargetType.class, targetTypeRepository::countDsSetTypesById);
}
private static Page<TargetType> convertPage(final Page<JpaTargetType> findAll, final Pageable pageable) {
return new PageImpl<>(Collections.unmodifiableList(findAll.getContent()), pageable, findAll.getTotalElements());
}
}

View File

@@ -8,6 +8,12 @@
*/
package org.eclipse.hawkbit.repository.jpa;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetTypeSpecification;
import org.eclipse.hawkbit.repository.model.TargetType;
@@ -23,12 +29,6 @@ import org.springframework.data.repository.query.Param;
import org.springframework.lang.NonNull;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
/**
* {@link PagingAndSortingRepository} for {@link JpaTargetType}.
*
@@ -42,23 +42,24 @@ public interface TargetTypeRepository
*
* Calls version based on spec to allow injecting further specs
*
* @param id id to filter for
* @param id
* id to filter for
* @return {@link Optional} of {@link TargetType}
*/
@Override
@NonNull
default Optional<JpaTargetType> findById(@NonNull Long id) {
default Optional<JpaTargetType> findById(@NonNull final Long id) {
return this.findOne(Specification.where(TargetTypeSpecification.hasId(id)));
}
/**
* @param ids
* List of ID
* List of ID
* @return Target type list
*/
@Override
@NonNull
default List<JpaTargetType> findAllById(Iterable<Long> ids) {
default List<JpaTargetType> findAllById(final Iterable<Long> ids) {
final List<Long> collectedIds = StreamSupport.stream(ids.spliterator(), true).collect(Collectors.toList());
return this.findAll(Specification.where(TargetTypeSpecification.hasIdIn(collectedIds)));
}
@@ -92,12 +93,13 @@ public interface TargetTypeRepository
*
* Calls version with (empty) spec to allow injecting further specs
*
* @param sort instructions to sort result by
* @param sort
* instructions to sort result by
* @return {@link List} of {@link TargetType}s
*/
@Override
@NonNull
default Iterable<JpaTargetType> findAll(@NonNull Sort sort) {
default Iterable<JpaTargetType> findAll(@NonNull final Sort sort) {
return this.findAll(Specification.where(null), sort);
}
@@ -106,35 +108,40 @@ public interface TargetTypeRepository
*
* Calls version with (empty) spec to allow injecting further specs
*
* @param pageable paging context
* @param pageable
* paging context
* @return {@link List} of {@link TargetType}s
*/
@Override
@NonNull
default Page<JpaTargetType> findAll(@NonNull Pageable pageable) {
default Page<JpaTargetType> findAll(@NonNull final Pageable pageable) {
return this.findAll(Specification.where(null), pageable);
}
/**
* Checks whether {@link TargetType} in the repository matching an id exists or not.
* Checks whether {@link TargetType} 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
* @param id
* id to check for
* @return true if TargetType with id exists
*/
@Override
default boolean existsById(@NonNull Long id) {
default boolean existsById(@NonNull final Long id) {
return this.exists(TargetTypeSpecification.hasId(id));
}
/**
* Checks whether {@link TargetType} in the repository matching a spec exists or not.
* Checks whether {@link TargetType} in the repository matching a spec
* exists or not.
*
* @param spec to check for existence
* @param spec
* to check for existence
* @return true if target with id exists
*/
default boolean exists(@NonNull Specification<JpaTargetType> spec) {
default boolean exists(@NonNull final Specification<JpaTargetType> spec) {
return this.count(spec) > 0;
}
@@ -152,7 +159,7 @@ public interface TargetTypeRepository
/**
* @param tenant
* Tenant
* Tenant
*/
@Modifying
@Transactional
@@ -169,7 +176,7 @@ public interface TargetTypeRepository
* @return all {@link TargetType}s in the repository with given
* {@link TargetType#getName()}
*/
default List<JpaTargetType> findByDsType(@Param("id") Long dsTypeId) {
default List<JpaTargetType> findByDsType(@Param("id") final Long dsTypeId) {
return this.findAll(Specification.where(TargetTypeSpecification.hasDsSetType(dsTypeId)));
}
@@ -180,7 +187,18 @@ public interface TargetTypeRepository
* @return all {@link TargetType}s in the repository with given
* {@link TargetType#getName()}
*/
default Optional<JpaTargetType> findByName(String name){
default Optional<JpaTargetType> findByName(final String name) {
return this.findOne(Specification.where(TargetTypeSpecification.hasName(name)));
};
}
/**
* Count number of {@link TargetType}s in the repository by name.
*
* @param name
* target type name
* @return number of targetTypes in the repository by name
*/
default long countByName(final String name) {
return this.count(TargetTypeSpecification.hasName(name));
}
}

View File

@@ -23,9 +23,9 @@ import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.util.StringUtils;
@@ -38,11 +38,11 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAutoAssignExecutor.class);
/**
* The message which is added to the action status when a distribution set is
* assigned to an target. First %s is the name of the target filter.
* The message which is added to the action status when a distribution set
* is assigned to an target. First %s is the name of the target filter.
*/
private static final String ACTION_MESSAGE = "Auto assignment by target filter: %s";
/**
* Maximum for target filter queries with auto assign DS activated.
*/
@@ -94,7 +94,7 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor {
}
protected void forEachFilterWithAutoAssignDS(final Consumer<TargetFilterQuery> consumer) {
Page<TargetFilterQuery> filterQueries;
Slice<TargetFilterQuery> filterQueries;
Pageable query = PageRequest.of(0, PAGE_SIZE);
do {
@@ -117,8 +117,8 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor {
}
/**
* Runs target assignments within a dedicated transaction for a given list of
* controllerIDs
* Runs target assignments within a dedicated transaction for a given list
* of controllerIDs
*
* @param targetFilterQuery
* the target filter query
@@ -146,8 +146,8 @@ public abstract class AbstractAutoAssignExecutor implements AutoAssignExecutor {
}
/**
* Creates a list of {@link DeploymentRequest} for given list of controllerIds
* and {@link TargetFilterQuery}
* Creates a list of {@link DeploymentRequest} for given list of
* controllerIds and {@link TargetFilterQuery}
*
* @param controllerIds
* list of controllerIds

View File

@@ -13,6 +13,7 @@ import java.util.Collection;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.ListJoin;
import javax.persistence.criteria.Path;
@@ -23,12 +24,11 @@ import javax.persistence.criteria.SetJoin;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag_;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType_;
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.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.CollectionUtils;
@@ -52,7 +52,7 @@ public final class DistributionSetSpecification {
* @return the {@link DistributionSet} {@link Specification}
*/
public static Specification<JpaDistributionSet> isDeleted(final Boolean isDeleted) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(JpaDistributionSet_.deleted), isDeleted);
return (dsRoot, query, cb) -> cb.equal(dsRoot.<Boolean> get(JpaDistributionSet_.deleted), isDeleted);
}
@@ -66,7 +66,7 @@ public final class DistributionSetSpecification {
* @return the {@link DistributionSet} {@link Specification}
*/
public static Specification<JpaDistributionSet> isCompleted(final Boolean isCompleted) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(JpaDistributionSet_.complete), isCompleted);
return (dsRoot, query, cb) -> cb.equal(dsRoot.<Boolean> get(JpaDistributionSet_.complete), isCompleted);
}
@@ -80,7 +80,7 @@ public final class DistributionSetSpecification {
* @return the {@link DistributionSet} {@link Specification}
*/
public static Specification<JpaDistributionSet> isValid(final Boolean isValid) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(JpaDistributionSet_.valid), isValid);
return (dsRoot, query, cb) -> cb.equal(dsRoot.<Boolean> get(JpaDistributionSet_.valid), isValid);
}
@@ -93,10 +93,10 @@ public final class DistributionSetSpecification {
* @return the {@link DistributionSet} {@link Specification}
*/
public static Specification<JpaDistributionSet> byId(final Long distid) {
return (targetRoot, query, cb) -> {
final Predicate predicate = cb.equal(targetRoot.<Long> get(JpaDistributionSet_.id), distid);
targetRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT);
targetRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT);
return (dsRoot, query, cb) -> {
final Predicate predicate = cb.equal(dsRoot.<Long> get(JpaDistributionSet_.id), distid);
dsRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT);
dsRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT);
query.distinct(true);
return predicate;
@@ -112,31 +112,16 @@ public final class DistributionSetSpecification {
* @return the {@link DistributionSet} {@link Specification}
*/
public static Specification<JpaDistributionSet> byIds(final Collection<Long> distids) {
return (targetRoot, query, cb) -> {
final Predicate predicate = targetRoot.<Long> get(JpaDistributionSet_.id).in(distids);
targetRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT);
targetRoot.fetch(JpaDistributionSet_.tags, JoinType.LEFT);
targetRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT);
return (dsRoot, query, cb) -> {
final Predicate predicate = dsRoot.<Long> get(JpaDistributionSet_.id).in(distids);
dsRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT);
dsRoot.fetch(JpaDistributionSet_.tags, JoinType.LEFT);
dsRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT);
query.distinct(true);
return predicate;
};
}
/**
* {@link Specification} for retrieving {@link DistributionSet}s by "like
* name or like description or like version".
*
* @param subString
* to be filtered on
* @return the {@link DistributionSet} {@link Specification}
*/
public static Specification<JpaDistributionSet> likeNameOrDescriptionOrVersion(final String subString) {
return (targetRoot, query, cb) -> cb.or(
cb.like(cb.lower(targetRoot.<String> get(JpaDistributionSet_.name)), subString.toLowerCase()),
cb.like(cb.lower(targetRoot.<String> get(JpaDistributionSet_.version)), subString.toLowerCase()),
cb.like(cb.lower(targetRoot.<String> get(JpaDistributionSet_.description)), subString.toLowerCase()));
}
/**
* {@link Specification} for retrieving {@link DistributionSet}s by "like
* name and like version".
@@ -148,9 +133,9 @@ public final class DistributionSetSpecification {
* @return the {@link DistributionSet} {@link Specification}
*/
public static Specification<JpaDistributionSet> likeNameAndVersion(final String name, final String version) {
return (targetRoot, query, cb) -> cb.and(
cb.like(cb.lower(targetRoot.<String> get(JpaDistributionSet_.name)), name.toLowerCase()),
cb.like(cb.lower(targetRoot.<String> get(JpaDistributionSet_.version)), version.toLowerCase()));
return (dsRoot, query, cb) -> cb.and(
cb.like(cb.lower(dsRoot.<String> get(JpaDistributionSet_.name)), name.toLowerCase()),
cb.like(cb.lower(dsRoot.<String> get(JpaDistributionSet_.version)), version.toLowerCase()));
}
/**
@@ -165,16 +150,16 @@ public final class DistributionSetSpecification {
*/
public static Specification<JpaDistributionSet> hasTags(final Collection<String> tagNames,
final Boolean selectDSWithNoTag) {
return (targetRoot, query, cb) -> {
final Predicate predicate = getHasTagsPredicate(targetRoot, cb, selectDSWithNoTag, tagNames);
return (dsRoot, query, cb) -> {
final Predicate predicate = getHasTagsPredicate(dsRoot, cb, selectDSWithNoTag, tagNames);
query.distinct(true);
return predicate;
};
}
private static Predicate getHasTagsPredicate(final Root<JpaDistributionSet> targetRoot, final CriteriaBuilder cb,
private static Predicate getHasTagsPredicate(final Root<JpaDistributionSet> dsRoot, final CriteriaBuilder cb,
final Boolean selectDSWithNoTag, final Collection<String> tagNames) {
final SetJoin<JpaDistributionSet, JpaDistributionSetTag> tags = targetRoot.join(JpaDistributionSet_.tags,
final SetJoin<JpaDistributionSet, JpaDistributionSetTag> tags = dsRoot.join(JpaDistributionSet_.tags,
JoinType.LEFT);
final Path<String> exp = tags.get(JpaDistributionSetTag_.name);
@@ -210,9 +195,9 @@ public final class DistributionSetSpecification {
*/
public static Specification<JpaDistributionSet> equalsNameAndVersionIgnoreCase(final String name,
final String version) {
return (targetRoot, query, cb) -> cb.and(
cb.equal(cb.lower(targetRoot.<String> get(JpaDistributionSet_.name)), name.toLowerCase()),
cb.equal(cb.lower(targetRoot.<String> get(JpaDistributionSet_.version)), version.toLowerCase()));
return (dsRoot, query, cb) -> cb.and(
cb.equal(cb.lower(dsRoot.<String> get(JpaDistributionSet_.name)), name.toLowerCase()),
cb.equal(cb.lower(dsRoot.<String> get(JpaDistributionSet_.version)), version.toLowerCase()));
}
@@ -220,13 +205,13 @@ public final class DistributionSetSpecification {
* {@link Specification} for retrieving {@link DistributionSet} with given
* {@link DistributionSet#getType()}.
*
* @param type
* to search
* @param typeId
* id of distribution set type to search
* @return the {@link DistributionSet} {@link Specification}
*/
public static Specification<JpaDistributionSet> byType(final DistributionSetType type) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.<JpaDistributionSetType> get(JpaDistributionSet_.type),
type);
public static Specification<JpaDistributionSet> byType(final Long typeId) {
return (dsRoot, query, cb) -> cb.equal(dsRoot.get(JpaDistributionSet_.type).get(JpaDistributionSetType_.id),
typeId);
}
@@ -269,11 +254,38 @@ public final class DistributionSetSpecification {
*/
public static Specification<JpaDistributionSet> hasTag(final Long tagId) {
return (targetRoot, query, cb) -> {
final SetJoin<JpaDistributionSet, JpaDistributionSetTag> tags = targetRoot.join(JpaDistributionSet_.tags,
return (dsRoot, query, cb) -> {
final SetJoin<JpaDistributionSet, JpaDistributionSetTag> tags = dsRoot.join(JpaDistributionSet_.tags,
JoinType.LEFT);
return cb.equal(tags.get(JpaDistributionSetTag_.id), tagId);
};
}
/**
* Can be added to specification chain to order result by provided target
*
* Order: 1. Distribution set installed on target, 2. Distribution set(s)
* assigned to target, 3. Based on distribution set id
*
* NOTE: Other specs, pagables and sort objects may alter the queries
* orderBy entry too, possibly invalidating the applied order, keep in mind
* when using this
*
* @param linkedControllerId
* controller id to get installed/assigned DS for
* @return specification that applies order by target, may be overwritten
*/
public static Specification<JpaDistributionSet> orderedByLinkedTarget(final String linkedControllerId) {
return (dsRoot, query, cb) -> {
final Root<JpaTarget> targetRoot = query.from(JpaTarget.class);
final Expression<Object> assignedInstalledCase = cb.selectCase()
.when(cb.equal(targetRoot.get(JpaTarget_.installedDistributionSet), dsRoot), 1)
.when(cb.equal(targetRoot.get(JpaTarget_.assignedDistributionSet), dsRoot), 2).otherwise(3);
query.orderBy(cb.asc(assignedInstalledCase), cb.asc(dsRoot.get(JpaDistributionSet_.id)));
return cb.equal(targetRoot.get(JpaTarget_.controllerId), linkedControllerId);
};
}
}

View File

@@ -45,4 +45,24 @@ public final class RolloutSpecification {
}
/**
* Builds a {@link Specification} to search a rollout by name.
*
* @param searchText
* search string
* @param isDeleted
* <code>true</code> if deleted rollouts should be included in
* the search. Otherwise <code>false</code>
* @return criteria specification with a query for name of a rollout
*
*/
public static Specification<JpaRollout> likeName(final String searchText, final boolean isDeleted) {
return (rolloutRoot, query, criteriaBuilder) -> {
final String searchTextToLower = searchText.toLowerCase();
return criteriaBuilder.and(
criteriaBuilder.like(criteriaBuilder.lower(rolloutRoot.get(JpaRollout_.name)), searchTextToLower),
criteriaBuilder.equal(rolloutRoot.get(JpaRollout_.deleted), isDeleted));
};
}
}

View File

@@ -37,16 +37,18 @@ public final class SoftwareModuleSpecification {
/**
* {@link Specification} for retrieving {@link SoftwareModule}s by "like
* name or like version".
*
* @param subString
* name and like version".
*
* @param name
* to be filtered on
* @param version
* to be filtered on
* @return the {@link SoftwareModule} {@link Specification}
*/
public static Specification<JpaSoftwareModule> likeNameOrVersion(final String subString) {
return (targetRoot, query, cb) -> cb.or(
cb.like(cb.lower(targetRoot.<String> get(JpaSoftwareModule_.name)), subString.toLowerCase()),
cb.like(cb.lower(targetRoot.<String> get(JpaSoftwareModule_.version)), subString.toLowerCase()));
public static Specification<JpaSoftwareModule> likeNameAndVersion(final String name, final String version) {
return (smRoot, query, cb) -> cb.and(
cb.like(cb.lower(smRoot.<String> get(JpaSoftwareModule_.name)), name.toLowerCase()),
cb.like(cb.lower(smRoot.<String> get(JpaSoftwareModule_.version)), version.toLowerCase()));
}
/**
@@ -58,8 +60,22 @@ public final class SoftwareModuleSpecification {
* @return the {@link SoftwareModule} {@link Specification}
*/
public static Specification<JpaSoftwareModule> equalType(final Long type) {
return (targetRoot, query, cb) -> cb.equal(
targetRoot.<JpaSoftwareModuleType> get(JpaSoftwareModule_.type).get(JpaSoftwareModuleType_.id), type);
return (smRoot, query, cb) -> cb.equal(
smRoot.<JpaSoftwareModuleType> get(JpaSoftwareModule_.type).get(JpaSoftwareModuleType_.id), type);
}
/**
* {@link Specification} for fetching {@link SoftwareModule}s type.
*
* @return the {@link SoftwareModule} {@link Specification}
*/
public static Specification<JpaSoftwareModule> fetchType() {
return (smRoot, query, cb) -> {
if (!query.getResultType().isAssignableFrom(Long.class)) {
smRoot.fetch(JpaSoftwareModule_.type);
}
return cb.conjunction();
};
}
}

View File

@@ -126,8 +126,8 @@ public final class TargetSpecifications {
}
/**
* {@link Specification} for retrieving {@link Target}s that have the request
* controller attributes flag set
* {@link Specification} for retrieving {@link Target}s that have the
* request controller attributes flag set
*
* @return the {@link Target} {@link Specification}
*/
@@ -154,8 +154,8 @@ public final class TargetSpecifications {
}
/**
* {@link Specification} for retrieving {@link Target}s by "equal to any given
* {@link TargetUpdateStatus}".
* {@link Specification} for retrieving {@link Target}s by "equal to any
* given {@link TargetUpdateStatus}".
*
* @param updateStatus
* to be filtered on
@@ -180,8 +180,8 @@ 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 "not equal to
* given {@link TargetUpdateStatus}".
*
* @param updateStatus
* to be filtered on
@@ -194,14 +194,15 @@ public final class TargetSpecifications {
/**
* {@link Specification} for retrieving {@link Target}s that are overdue. A
* target is overdue if it did not respond during the configured intervals:<br>
* target is overdue if it did not respond during the configured
* intervals:<br>
* <em>poll_itvl + overdue_itvl</em>
*
* @param overdueTimestamp
* the calculated timestamp to compare with the last respond of a
* target (lastTargetQuery).<br>
* The <code>overdueTimestamp</code> has to be calculated with the
* following expression:<br>
* The <code>overdueTimestamp</code> has to be calculated with
* the following expression:<br>
* <em>overdueTimestamp = nowTimestamp - poll_itvl -
* overdue_itvl</em>
*
@@ -212,23 +213,6 @@ public final class TargetSpecifications {
overdueTimestamp);
}
/**
* {@link Specification} for retrieving {@link Target}s by "like controllerId or
* like name or like description".
*
* @param searchText
* to be filtered on
* @return the {@link Target} {@link Specification}
*/
public static Specification<JpaTarget> likeIdOrNameOrDescription(final String searchText) {
return (targetRoot, query, cb) -> {
final String searchTextToLower = searchText.toLowerCase();
return cb.or(cb.like(cb.lower(targetRoot.get(JpaTarget_.controllerId)), searchTextToLower),
cb.like(cb.lower(targetRoot.get(JpaTarget_.name)), searchTextToLower),
cb.like(cb.lower(targetRoot.get(JpaTarget_.description)), searchTextToLower));
};
}
/**
* {@link Specification} for retrieving {@link Target}s by "like attribute
* value".
@@ -248,19 +232,24 @@ public final class TargetSpecifications {
}
/**
* {@link Specification} for retrieving {@link Target}s by "like controllerId or
* like name or like description or like attribute value".
* {@link Specification} for retrieving {@link Target}s by "like
* controllerId or like name".
*
* @param searchText
* to be filtered on
* @return the {@link Target} {@link Specification}
*/
public static Specification<JpaTarget> likeIdOrNameOrDescriptionOrAttributeValue(final String searchText) {
return Specification.where(likeIdOrNameOrDescription(searchText)).or(likeAttributeValue(searchText));
public static Specification<JpaTarget> likeControllerIdOrName(final String searchText) {
return (targetRoot, query, cb) -> {
final String searchTextToLower = searchText.toLowerCase();
return cb.or(cb.like(cb.lower(targetRoot.get(JpaTarget_.controllerId)), searchTextToLower),
cb.like(cb.lower(targetRoot.get(JpaTarget_.name)), searchTextToLower));
};
}
/**
* {@link Specification} for retrieving {@link Target}s by "like controllerId".
* {@link Specification} for retrieving {@link Target}s by "like
* controllerId".
*
* @param distributionId
* to be filtered on
@@ -271,8 +260,8 @@ public final class TargetSpecifications {
}
/**
* Finds all targets by given {@link Target#getControllerId()}s and which are
* not yet assigned to given {@link DistributionSet}.
* Finds all targets by given {@link Target#getControllerId()}s and which
* are not yet assigned to given {@link DistributionSet}.
*
* @param tIDs
* to search for.
@@ -305,8 +294,8 @@ public final class TargetSpecifications {
}
/**
* {@link Specification} for retrieving {@link Target}s by "has no tag names"or
* "has at least on of the given tag names".
* {@link Specification} for retrieving {@link Target}s by "has no tag
* names"or "has at least on of the given tag names".
*
* @param tagNames
* to be filtered on
@@ -348,8 +337,8 @@ public final class TargetSpecifications {
}
/**
* {@link Specification} for retrieving {@link Target}s by assigned distribution
* set.
* {@link Specification} for retrieving {@link Target}s by assigned
* distribution set.
*
* @param distributionSetId
* the ID of the distribution set which must be assigned
@@ -380,10 +369,10 @@ public final class TargetSpecifications {
}
/**
* {@link Specification} for retrieving {@link Target}s that are compatible with
* given {@link DistributionSetType}. Compatibility is evaluated by checking the
* {@link TargetType} of a target. Targets that don't have a {@link TargetType}
* are compatible with all {@link DistributionSetType}
* {@link Specification} for retrieving {@link Target}s that are compatible
* with given {@link DistributionSetType}. Compatibility is evaluated by
* checking the {@link TargetType} of a target. Targets that don't have a
* {@link TargetType} are compatible with all {@link DistributionSetType}
*
* @param distributionSetTypeId
* the ID of the distribution set type which must be compatible
@@ -399,15 +388,16 @@ public final class TargetSpecifications {
};
}
private static Predicate getTargetTypeIsNullPredicate(Root<JpaTarget> targetRoot) {
private static Predicate getTargetTypeIsNullPredicate(final Root<JpaTarget> targetRoot) {
return targetRoot.get(JpaTarget_.targetType).isNull();
}
/**
* {@link Specification} for retrieving {@link Target}s that are NOT compatible
* with given {@link DistributionSetType}. Compatibility is evaluated by
* checking the {@link TargetType} of a target. Targets that don't have a
* {@link TargetType} are compatible with all {@link DistributionSetType}
* {@link Specification} for retrieving {@link Target}s that are NOT
* compatible with given {@link DistributionSetType}. Compatibility is
* evaluated by checking the {@link TargetType} of a target. Targets that
* don't have a {@link TargetType} are compatible with all
* {@link DistributionSetType}
*
* @param distributionSetTypeId
* the ID of the distribution set type which must be incompatible
@@ -456,8 +446,8 @@ public final class TargetSpecifications {
}
/**
* {@link Specification} for retrieving {@link Target}s that are in an action
* for a given {@link RolloutGroup}
* {@link Specification} for retrieving {@link Target}s that are in an
* action for a given {@link RolloutGroup}
*
* @param group
* the {@link RolloutGroup}
@@ -490,8 +480,8 @@ public final class TargetSpecifications {
}
/**
* {@link Specification} for retrieving {@link Target}s that have no Action of
* the {@link RolloutGroup}.
* {@link Specification} for retrieving {@link Target}s that have no Action
* of the {@link RolloutGroup}.
*
* @param group
* the {@link RolloutGroup}
@@ -512,8 +502,8 @@ public final class TargetSpecifications {
}
/**
* {@link Specification} for retrieving {@link Target}s by assigned distribution
* set.
* {@link Specification} for retrieving {@link Target}s by assigned
* distribution set.
*
* @param distributionSetId
* the ID of the distribution set which must be assigned
@@ -553,7 +543,8 @@ public final class TargetSpecifications {
}
/**
* {@link Specification} for retrieving {@link Target}s by target type id is equal to null
* {@link Specification} for retrieving {@link Target}s by target type id is
* equal to null
*
* @return the {@link Target} {@link Specification}
*/
@@ -562,8 +553,8 @@ public final class TargetSpecifications {
}
/**
* {@link Specification} for retrieving {@link Target}s that don't have target
* type assigned
* {@link Specification} for retrieving {@link Target}s that don't have
* target type assigned
*
* @param typeId
* the id of the target type
@@ -576,15 +567,15 @@ public final class TargetSpecifications {
}
/**
* Can be added to specification chain to order result by provided distribution
* set
* Can be added to specification chain to order result by provided
* distribution set
*
* Order: 1. Targets with DS installed, 2. Targets with DS assigned, 3. Based on
* target id
* Order: 1. Targets with DS installed, 2. Targets with DS assigned, 3.
* Based on target id
*
* NOTE: Other specs, pagables and sort objects may alter the queries orderBy
* entry too, possibly invalidating the applied order, keep in mind when using
* this
* NOTE: Other specs, pagables and sort objects may alter the queries
* orderBy entry too, possibly invalidating the applied order, keep in mind
* when using this
*
* @param distributionSetIdForOrder
* distribution set to consider

View File

@@ -0,0 +1 @@
CREATE INDEX sp_idx_rollout_status_tenant ON sp_rollout (tenant, status);

View File

@@ -0,0 +1 @@
CREATE INDEX sp_idx_rollout_status_tenant ON sp_rollout (tenant, status);

View File

@@ -0,0 +1 @@
CREATE INDEX sp_idx_rollout_status_tenant ON sp_rollout (tenant, status);

View File

@@ -0,0 +1,3 @@
CREATE INDEX sp_idx_rollout_status_tenant
ON sp_rollout
USING BTREE (tenant, status);

View File

@@ -0,0 +1 @@
CREATE INDEX sp_idx_rollout_status_tenant ON sp_rollout (tenant, status);