From 3467d9257dd68fac4df49b4529b8bc04bae1978e Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Wed, 16 Jul 2014 13:51:46 +0200 Subject: [PATCH] DATAJPA-574 - Implementation of QueryDslPredicateExecutor now considers lock mode and query hints. The Querydsl query creation now also leverages the CrudMethodMetadata instance held in SimpleJpaRepository to apply lock mode settings and query hints to the query to be executed. --- .../support/QueryDslJpaRepository.java | 20 ++++++++++++- .../data/jpa/repository/support/Querydsl.java | 5 ++-- .../support/SimpleJpaRepository.java | 4 +++ .../CrudMethodMetadataIntegrationTests.java | 28 +++++++++++++++---- .../jpa/repository/sample/RoleRepository.java | 14 +++++++++- 5 files changed, 62 insertions(+), 9 deletions(-) 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 d7695d854..5eccacd2a 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 @@ -18,8 +18,10 @@ package org.springframework.data.jpa.repository.support; import java.io.Serializable; import java.util.Collections; import java.util.List; +import java.util.Map.Entry; import javax.persistence.EntityManager; +import javax.persistence.LockModeType; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -30,6 +32,7 @@ import org.springframework.data.querydsl.QueryDslPredicateExecutor; import org.springframework.data.querydsl.SimpleEntityPathResolver; import com.mysema.query.jpa.JPQLQuery; +import com.mysema.query.jpa.impl.JPAQuery; import com.mysema.query.types.EntityPath; import com.mysema.query.types.OrderSpecifier; import com.mysema.query.types.Predicate; @@ -136,6 +139,21 @@ public class QueryDslJpaRepository extends SimpleJpa * @return the Querydsl {@link JPQLQuery}. */ protected JPQLQuery createQuery(Predicate... predicate) { - return querydsl.createQuery(path).where(predicate); + + JPAQuery query = querydsl.createQuery(path).where(predicate); + CrudMethodMetadata metadata = getRepositoryMethodMetadata(); + + if (metadata == null) { + return query; + } + + LockModeType type = metadata.getLockModeType(); + query = type == null ? query : query.setLockMode(type); + + for (Entry hint : metadata.getQueryHints().entrySet()) { + query.setHint(hint.getKey(), hint.getValue()); + } + + return query; } } 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 index 44883ae03..dd920481c 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/Querydsl.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/Querydsl.java @@ -30,6 +30,7 @@ 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.AbstractJPAQuery; import com.mysema.query.jpa.impl.JPAQuery; import com.mysema.query.support.Expressions; import com.mysema.query.types.EntityPath; @@ -72,7 +73,7 @@ public class Querydsl { * * @return */ - public JPQLQuery createQuery() { + public AbstractJPAQuery createQuery() { switch (provider) { case ECLIPSELINK: @@ -92,7 +93,7 @@ public class Querydsl { * * @return */ - public JPQLQuery createQuery(EntityPath... paths) { + public AbstractJPAQuery createQuery(EntityPath... paths) { return createQuery().from(paths); } diff --git a/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java b/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java index 67c9b2a98..c57e3ece8 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/SimpleJpaRepository.java @@ -106,6 +106,10 @@ public class SimpleJpaRepository implements JpaRepos this.crudMethodMetadata = crudMethodMetadata; } + protected CrudMethodMetadata getRepositoryMethodMetadata() { + return crudMethodMetadata; + } + protected Class getDomainClass() { return entityInformation.getJavaType(); } diff --git a/src/test/java/org/springframework/data/jpa/repository/CrudMethodMetadataIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/CrudMethodMetadataIntegrationTests.java index de7835478..0bb0f3f03 100644 --- a/src/test/java/org/springframework/data/jpa/repository/CrudMethodMetadataIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/CrudMethodMetadataIntegrationTests.java @@ -28,11 +28,13 @@ import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; +import org.hibernate.ejb.HibernateEntityManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.data.jpa.domain.sample.QRole; import org.springframework.data.jpa.domain.sample.Role; import org.springframework.data.jpa.repository.sample.RoleRepository; import org.springframework.data.jpa.repository.support.JpaEntityInformation; @@ -50,7 +52,8 @@ public class CrudMethodMetadataIntegrationTests { @Mock CriteriaBuilder builder; @Mock CriteriaQuery criteriaQuery; @Mock JpaEntityInformation information; - @Mock TypedQuery query; + @Mock TypedQuery typedQuery; + @Mock javax.persistence.Query query; RoleRepository repository; @@ -78,13 +81,13 @@ public class CrudMethodMetadataIntegrationTests { when(em.getCriteriaBuilder()).thenReturn(builder); when(builder.createQuery(Role.class)).thenReturn(criteriaQuery); - when(em.createQuery(criteriaQuery)).thenReturn(query); - when(query.setLockMode(any(LockModeType.class))).thenReturn(query); + when(em.createQuery(criteriaQuery)).thenReturn(typedQuery); + when(typedQuery.setLockMode(any(LockModeType.class))).thenReturn(typedQuery); repository.findAll(); - verify(query).setLockMode(LockModeType.READ); - verify(query).setHint("foo", "bar"); + verify(typedQuery).setLockMode(LockModeType.READ); + verify(typedQuery).setHint("foo", "bar"); } /** @@ -100,4 +103,19 @@ public class CrudMethodMetadataIntegrationTests { verify(em).find(Role.class, 1, expectedLockModeType, expectedLinks); } + + /** + * @see DATAJPA-574 + */ + @Test + public void appliesLockModeAndQueryHintsToQuerydslQuery() { + + when(em.getDelegate()).thenReturn(mock(HibernateEntityManager.class)); + when(em.createQuery(anyString())).thenReturn(query); + + repository.findOne(QRole.role.name.eq("role")); + + verify(query).setLockMode(LockModeType.READ); + verify(query).setHint("foo", "bar"); + } } diff --git a/src/test/java/org/springframework/data/jpa/repository/sample/RoleRepository.java b/src/test/java/org/springframework/data/jpa/repository/sample/RoleRepository.java index f34b54f86..976810bc6 100644 --- a/src/test/java/org/springframework/data/jpa/repository/sample/RoleRepository.java +++ b/src/test/java/org/springframework/data/jpa/repository/sample/RoleRepository.java @@ -21,15 +21,18 @@ import javax.persistence.QueryHint; import org.springframework.data.jpa.domain.sample.Role; import org.springframework.data.jpa.repository.Lock; import org.springframework.data.jpa.repository.QueryHints; +import org.springframework.data.querydsl.QueryDslPredicateExecutor; import org.springframework.data.repository.CrudRepository; +import com.mysema.query.types.Predicate; + /** * Typing interface for {@code Role}. * * @author Oliver Gierke * @author Thomas Darimont */ -public interface RoleRepository extends CrudRepository { +public interface RoleRepository extends CrudRepository, QueryDslPredicateExecutor { /* * (non-Javadoc) @@ -47,6 +50,15 @@ public interface RoleRepository extends CrudRepository { @QueryHints(@QueryHint(name = "foo", value = "bar")) Role findOne(Integer id); + /* + * (non-Javadoc) + * @see org.springframework.data.querydsl.QueryDslPredicateExecutor#findOne(com.mysema.query.types.Predicate) + */ + @Override + @Lock(LockModeType.READ) + @QueryHints(@QueryHint(name = "foo", value = "bar")) + Role findOne(Predicate predicate); + /** * @see DATAJPA-509 */