From 90d7d697f5033ffeddaa2c391005d5ed7b3a5cff Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 22 Jan 2025 14:17:33 +0100 Subject: [PATCH] Remove deprecated QuerydslJpaRepository. Closes #3683 --- .../support/QuerydslJpaRepository.java | 228 ------------ .../support/QuerydslJpaRepositoryTests.java | 341 ------------------ 2 files changed, 569 deletions(-) delete mode 100644 spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/QuerydslJpaRepository.java delete mode 100644 spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/QuerydslJpaRepositoryTests.java diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/QuerydslJpaRepository.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/QuerydslJpaRepository.java deleted file mode 100644 index 129d56f6e9..0000000000 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/support/QuerydslJpaRepository.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright 2008-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.jpa.repository.support; - -import java.io.Serializable; -import java.util.List; -import java.util.Optional; -import java.util.function.Function; - -import jakarta.persistence.EntityManager; -import jakarta.persistence.LockModeType; - -import org.springframework.dao.IncorrectResultSizeDataAccessException; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.data.querydsl.EntityPathResolver; -import org.springframework.data.querydsl.QSort; -import org.springframework.data.querydsl.QuerydslPredicateExecutor; -import org.springframework.data.querydsl.SimpleEntityPathResolver; -import org.springframework.data.repository.query.FluentQuery; -import org.springframework.data.support.PageableExecutionUtils; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -import com.querydsl.core.NonUniqueResultException; -import com.querydsl.core.types.EntityPath; -import com.querydsl.core.types.OrderSpecifier; -import com.querydsl.core.types.Predicate; -import com.querydsl.core.types.dsl.PathBuilder; -import com.querydsl.jpa.JPQLQuery; -import com.querydsl.jpa.impl.AbstractJPAQuery; - -/** - * QueryDsl specific extension of {@link SimpleJpaRepository} which adds implementation for - * {@link QuerydslPredicateExecutor}. - * - * @author Oliver Gierke - * @author Thomas Darimont - * @author Mark Paluch - * @author Jocelyn Ntakpe - * @author Christoph Strobl - * @author Jens Schauder - * @author Greg Turnquist - * @author Yanming Zhou - * @deprecated Instead of this class use {@link QuerydslJpaPredicateExecutor} - */ -@Deprecated -public class QuerydslJpaRepository extends SimpleJpaRepository - implements QuerydslPredicateExecutor { - - private final EntityPath path; - private final PathBuilder builder; - private final Querydsl querydsl; - private final EntityManager entityManager; - - /** - * Creates a new {@link QuerydslJpaRepository} from the given domain class and {@link EntityManager}. This will use - * the {@link SimpleEntityPathResolver} to translate the given domain class into an {@link EntityPath}. - * - * @param entityInformation must not be {@literal null}. - * @param entityManager must not be {@literal null}. - */ - public QuerydslJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager) { - this(entityInformation, entityManager, SimpleEntityPathResolver.INSTANCE); - } - - /** - * Creates a new {@link QuerydslJpaRepository} from the given domain class and {@link EntityManager} and uses the - * given {@link EntityPathResolver} to translate the domain class into an {@link EntityPath}. - * - * @param entityInformation must not be {@literal null}. - * @param entityManager must not be {@literal null}. - * @param resolver must not be {@literal null}. - */ - public QuerydslJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager, - EntityPathResolver resolver) { - - super(entityInformation, entityManager); - - this.path = resolver.createPath(entityInformation.getJavaType()); - this.builder = new PathBuilder<>(path.getType(), path.getMetadata()); - this.querydsl = new Querydsl(entityManager, builder); - this.entityManager = entityManager; - } - - @Override - public Optional findOne(Predicate predicate) { - - try { - return Optional.ofNullable(createQuery(predicate).select(path).limit(2).fetchOne()); - } catch (NonUniqueResultException ex) { - throw new IncorrectResultSizeDataAccessException(ex.getMessage(), 1, ex); - } - } - - @Override - public List findAll(Predicate predicate) { - return createQuery(predicate).select(path).fetch(); - } - - @Override - public List findAll(Predicate predicate, OrderSpecifier... orders) { - return executeSorted(createQuery(predicate).select(path), orders); - } - - @Override - public List findAll(Predicate predicate, Sort sort) { - - Assert.notNull(sort, "Sort must not be null"); - - return executeSorted(createQuery(predicate).select(path), sort); - } - - @Override - public List findAll(OrderSpecifier... orders) { - - Assert.notNull(orders, "Order specifiers must not be null"); - - return executeSorted(createQuery(new Predicate[0]).select(path), orders); - } - - @Override - public Page findAll(Predicate predicate, Pageable pageable) { - - Assert.notNull(pageable, "Pageable must not be null"); - - final JPQLQuery countQuery = createCountQuery(predicate); - JPQLQuery query = querydsl.applyPagination(pageable, createQuery(predicate).select(path)); - - return PageableExecutionUtils.getPage(query.fetch(), pageable, countQuery::fetchCount); - } - - @Override - public R findBy(Predicate predicate, - Function, R> queryFunction) { - throw new UnsupportedOperationException( - "Fluent Query API support for Querydsl is only found in QuerydslJpaPredicateExecutor."); - } - - @Override - public long count(Predicate predicate) { - return createQuery(predicate).fetchCount(); - } - - @Override - public boolean exists(Predicate predicate) { - return createQuery(predicate).fetchCount() > 0; - } - - /** - * Creates a new {@link JPQLQuery} for the given {@link Predicate}. - * - * @param predicate - * @return the Querydsl {@link JPQLQuery}. - */ - protected JPQLQuery createQuery(Predicate... predicate) { - - AbstractJPAQuery query = doCreateQuery(getQueryHints().withFetchGraphs(entityManager), predicate); - - CrudMethodMetadata metadata = getRepositoryMethodMetadata(); - - if (metadata == null) { - return query; - } - - LockModeType type = metadata.getLockModeType(); - return type == null ? query : query.setLockMode(type); - } - - /** - * Creates a new {@link JPQLQuery} count query for the given {@link Predicate}. - * - * @param predicate, can be {@literal null}. - * @return the Querydsl count {@link JPQLQuery}. - */ - protected JPQLQuery createCountQuery(@Nullable Predicate... predicate) { - return doCreateQuery(getQueryHints(), predicate); - } - - private AbstractJPAQuery doCreateQuery(QueryHints hints, @Nullable Predicate... predicate) { - - AbstractJPAQuery query = querydsl.createQuery(path); - - if (predicate != null) { - query = query.where(predicate); - } - - hints.forEach(query::setHint); - - return query; - } - - /** - * Executes the given {@link JPQLQuery} after applying the given {@link OrderSpecifier}s. - * - * @param query must not be {@literal null}. - * @param orders must not be {@literal null}. - * @return - */ - private List executeSorted(JPQLQuery query, OrderSpecifier... orders) { - return executeSorted(query, new QSort(orders)); - } - - /** - * Executes the given {@link JPQLQuery} after applying the given {@link Sort}. - * - * @param query must not be {@literal null}. - * @param sort must not be {@literal null}. - * @return - */ - private List executeSorted(JPQLQuery query, Sort sort) { - return querydsl.applySorting(sort, query).fetch(); - } -} diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/QuerydslJpaRepositoryTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/QuerydslJpaRepositoryTests.java deleted file mode 100644 index ece657841b..0000000000 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/support/QuerydslJpaRepositoryTests.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright 2008-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.data.jpa.repository.support; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; - -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; - -import java.sql.Date; -import java.time.LocalDate; -import java.util.List; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.dao.IncorrectResultSizeDataAccessException; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.domain.Sort.Order; -import org.springframework.data.jpa.domain.sample.Address; -import org.springframework.data.jpa.domain.sample.QUser; -import org.springframework.data.jpa.domain.sample.Role; -import org.springframework.data.jpa.domain.sample.User; -import org.springframework.data.querydsl.QPageRequest; -import org.springframework.data.querydsl.QSort; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit.jupiter.SpringExtension; -import org.springframework.transaction.annotation.Transactional; - -import com.querydsl.core.types.Predicate; -import com.querydsl.core.types.dsl.BooleanExpression; -import com.querydsl.core.types.dsl.PathBuilder; -import com.querydsl.core.types.dsl.PathBuilderFactory; - -/** - * Integration test for {@link QuerydslJpaRepository}. - * - * @author Oliver Gierke - * @author Thomas Darimont - * @author Mark Paluch - * @author Christoph Strobl - * @author Malte Mauelshagen - * @author Greg Turnquist - * @author Krzysztof Krason - */ -@ExtendWith(SpringExtension.class) -@ContextConfiguration({ "classpath:infrastructure.xml" }) -@Transactional -class QuerydslJpaRepositoryTests { - - @PersistenceContext EntityManager em; - - private QuerydslJpaRepository repository; - private QUser user = new QUser("user"); - private User dave; - private User carter; - private User oliver; - private Role adminRole; - - @BeforeEach - void setUp() { - - JpaEntityInformation information = new JpaMetamodelEntityInformation<>(User.class, em.getMetamodel(), - em.getEntityManagerFactory().getPersistenceUnitUtil()); - - repository = new QuerydslJpaRepository<>(information, em); - dave = repository.save(new User("Dave", "Matthews", "dave@matthews.com")); - carter = repository.save(new User("Carter", "Beauford", "carter@beauford.com")); - oliver = repository.save(new User("Oliver", "matthews", "oliver@matthews.com")); - adminRole = em.merge(new Role("admin")); - } - - @Test - void executesPredicatesCorrectly() { - - BooleanExpression isCalledDave = user.firstname.eq("Dave"); - BooleanExpression isBeauford = user.lastname.eq("Beauford"); - - List result = repository.findAll(isCalledDave.or(isBeauford)); - - assertThat(result).containsExactlyInAnyOrder(carter, dave); - } - - @Test - void executesStringBasedPredicatesCorrectly() { - - PathBuilder builder = new PathBuilderFactory().create(User.class); - - BooleanExpression isCalledDave = builder.getString("firstname").eq("Dave"); - BooleanExpression isBeauford = builder.getString("lastname").eq("Beauford"); - - List result = repository.findAll(isCalledDave.or(isBeauford)); - - assertThat(result).containsExactlyInAnyOrder(carter, dave); - } - - @Test // DATAJPA-243 - void considersSortingProvidedThroughPageable() { - - Predicate lastnameContainsE = user.lastname.contains("e"); - - Page result = repository.findAll(lastnameContainsE, PageRequest.of(0, 1, Direction.ASC, "lastname")); - - assertThat(result).containsExactly(carter); - - result = repository.findAll(lastnameContainsE, PageRequest.of(0, 2, Direction.DESC, "lastname")); - - assertThat(result).containsExactly(oliver, dave); - } - - @Test // DATAJPA-296 - void appliesIgnoreCaseOrdering() { - - Sort sort = Sort.by(new Order(Direction.DESC, "lastname").ignoreCase(), new Order(Direction.ASC, "firstname")); - - Page result = repository.findAll(user.lastname.contains("e"), PageRequest.of(0, 2, sort)); - - assertThat(result.getContent()).containsExactly(dave, oliver); - } - - @Test // DATAJPA-427 - void findBySpecificationWithSortByPluralAssociationPropertyInPageableShouldUseSortNullValuesLast() { - - oliver.getColleagues().add(dave); - dave.getColleagues().add(oliver); - - QUser user = QUser.user; - - Page page = repository.findAll(user.firstname.isNotNull(), - PageRequest.of(0, 10, Sort.by(Sort.Direction.ASC, "colleagues.firstname"))); - - assertThat(page.getContent()).hasSize(3).contains(oliver, dave, carter); - } - - @Test // DATAJPA-427 - void findBySpecificationWithSortBySingularAssociationPropertyInPageableShouldUseSortNullValuesLast() { - - oliver.setManager(dave); - dave.setManager(carter); - - QUser user = QUser.user; - - Page page = repository.findAll(user.firstname.isNotNull(), - PageRequest.of(0, 10, Sort.by(Sort.Direction.ASC, "manager.firstname"))); - - assertThat(page.getContent()).hasSize(3).contains(dave, oliver, carter); - } - - @Test // DATAJPA-427 - void findBySpecificationWithSortBySingularPropertyInPageableShouldUseSortNullValuesFirst() { - - QUser user = QUser.user; - - Page page = repository.findAll(user.firstname.isNotNull(), - PageRequest.of(0, 10, Sort.by(Sort.Direction.ASC, "firstname"))); - - assertThat(page.getContent()).containsExactly(carter, dave, oliver); - } - - @Test // DATAJPA-427 - void findBySpecificationWithSortByOrderIgnoreCaseBySingularPropertyInPageableShouldUseSortNullValuesFirst() { - - QUser user = QUser.user; - - Page page = repository.findAll(user.firstname.isNotNull(), - PageRequest.of(0, 10, Sort.by(new Order(Sort.Direction.ASC, "firstname").ignoreCase()))); - - assertThat(page.getContent()).containsExactly(carter, dave, oliver); - } - - @Test // DATAJPA-427 - void findBySpecificationWithSortByNestedEmbeddedPropertyInPageableShouldUseSortNullValuesFirst() { - - oliver.setAddress(new Address("Germany", "Saarbrücken", "HaveItYourWay", "123")); - - QUser user = QUser.user; - - Page page = repository.findAll(user.firstname.isNotNull(), - PageRequest.of(0, 10, Sort.by(Sort.Direction.ASC, "address.streetName"))); - - assertThat(page.getContent()).containsExactly(dave, carter, oliver); - } - - @Test // DATAJPA-12 - void findBySpecificationWithSortByQueryDslOrderSpecifierWithQPageRequestAndQSort() { - - QUser user = QUser.user; - - Page page = repository.findAll(user.firstname.isNotNull(), - QPageRequest.of(0, 10, new QSort(user.firstname.asc()))); - - assertThat(page.getContent()).containsExactly(carter, dave, oliver); - } - - @Test // DATAJPA-12 - void findBySpecificationWithSortByQueryDslOrderSpecifierWithQPageRequest() { - - QUser user = QUser.user; - - Page page = repository.findAll(user.firstname.isNotNull(), QPageRequest.of(0, 10, user.firstname.asc())); - - assertThat(page.getContent()).containsExactly(carter, dave, oliver); - } - - @Test // DATAJPA-12 - void findBySpecificationWithSortByQueryDslOrderSpecifierForAssociationShouldGenerateLeftJoinWithQPageRequest() { - - oliver.setManager(dave); - dave.setManager(carter); - - QUser user = QUser.user; - - Page page = repository.findAll(user.firstname.isNotNull(), - QPageRequest.of(0, 10, user.manager.firstname.asc())); - - assertThat(page.getContent()).containsExactly(carter, dave, oliver); - } - - @Test // DATAJPA-491 - void sortByNestedAssociationPropertyWithSpecificationAndSortInPageable() { - - oliver.setManager(dave); - dave.getRoles().add(adminRole); - - Page page = repository.findAll(PageRequest.of(0, 10, Sort.by(Direction.ASC, "manager.roles.name"))); - - assertThat(page.getContent()).hasSize(3); - assertThat(page.getContent().get(0)).isEqualTo(dave); - } - - @Test // DATAJPA-500, DATAJPA-635 - void sortByNestedEmbeddedAttribute() { - - carter.setAddress(new Address("U", "Z", "Y", "41")); - dave.setAddress(new Address("U", "A", "Y", "41")); - oliver.setAddress(new Address("G", "D", "X", "42")); - - List users = repository.findAll(QUser.user.address.streetName.asc()); - - assertThat(users).hasSize(3).contains(dave, oliver, carter); - } - - @Test // DATAJPA-566, DATAJPA-635 - void shouldSupportSortByOperatorWithDateExpressions() { - - carter.setDateOfBirth(Date.valueOf(LocalDate.of(2000, 2, 1))); - dave.setDateOfBirth(Date.valueOf(LocalDate.of(2000, 1, 1))); - oliver.setDateOfBirth(Date.valueOf(LocalDate.of(2003, 5, 1))); - - List users = repository.findAll(QUser.user.dateOfBirth.yearMonth().asc()); - - assertThat(users).containsExactly(dave, carter, oliver); - } - - @Test // DATAJPA-665 - void shouldSupportExistsWithPredicate() { - - assertThat(repository.exists(user.firstname.eq("Dave"))).isTrue(); - assertThat(repository.exists(user.firstname.eq("Unknown"))).isFalse(); - assertThat(repository.exists((Predicate) null)).isTrue(); - } - - @Test // DATAJPA-679 - void shouldSupportFindAllWithPredicateAndSort() { - - List users = repository.findAll(user.dateOfBirth.isNull(), Sort.by(Direction.ASC, "firstname")); - - assertThat(users).contains(carter, dave, oliver); - } - - @Test // DATAJPA-585 - void worksWithUnpagedPageable() { - assertThat(repository.findAll(user.dateOfBirth.isNull(), Pageable.unpaged()).getContent()).hasSize(3); - } - - @Test // DATAJPA-912 - void pageableQueryReportsTotalFromResult() { - - Page firstPage = repository.findAll(user.dateOfBirth.isNull(), PageRequest.of(0, 10)); - assertThat(firstPage.getContent()).hasSize(3); - assertThat(firstPage.getTotalElements()).isEqualTo(3L); - - Page secondPage = repository.findAll(user.dateOfBirth.isNull(), PageRequest.of(1, 2)); - assertThat(secondPage.getContent()).hasSize(1); - assertThat(secondPage.getTotalElements()).isEqualTo(3L); - } - - @Test // DATAJPA-912 - void pageableQueryReportsTotalFromCount() { - - Page firstPage = repository.findAll(user.dateOfBirth.isNull(), PageRequest.of(0, 3)); - assertThat(firstPage.getContent()).hasSize(3); - assertThat(firstPage.getTotalElements()).isEqualTo(3L); - - Page secondPage = repository.findAll(user.dateOfBirth.isNull(), PageRequest.of(10, 10)); - assertThat(secondPage.getContent()).isEmpty(); - assertThat(secondPage.getTotalElements()).isEqualTo(3L); - } - - @Test // DATAJPA-1115 - void findOneWithPredicateReturnsResultCorrectly() { - assertThat(repository.findOne(user.eq(dave))).contains(dave); - } - - @Test // DATAJPA-1115 - void findOneWithPredicateReturnsOptionalEmptyWhenNoDataFound() { - assertThat(repository.findOne(user.firstname.eq("batman"))).isNotPresent(); - } - - @Test // DATAJPA-1115 - void findOneWithPredicateThrowsExceptionForNonUniqueResults() { - - assertThatExceptionOfType(IncorrectResultSizeDataAccessException.class) - .isThrownBy(() -> repository.findOne(user.emailAddress.contains("com"))); - } - - @Test // GH-2294 - void findByFluentQuery() { - - assertThatExceptionOfType(UnsupportedOperationException.class) - .isThrownBy(() -> repository.findBy(user.firstname.eq("Dave"), q -> q.sortBy(Sort.by("firstname")).all())); - } -}