From 495cfbc4cf6e110bf7b6dcb47d7bfd8587056169 Mon Sep 17 00:00:00 2001 From: Damien Arrachequesne Date: Wed, 3 Apr 2024 10:01:03 +0200 Subject: [PATCH] fix: properly compute search panes with related entities Related: https://github.com/darrachequesne/spring-data-jpa-datatables/issues/159 --- .../repository/DataTablesRepositoryImpl.java | 19 ++++++++++++++----- .../repository/EmployeeRepositoryTest.java | 8 ++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/springframework/data/jpa/datatables/repository/DataTablesRepositoryImpl.java b/src/main/java/org/springframework/data/jpa/datatables/repository/DataTablesRepositoryImpl.java index b30f640..0c955d9 100644 --- a/src/main/java/org/springframework/data/jpa/datatables/repository/DataTablesRepositoryImpl.java +++ b/src/main/java/org/springframework/data/jpa/datatables/repository/DataTablesRepositoryImpl.java @@ -3,11 +3,9 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Root; import lombok.extern.slf4j.Slf4j; -import org.hibernate.query.sqm.tree.domain.AbstractSqmFrom; -import org.hibernate.query.sqm.tree.domain.SqmPath; -import org.hibernate.query.sqm.tree.from.SqmAttributeJoin; import org.springframework.data.domain.Page; import org.springframework.data.jpa.datatables.SpecificationBuilder; import org.springframework.data.jpa.datatables.mapping.DataTablesInput; @@ -109,8 +107,10 @@ private SearchPanes computeSearchPanes(DataTablesInput input, Specification s CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder(); CriteriaQuery query = criteriaBuilder.createQuery(Object[].class); Root root = query.from(getDomainClass()); - query.multiselect(root.get(attribute), criteriaBuilder.count(root)); - query.groupBy(root.get(attribute)); + Path path = getPath(root, attribute); + + query.multiselect(path, criteriaBuilder.count(root)); + query.groupBy(path); query.where(specification.toPredicate(root, query, criteriaBuilder)); List items = new ArrayList<>(); @@ -127,4 +127,13 @@ private SearchPanes computeSearchPanes(DataTablesInput input, Specification s return new SearchPanes(options); } + private Path getPath(Root root, String attribute) { + String[] parts = attribute.split("\\."); + Path path = root; + for (String part : parts) { + path = path.get(part); + } + return path; + } + } diff --git a/src/test/java/org/springframework/data/jpa/datatables/repository/EmployeeRepositoryTest.java b/src/test/java/org/springframework/data/jpa/datatables/repository/EmployeeRepositoryTest.java index 38bc58f..c6a501f 100644 --- a/src/test/java/org/springframework/data/jpa/datatables/repository/EmployeeRepositoryTest.java +++ b/src/test/java/org/springframework/data/jpa/datatables/repository/EmployeeRepositoryTest.java @@ -318,6 +318,7 @@ void withSearchPanes() { Map> searchPanes = new HashMap<>(); searchPanes.put("position", new HashSet<>(asList("Software Engineer", "Integration Specialist"))); searchPanes.put("age", emptySet()); + searchPanes.put("office.city", emptySet()); input.setSearchPanes(searchPanes); @@ -325,6 +326,8 @@ void withSearchPanes() { assertThat(output.getRecordsFiltered()).isEqualTo(3); assertThat(output.getSearchPanes()).isNotNull(); + assertThat(output.getSearchPanes().getOptions().size()).isEqualTo(3); + assertThat(output.getSearchPanes().getOptions().get("position")).containsOnly( new SearchPanes.Item("Software Engineer", "Software Engineer", 2, 2), new SearchPanes.Item("Integration Specialist", "Integration Specialist", 1, 1) @@ -334,6 +337,11 @@ void withSearchPanes() { new SearchPanes.Item("41", "41", 1, 1), new SearchPanes.Item("61", "61", 1, 1) ); + assertThat(output.getSearchPanes().getOptions().get("office.city")).containsOnly( + new SearchPanes.Item("London", "London", 1, 1), + new SearchPanes.Item("New York", "New York", 1, 1), + new SearchPanes.Item("San Francisco", "San Francisco", 1, 1) + ); } @Test