diff --git a/src/main/java/org/springframework/data/jpa/repository/support/QueryDslJpaRepository.java b/src/main/java/org/springframework/data/jpa/repository/support/QueryDslJpaRepository.java index b25d0c5b2..0c36f096a 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/QueryDslJpaRepository.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/QueryDslJpaRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 the original author or authors. + * Copyright 2008-2012 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. @@ -23,15 +23,12 @@ import javax.persistence.EntityManager; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; -import org.springframework.data.domain.Sort; -import org.springframework.data.domain.Sort.Order; import org.springframework.data.querydsl.EntityPathResolver; import org.springframework.data.querydsl.QueryDslPredicateExecutor; import org.springframework.data.querydsl.SimpleEntityPathResolver; import com.mysema.query.jpa.JPQLQuery; import com.mysema.query.types.EntityPath; -import com.mysema.query.types.Expression; import com.mysema.query.types.OrderSpecifier; import com.mysema.query.types.Predicate; import com.mysema.query.types.path.PathBuilder; @@ -47,10 +44,9 @@ public class QueryDslJpaRepository extends SimpleJpa private static final EntityPathResolver DEFAULT_ENTITY_PATH_RESOLVER = SimpleEntityPathResolver.INSTANCE; - private final EntityManager em; private final EntityPath path; private final PathBuilder builder; - private final PersistenceProvider provider; + private final Querydsl querydsl; /** * Creates a new {@link QueryDslJpaRepository} from the given domain class and {@link EntityManager}. This will use @@ -60,7 +56,6 @@ public class QueryDslJpaRepository extends SimpleJpa * @param entityManager must not be {@literal null}. */ public QueryDslJpaRepository(JpaEntityInformation entityInformation, EntityManager entityManager) { - this(entityInformation, entityManager, DEFAULT_ENTITY_PATH_RESOLVER); } @@ -76,10 +71,10 @@ public class QueryDslJpaRepository extends SimpleJpa EntityPathResolver resolver) { super(entityInformation, entityManager); - this.em = entityManager; + this.path = resolver.createPath(entityInformation.getJavaType()); this.builder = new PathBuilder(path.getType(), path.getMetadata()); - this.provider = PersistenceProvider.fromEntityManager(entityManager); + this.querydsl = new Querydsl(entityManager, builder); } /* @@ -113,7 +108,7 @@ public class QueryDslJpaRepository extends SimpleJpa public Page findAll(Predicate predicate, Pageable pageable) { JPQLQuery countQuery = createQuery(predicate); - JPQLQuery query = applyPagination(createQuery(predicate), pageable); + JPQLQuery query = querydsl.applyPagination(pageable, createQuery(predicate)); return new PageImpl(query.list(path), pageable, countQuery.count()); } @@ -133,60 +128,6 @@ public class QueryDslJpaRepository extends SimpleJpa * @return the Querydsl {@link JPQLQuery}. */ protected JPQLQuery createQuery(Predicate... predicate) { - return QuerydslUtils.createQueryInstance(em, provider).from(path).where(predicate); - } - - /** - * Applies the given {@link Pageable} to the given {@link JPQLQuery}. - * - * @param query must not be {@literal null}. - * @param pageable - * @return the Querydsl {@link JPQLQuery}. - */ - protected JPQLQuery applyPagination(JPQLQuery query, Pageable pageable) { - - if (pageable == null) { - return query; - } - - query.offset(pageable.getOffset()); - query.limit(pageable.getPageSize()); - - return applySorting(query, pageable.getSort()); - } - - /** - * Applies sorting to the given {@link JPQLQuery}. - * - * @param query must not be {@literal null}. - * @param sort - * @return the Querydsl {@link JPQLQuery} - */ - protected JPQLQuery applySorting(JPQLQuery query, Sort sort) { - - if (sort == null) { - return query; - } - - for (Order order : sort) { - query.orderBy(toOrder(order)); - } - - return query; - } - - /** - * Transforms a plain {@link Order} into a QueryDsl specific {@link OrderSpecifier}. - * - * @param order - * @return - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - protected OrderSpecifier toOrder(Order order) { - - Expression property = builder.get(order.getProperty()); - - return new OrderSpecifier(order.isAscending() ? com.mysema.query.types.Order.ASC - : com.mysema.query.types.Order.DESC, property); + return querydsl.createQuery(path).where(predicate); } } diff --git a/src/main/java/org/springframework/data/jpa/repository/support/QueryDslRepositorySupport.java b/src/main/java/org/springframework/data/jpa/repository/support/QueryDslRepositorySupport.java index 782e5139a..878bac417 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/QueryDslRepositorySupport.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/QueryDslRepositorySupport.java @@ -39,9 +39,20 @@ import com.mysema.query.types.path.PathBuilderFactory; @Repository public abstract class QueryDslRepositorySupport { - private PathBuilderFactory builderFactory = new PathBuilderFactory(); + private final PathBuilder builder; + private EntityManager entityManager; - private PersistenceProvider provider; + private Querydsl querydsl; + + /** + * Creates a new {@link QueryDslRepositorySupport} instance for the given domain type. + * + * @param domainClass must not be {@literal null}. + */ + public QueryDslRepositorySupport(Class domainClass) { + Assert.notNull(domainClass); + this.builder = new PathBuilderFactory().create(domainClass); + } /** * Setter to inject {@link EntityManager}. @@ -52,8 +63,8 @@ public abstract class QueryDslRepositorySupport { public void setEntityManager(EntityManager entityManager) { Assert.notNull(entityManager); + this.querydsl = new Querydsl(entityManager, builder); this.entityManager = entityManager; - this.provider = PersistenceProvider.fromEntityManager(entityManager); } /** @@ -62,6 +73,7 @@ public abstract class QueryDslRepositorySupport { @PostConstruct public void validate() { Assert.notNull(entityManager, "EntityManager must not be null!"); + Assert.notNull(querydsl, "Querydsl must not be null!"); } /** @@ -79,7 +91,7 @@ public abstract class QueryDslRepositorySupport { * @return the Querydsl {@link JPQLQuery}. */ protected JPQLQuery from(EntityPath... paths) { - return QuerydslUtils.createQueryInstance(entityManager, provider).from(paths); + return querydsl.createQuery(paths); } /** @@ -89,7 +101,6 @@ public abstract class QueryDslRepositorySupport { * @return the Querydsl {@link DeleteClause}. */ protected DeleteClause delete(EntityPath path) { - return new JPADeleteClause(entityManager, path); } @@ -100,19 +111,26 @@ public abstract class QueryDslRepositorySupport { * @return the Querydsl {@link UpdateClause}. */ protected UpdateClause update(EntityPath path) { - return new JPAUpdateClause(entityManager, path); } /** - * Returns a {@link PathBuilder} for the given type. + * Returns a {@link PathBuilder} for the configured domain type. * * @param - * @param type * @return the Querdsl {@link PathBuilder}. */ - protected PathBuilder getBuilder(Class type) { + @SuppressWarnings("unchecked") + protected PathBuilder getBuilder() { + return (PathBuilder) builder; + } - return builderFactory.create(type); + /** + * Returns the underlying Querydsl helper instance. + * + * @return + */ + protected Querydsl getQuerydsl() { + return this.querydsl; } } diff --git a/src/main/java/org/springframework/data/jpa/repository/support/Querydsl.java b/src/main/java/org/springframework/data/jpa/repository/support/Querydsl.java new file mode 100644 index 000000000..dea0f96b9 --- /dev/null +++ b/src/main/java/org/springframework/data/jpa/repository/support/Querydsl.java @@ -0,0 +1,144 @@ +/* + * Copyright 2012 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 + * + * http://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 javax.persistence.EntityManager; + +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.domain.Sort.Order; +import org.springframework.util.Assert; + +import com.mysema.query.jpa.EclipseLinkTemplates; +import com.mysema.query.jpa.HQLTemplates; +import com.mysema.query.jpa.JPQLQuery; +import com.mysema.query.jpa.OpenJPATemplates; +import com.mysema.query.jpa.impl.JPAQuery; +import com.mysema.query.types.EntityPath; +import com.mysema.query.types.Expression; +import com.mysema.query.types.OrderSpecifier; +import com.mysema.query.types.path.PathBuilder; + +/** + * Helper instance to ease access to Querydsl JPA query API. + * + * @author Oliver Gierke + */ +public class Querydsl { + + private final EntityManager em; + private final PersistenceProvider provider; + private final PathBuilder builder; + + /** + * Creates a new {@link Querydsl} for the given {@link EntityManager} and {@link PathBuilder}. + * + * @param em must not be {@literal null}. + * @param builder must not be {@literal null}. + */ + public Querydsl(EntityManager em, PathBuilder builder) { + + Assert.notNull(em); + Assert.notNull(builder); + + this.em = em; + this.provider = PersistenceProvider.fromEntityManager(em); + this.builder = builder; + } + + /** + * Creates the {@link JPQLQuery} instance based on the configured {@link EntityManager}. + * + * @return + */ + public JPQLQuery createQuery() { + + switch (provider) { + case ECLIPSELINK: + return new JPAQuery(em, EclipseLinkTemplates.DEFAULT); + case HIBERNATE: + return new JPAQuery(em, HQLTemplates.DEFAULT); + case OPEN_JPA: + return new JPAQuery(em, OpenJPATemplates.DEFAULT); + case GENERIC_JPA: + default: + return new JPAQuery(em); + } + } + + /** + * Creates the {@link JPQLQuery} instance based on the configured {@link EntityManager}. + * + * @return + */ + public JPQLQuery createQuery(EntityPath... paths) { + return createQuery().from(paths); + } + + /** + * Applies the given {@link Pageable} to the given {@link JPQLQuery}. + * + * @param pageable + * @param query must not be {@literal null}. + * @return the Querydsl {@link JPQLQuery}. + */ + public JPQLQuery applyPagination(Pageable pageable, JPQLQuery query) { + + if (pageable == null) { + return query; + } + + query.offset(pageable.getOffset()); + query.limit(pageable.getPageSize()); + + return query; + } + + /** + * Applies sorting to the given {@link JPQLQuery}. + * + * @param sort + * @param query must not be {@literal null}. + * @return the Querydsl {@link JPQLQuery} + */ + public JPQLQuery applySorting(Sort sort, JPQLQuery query) { + + if (sort == null) { + return query; + } + + for (Order order : sort) { + query.orderBy(toOrder(order)); + } + + return query; + } + + /** + * Transforms a plain {@link Order} into a QueryDsl specific {@link OrderSpecifier}. + * + * @param order + * @return + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + private OrderSpecifier toOrder(Order order) { + + Expression property = builder.get(order.getProperty()); + + return new OrderSpecifier(order.isAscending() ? com.mysema.query.types.Order.ASC + : com.mysema.query.types.Order.DESC, property); + } +} diff --git a/src/main/java/org/springframework/data/jpa/repository/support/QuerydslUtils.java b/src/main/java/org/springframework/data/jpa/repository/support/QuerydslUtils.java deleted file mode 100644 index c3efe73f3..000000000 --- a/src/main/java/org/springframework/data/jpa/repository/support/QuerydslUtils.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2012 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 - * - * http://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 javax.persistence.EntityManager; - -import com.mysema.query.jpa.EclipseLinkTemplates; -import com.mysema.query.jpa.HQLTemplates; -import com.mysema.query.jpa.JPQLQuery; -import com.mysema.query.jpa.OpenJPATemplates; -import com.mysema.query.jpa.impl.JPAQuery; - -/** - * Utility methods for Querydsl. - * - * @author Oliver Gierke - */ -class QuerydslUtils { - - private QuerydslUtils() { - - } - - /** - * Creates the {@link JPQLQuery} instance based on the given {@link EntityManager} and {@link PersistenceProvider}. - * - * @return - */ - public static JPQLQuery createQueryInstance(EntityManager em, PersistenceProvider provider) { - - switch (provider) { - case ECLIPSELINK: - return new JPAQuery(em, EclipseLinkTemplates.DEFAULT); - case HIBERNATE: - return new JPAQuery(em, HQLTemplates.DEFAULT); - case OPEN_JPA: - return new JPAQuery(em, OpenJPATemplates.DEFAULT); - case GENERIC_JPA: - default: - return new JPAQuery(em); - } - } -} diff --git a/src/test/java/org/springframework/data/jpa/repository/support/QueryDslRepositorySupportIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/support/QueryDslRepositorySupportIntegrationTests.java index 7d5db1b45..a34fc000b 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/QueryDslRepositorySupportIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/QueryDslRepositorySupportIntegrationTests.java @@ -24,6 +24,7 @@ import javax.persistence.PersistenceContext; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.jpa.domain.sample.User; import org.springframework.data.jpa.repository.support.QueryDslRepositorySupportTests.UserRepository; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -63,6 +64,10 @@ public class QueryDslRepositorySupportIntegrationTests { static class ReconfiguringUserRepositoryImpl extends QueryDslRepositorySupport { + public ReconfiguringUserRepositoryImpl() { + super(User.class); + } + @Override @PersistenceContext(unitName = "querydsl") public void setEntityManager(EntityManager entityManager) { diff --git a/src/test/java/org/springframework/data/jpa/repository/support/QueryDslRepositorySupportTests.java b/src/test/java/org/springframework/data/jpa/repository/support/QueryDslRepositorySupportTests.java index 48b5ba255..4aef7df47 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/QueryDslRepositorySupportTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/QueryDslRepositorySupportTests.java @@ -127,6 +127,10 @@ public class QueryDslRepositorySupportTests { private static final QUser user = QUser.user; + public UserRepositoryImpl() { + super(User.class); + } + @Override @PersistenceContext(unitName = "default") public void setEntityManager(EntityManager entityManager) {