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 d7695d854c..5eccacd2a3 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 @@ 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.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 long count(Predicate predicate) { * @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 44883ae038..dd920481ca 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.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 Querydsl(EntityManager em, PathBuilder builder) { * * @return */ - public JPQLQuery createQuery() { + public AbstractJPAQuery createQuery() { switch (provider) { case ECLIPSELINK: @@ -92,7 +93,7 @@ public JPQLQuery createQuery() { * * @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 67c9b2a98d..c57e3ece86 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 void setRepositoryMethodMetadata(CrudMethodMetadata crudMethodMetadata) { 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 de7835478c..0bb0f3f036 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.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 void usesLockInformationAnnotatedAtRedeclaredMethod() { 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 void usesMetadataAnnotatedAtRedeclaredFindOne() { 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 f34b54f867..976810bc64 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 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 */