Fix RSQL filter in batch update query in assign target group (#3107)
* Fix RSQL filter in batch update query in assign target group Signed-off-by: strailov <Stanislav.Trailov@bosch.io> * Stick with old approach when using hibernate Signed-off-by: strailov <Stanislav.Trailov@bosch.io> * avoid fully qualified classname Signed-off-by: strailov <Stanislav.Trailov@bosch.io> * Refer review changes Signed-off-by: strailov <Stanislav.Trailov@bosch.io> * add link to the bug reported to eclipse link Signed-off-by: strailov <Stanislav.Trailov@bosch.io> --------- Signed-off-by: strailov <Stanislav.Trailov@bosch.io>
This commit is contained in:
committed by
GitHub
parent
b0e279a3e8
commit
794455064f
@@ -22,6 +22,8 @@ import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetGroupRestApi;
|
||||
import org.eclipse.hawkbit.repository.TargetTagManagement;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -229,4 +231,30 @@ public class MgmtTargetGroupResourceTest extends AbstractManagementApiIntegratio
|
||||
.andExpect(jsonPath("content.[1].controllerId", Matchers.equalTo("target2")))
|
||||
.andExpect(jsonPath("content.[2].controllerId", Matchers.equalTo("target3")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAssignGroupToTargetsFilteredByTagNotEqual() throws Exception {
|
||||
targetManagement.create(builder().controllerId("target1").build());
|
||||
targetManagement.create(builder().controllerId("target2").build());
|
||||
targetManagement.create(builder().controllerId("target3").build());
|
||||
|
||||
final TargetTag tag1 = targetTagManagement.create(TargetTagManagement.Create.builder().name("tag1").build());
|
||||
final TargetTag tag2 = targetTagManagement.create(TargetTagManagement.Create.builder().name("tag2").build());
|
||||
|
||||
targetManagement.assignTag(List.of("target1"), tag1.getId());
|
||||
targetManagement.assignTag(List.of("target2"), tag1.getId());
|
||||
targetManagement.assignTag(List.of("target3"), tag2.getId());
|
||||
|
||||
mvc.perform(put(MgmtTargetGroupRestApi.TARGETGROUPS_V1 + "/FilteredGroup")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.param("q", "tag!=tag1"))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
mvc.perform(get(MgmtTargetGroupRestApi.TARGETGROUPS_V1 + "/FilteredGroup/assigned")
|
||||
.param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "ID:ASC")
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("content", Matchers.hasSize(1)))
|
||||
.andExpect(jsonPath("content.[0].controllerId", Matchers.equalTo("target3")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import jakarta.persistence.criteria.CriteriaUpdate;
|
||||
import jakarta.persistence.criteria.MapJoin;
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.persistence.criteria.Subquery;
|
||||
import jakarta.persistence.metamodel.MapAttribute;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
@@ -39,9 +40,11 @@ import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.jpa.Jpa;
|
||||
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType;
|
||||
@@ -336,11 +339,24 @@ public class JpaTargetManagement
|
||||
|
||||
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
final CriteriaUpdate<JpaTarget> criteriaUpdateQuery = cb.createCriteriaUpdate(JpaTarget.class);
|
||||
final Root<JpaTarget> root = criteriaUpdateQuery.getRoot();
|
||||
final Root<JpaTarget> updateRoot = criteriaUpdateQuery.getRoot();
|
||||
criteriaUpdateQuery.set("group", group);
|
||||
// get predicate from rsql specification using a dummy query in order to execute batch update
|
||||
final Predicate predicate = rsqlSpecification.toPredicate(root, entityManager.getCriteriaBuilder().createQuery(JpaTarget.class), cb);
|
||||
criteriaUpdateQuery.where(predicate);
|
||||
|
||||
if (Jpa.JPA_VENDOR == Jpa.JpaVendor.ECLIPSELINK) {
|
||||
// EclipseLink: use subquery approach — applying predicate directly to the UPDATE root
|
||||
// fails for NOT EXISTS due to UpdateAllQuery's @Id resolution bug
|
||||
// BUG Reported: https://github.com/eclipse-ee4j/eclipselink/issues/2757
|
||||
final Subquery<Long> subquery = criteriaUpdateQuery.subquery(Long.class);
|
||||
final Root<JpaTarget> subRoot = subquery.from(JpaTarget.class);
|
||||
subquery.select(subRoot.get(AbstractJpaBaseEntity_.ID));
|
||||
subquery.where(rsqlSpecification.toPredicate(subRoot, cb.createQuery(JpaTarget.class), cb));
|
||||
criteriaUpdateQuery.where(updateRoot.get(AbstractJpaBaseEntity_.ID).in(subquery));
|
||||
} else {
|
||||
// Hibernate: apply predicate directly to the UPDATE root — Hibernate handles
|
||||
// NOT EXISTS subqueries correctly in CriteriaUpdate context
|
||||
final Predicate predicate = rsqlSpecification.toPredicate(updateRoot, cb.createQuery(JpaTarget.class), cb);
|
||||
criteriaUpdateQuery.where(predicate);
|
||||
}
|
||||
|
||||
entityManager.createQuery(criteriaUpdateQuery).executeUpdate();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user