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.
This commit is contained in:
Oliver Gierke
2014-07-16 13:51:46 +02:00
parent 2b4dfa2aeb
commit 3467d9257d
5 changed files with 62 additions and 9 deletions

View File

@@ -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<T, ID extends Serializable> 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<String, Object> hint : metadata.getQueryHints().entrySet()) {
query.setHint(hint.getKey(), hint.getValue());
}
return query;
}
}

View File

@@ -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<JPAQuery> createQuery() {
switch (provider) {
case ECLIPSELINK:
@@ -92,7 +93,7 @@ public class Querydsl {
*
* @return
*/
public JPQLQuery createQuery(EntityPath<?>... paths) {
public AbstractJPAQuery<JPAQuery> createQuery(EntityPath<?>... paths) {
return createQuery().from(paths);
}

View File

@@ -106,6 +106,10 @@ public class SimpleJpaRepository<T, ID extends Serializable> implements JpaRepos
this.crudMethodMetadata = crudMethodMetadata;
}
protected CrudMethodMetadata getRepositoryMethodMetadata() {
return crudMethodMetadata;
}
protected Class<T> getDomainClass() {
return entityInformation.getJavaType();
}

View File

@@ -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<Role> criteriaQuery;
@Mock JpaEntityInformation<Role, Integer> information;
@Mock TypedQuery<Role> query;
@Mock TypedQuery<Role> 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");
}
}

View File

@@ -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<Role, Integer> {
public interface RoleRepository extends CrudRepository<Role, Integer>, QueryDslPredicateExecutor<Role> {
/*
* (non-Javadoc)
@@ -47,6 +50,15 @@ public interface RoleRepository extends CrudRepository<Role, Integer> {
@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
*/