Adapted refactorings in Spring Data Commons.

This commit is contained in:
Oliver Gierke
2011-02-25 14:45:03 +01:00
parent 4d50569470
commit bd949cf823
19 changed files with 350 additions and 238 deletions

View File

@@ -17,8 +17,14 @@ package org.springframework.data.jpa.repository.query;
import javax.persistence.EntityManager;
import org.springframework.data.jpa.repository.query.JpaQueryExecution.CollectionExecution;
import org.springframework.data.jpa.repository.query.JpaQueryExecution.ModifyingExecution;
import org.springframework.data.jpa.repository.query.JpaQueryExecution.PagedExecution;
import org.springframework.data.jpa.repository.query.JpaQueryExecution.SingleEntityExecution;
import org.springframework.data.repository.query.Parameters;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.support.EntityMetadata;
import org.springframework.util.Assert;
@@ -29,8 +35,7 @@ import org.springframework.util.Assert;
*/
public abstract class AbstractJpaQuery implements RepositoryQuery {
private final Parameters parameters;
private final JpaQueryExecution execution;
private final JpaQueryMethod method;
private final EntityManager em;
@@ -46,18 +51,30 @@ public abstract class AbstractJpaQuery implements RepositoryQuery {
Assert.notNull(method);
Assert.notNull(em);
this.parameters = method.getParameters();
this.execution = method.getExecution();
this.method = method;
this.em = em;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.query.RepositoryQuery#getQueryMethod
* ()
*/
public QueryMethod getQueryMethod() {
return method;
}
/**
* @return the parameters
*/
public Parameters getParameters() {
return parameters;
return method.getParameters();
}
@@ -79,7 +96,25 @@ public abstract class AbstractJpaQuery implements RepositoryQuery {
*/
public Object execute(Object[] parameters) {
return doExecute(execution, parameters);
return doExecute(getExecution(), parameters);
}
protected JpaQueryExecution getExecution() {
switch (method.getType()) {
case COLLECTION:
return new CollectionExecution();
case PAGING:
return new PagedExecution(getParameters());
case MODIFYING:
EntityMetadata<?> metadata = method.getEntityMetadata();
return method.getClearAutomatically() ? new ModifyingExecution(
metadata, em) : new ModifyingExecution(metadata, null);
default:
return new SingleEntityExecution();
}
}

View File

@@ -15,8 +15,6 @@
*/
package org.springframework.data.jpa.repository.query;
import java.lang.reflect.Method;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;
@@ -27,6 +25,7 @@ import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.Parameters;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.repository.support.EntityMetadata;
import org.springframework.util.Assert;
@@ -219,9 +218,9 @@ public abstract class JpaQueryExecution {
*
* @param em
*/
public ModifyingExecution(Method method, EntityManager em) {
public ModifyingExecution(EntityMetadata<?> metadata, EntityManager em) {
Class<?> type = method.getReturnType();
Class<?> type = metadata.getJavaType();
boolean isVoid = void.class.equals(type) || Void.class.equals(type);
boolean isInt =

View File

@@ -70,7 +70,7 @@ public final class JpaQueryLookupStrategy {
public final RepositoryQuery resolveQuery(Method method,
Class<?> domainClass) {
return resolveQuery(new JpaQueryMethod(method, provider, em), em);
return resolveQuery(new JpaQueryMethod(method, provider), em);
}

View File

@@ -22,17 +22,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.QueryHint;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.data.jpa.repository.query.JpaQueryExecution.CollectionExecution;
import org.springframework.data.jpa.repository.query.JpaQueryExecution.ModifyingExecution;
import org.springframework.data.jpa.repository.query.JpaQueryExecution.PagedExecution;
import org.springframework.data.jpa.repository.query.JpaQueryExecution.SingleEntityExecution;
import org.springframework.data.repository.query.Parameters;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.util.Assert;
@@ -47,7 +42,6 @@ import org.springframework.util.StringUtils;
public class JpaQueryMethod extends QueryMethod {
private final QueryExtractor extractor;
private final EntityManager em;
private final Method method;
@@ -56,55 +50,26 @@ public class JpaQueryMethod extends QueryMethod {
*
* @param method must not be {@literal null}
* @param extractor must not be {@literal null}
* @param em must not be {@literal null}
* @param metadata must not be {@literal null}
*/
public JpaQueryMethod(Method method, QueryExtractor extractor,
EntityManager em) {
public JpaQueryMethod(Method method, QueryExtractor extractor) {
super(method);
Assert.notNull(method, "Method must not be null!");
Assert.notNull(extractor, "Query extractor must not be null!");
Assert.notNull(em, "EntityManager must not be null!");
this.method = method;
this.extractor = extractor;
this.em = em;
Assert.isTrue(!(isModifyingQuery() && getParameters()
.hasSpecialParameter()), String.format(
"Modifying method must not contain %s!", Parameters.TYPES));
if (getParameters().hasPageableParameter()
&& !extractor.canExtractQuery()) {
throw new IllegalArgumentException(
"You cannot use Pageable as method parameter if your "
+ "persistence provider cannot extract queries!");
}
}
/**
* Returns the {@link JpaQueryExecution}.
*
* @return
*/
public JpaQueryExecution getExecution() {
if (isCollectionQuery()) {
return new CollectionExecution();
}
if (isPageQuery()) {
return new PagedExecution(getParameters());
}
if (isModifyingQuery()) {
return getClearAutomatically() ? new ModifyingExecution(method, em)
: new ModifyingExecution(method, null);
}
return new SingleEntityExecution();
Assert.isTrue(!(getParameters().hasPageableParameter() && !extractor
.canExtractQuery()),
"You cannot use Pageable as method parameter if your "
+ "persistence provider cannot extract queries!");
}
@@ -113,7 +78,8 @@ public class JpaQueryMethod extends QueryMethod {
*
* @return
*/
final boolean isModifyingQuery() {
@Override
protected boolean isModifyingQuery() {
return null != AnnotationUtils.findAnnotation(method, Modifying.class);
}
@@ -157,7 +123,8 @@ public class JpaQueryMethod extends QueryMethod {
*/
String getNamedQueryName() {
return String.format("%s.%s", getDomainClass().getSimpleName(),
Class<?> domainClass = getDomainClass();
return String.format("%s.%s", domainClass.getSimpleName(),
method.getName());
}
@@ -192,6 +159,18 @@ public class JpaQueryMethod extends QueryMethod {
}
/**
* Returns whether we should clear automatically for modifying queries.
*
* @return
*/
boolean getClearAutomatically() {
return (Boolean) AnnotationUtils.getValue(
method.getAnnotation(Modifying.class), "clearAutomatically");
}
/**
* Returns the {@link Query} annotation that is applied to the method or
* {@code null} if none available.
@@ -202,16 +181,4 @@ public class JpaQueryMethod extends QueryMethod {
return method.getAnnotation(Query.class);
}
/**
* Returns whether we should clear automatically for modifying queries.
*
* @return
*/
private boolean getClearAutomatically() {
return (Boolean) AnnotationUtils.getValue(
method.getAnnotation(Modifying.class), "clearAutomatically");
}
}

View File

@@ -23,7 +23,9 @@ import javax.persistence.criteria.CriteriaQuery;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.data.repository.support.EntityMetadata;
/**
@@ -34,7 +36,7 @@ import org.springframework.data.repository.query.parser.PartTree;
public class PartTreeJpaQuery extends AbstractJpaQuery {
private final PartTree tree;
private final Class<?> domainClass;
private final QueryMethod method;
/**
@@ -46,9 +48,10 @@ public class PartTreeJpaQuery extends AbstractJpaQuery {
public PartTreeJpaQuery(JpaQueryMethod method, EntityManager em) {
super(method, em);
this.tree = new PartTree(method.getName(), method.getDomainClass());
this.domainClass = method.getDomainClass();
this.tree =
new PartTree(method.getName(), method.getEntityMetadata()
.getJavaType());
this.method = method;
}
@@ -65,8 +68,9 @@ public class PartTreeJpaQuery extends AbstractJpaQuery {
ParameterAccessor accessor =
new ParametersParameterAccessor(getParameters(), parameters);
EntityMetadata<?> metadata = method.getEntityMetadata();
JpaQueryCreator jpaQueryCreator =
new JpaQueryCreator(tree, accessor, domainClass,
new JpaQueryCreator(tree, accessor, metadata.getJavaType(),
getEntityManager());
TypedQuery<Object> query =
@@ -92,8 +96,9 @@ public class PartTreeJpaQuery extends AbstractJpaQuery {
CriteriaQuery<Object> query =
new JpaCountQueryCreator(tree, new ParametersParameterAccessor(
getParameters(), parameters), domainClass,
getEntityManager()).createQuery();
getParameters(), parameters), method
.getEntityMetadata().getJavaType(), getEntityManager())
.createQuery();
return getEntityManager().createQuery(query);
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2011 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.metamodel.SingularAttribute;
import org.springframework.data.repository.support.EntityInformation;
/**
* Extension of {@link EntityInformation} to capture aditional JPA specific
* information about entities.
*
* @author Oliver Gierke
*/
public interface JpaEntityInformation<T> extends EntityInformation<T> {
/**
* Returns the id attribute of the entity.
*
* @return
*/
SingularAttribute<? super T, ?> getIdAttribute();
}

View File

@@ -23,7 +23,8 @@ import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.Metamodel;
import javax.persistence.metamodel.SingularAttribute;
import org.springframework.data.repository.support.AbstractEntityMetadata;
import org.springframework.data.repository.support.AbstractEntityInformation;
import org.springframework.data.repository.support.EntityInformation;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
@@ -34,27 +35,32 @@ import org.springframework.util.ReflectionUtils;
*
* @author Oliver Gierke
*/
public class JpaMetamodelEntityMetadata<T> extends AbstractEntityMetadata<T> {
public class JpaMetamodelEntityInformation<T> extends AbstractEntityInformation<T>
implements JpaEntityInformation<T> {
private final Member member;
private final SingularAttribute<? super T, ?> attribute;
/**
* Creates a new {@link JpaMetamodelEntityMetadata} for the given domain
* Creates a new {@link JpaMetamodelEntityInformation} for the given domain
* class and {@link Metamodel}.
*
* @param domainClass
* @param metamodel
*/
public JpaMetamodelEntityMetadata(Class<T> domainClass, Metamodel metamodel) {
public JpaMetamodelEntityInformation(Class<T> domainClass, Metamodel metamodel) {
super(domainClass);
Assert.notNull(metamodel);
EntityType<?> type = metamodel.entity(domainClass);
SingularAttribute<?, ?> idAttribute =
type.getId(type.getIdType().getJavaType());
this.member = idAttribute.getJavaMember();
EntityType<T> type = metamodel.entity(domainClass);
if (type == null) {
throw new IllegalArgumentException(
"The given domain class can not be found in the given Metamodel!");
}
this.attribute = type.getId(type.getIdType().getJavaType());
}
@@ -65,9 +71,9 @@ public class JpaMetamodelEntityMetadata<T> extends AbstractEntityMetadata<T> {
* org.springframework.data.repository.support.IdAware#getId(java.lang.Object
* )
*/
public Object getId(Object entity) {
public Object getId(T entity) {
return getMemberValue(member, entity);
return getMemberValue(attribute.getJavaMember(), entity);
}
@@ -94,4 +100,16 @@ public class JpaMetamodelEntityMetadata<T> extends AbstractEntityMetadata<T> {
throw new IllegalArgumentException(
"Given member is neither Field nor Method!");
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.jpa.repository.support.JpaEntityMetadata#
* getIdAttribute()
*/
public SingularAttribute<? super T, ?> getIdAttribute() {
return attribute;
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2011 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 java.io.Serializable;
import javax.persistence.metamodel.Metamodel;
import org.springframework.data.domain.Persistable;
/**
* Extension of {@link JpaMetamodelEntityInformation} that consideres methods of
* {@link Persistable} to lookup the id.
*
* @author Oliver Gierke
*/
public class JpaPersistableEntityInformation<T extends Persistable> extends
JpaMetamodelEntityInformation<T> {
/**
* Creates a new {@link JpaPersistableEntityInformation} for the given
* domain class and {@link Metamodel}.
*
* @param domainClass
* @param metamodel
*/
public JpaPersistableEntityInformation(Class<T> domainClass,
Metamodel metamodel) {
super(domainClass, metamodel);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.jpa.repository.support.JpaMetamodelEntityMetadata
* #getId(java.lang.Object)
*/
@Override
public Serializable getId(T entity) {
return entity.getId();
}
}

View File

@@ -17,13 +17,11 @@ package org.springframework.data.jpa.repository.support;
import javax.persistence.EntityManager;
import org.springframework.data.domain.Persistable;
import org.springframework.data.jpa.repository.query.JpaQueryLookupStrategy;
import org.springframework.data.jpa.repository.query.QueryExtractor;
import org.springframework.data.jpa.repository.utils.JpaClassUtils;
import org.springframework.data.repository.query.QueryLookupStrategy;
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
import org.springframework.data.repository.support.EntityMetadata;
import org.springframework.data.repository.support.PersistableEntityMetadata;
import org.springframework.data.repository.support.RepositoryFactorySupport;
import org.springframework.data.repository.support.RepositoryMetadata;
import org.springframework.util.Assert;
@@ -81,32 +79,15 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport {
protected Object getTargetRepository(RepositoryMetadata metadata,
EntityManager entityManager) {
return new SimpleJpaRepository(createEntityInformation(
metadata.getDomainClass(), entityManager), entityManager);
JpaEntityInformation<?> entityMetadata =
getEntityMetadata(metadata.getDomainClass());
return new SimpleJpaRepository(entityMetadata, entityManager);
}
/**
* Creates a new {@link EntityMetadata} instance for the given domain class
* and {@link EntityManager}. Default implementation will use a
* {@link PersistableMetadata} for domain classes implementing
* {@link Persistable} and fall back to the JPA meta model though
* {@link JpaMetamodelEntityInformation} otherwise.
*
* @param domainClass
* @param em
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
protected EntityMetadata<?> createEntityInformation(Class<?> domainClass,
EntityManager em) {
protected JpaEntityInformation<?> getEntityMetadata(Class<?> domainClass) {
if (Persistable.class.isAssignableFrom(domainClass)) {
return new PersistableEntityMetadata(domainClass);
} else {
return new JpaMetamodelEntityMetadata(domainClass,
em.getMetamodel());
}
return JpaClassUtils.getMetadata(domainClass, entityManager);
}

View File

@@ -39,17 +39,6 @@ public class JpaRepositoryFactoryBean<T extends JpaRepository<?, ?>> extends
private EntityManager entityManager;
public static <S extends JpaRepository<?, ?>> JpaRepositoryFactoryBean<S> create(
Class<S> repositoryInterface, EntityManager em) {
JpaRepositoryFactoryBean<S> factory = new JpaRepositoryFactoryBean<S>();
factory.setRepositoryInterface(repositoryInterface);
factory.setEntityManager(em);
return factory;
}
/**
* The {@link EntityManager} to be used.
*
@@ -65,12 +54,11 @@ public class JpaRepositoryFactoryBean<T extends JpaRepository<?, ?>> extends
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryFactoryBeanSupport
* #createRepositoryFactory()
* @see org.springframework.data.repository.support.
* TransactionalRepositoryFactoryBeanSupport#doCreateRepositoryFactory()
*/
@Override
protected RepositoryFactorySupport createRepositoryFactory() {
protected RepositoryFactorySupport doCreateRepositoryFactory() {
return createRepositoryFactory(entityManager);
}

View File

@@ -19,6 +19,7 @@ import static org.springframework.data.jpa.repository.query.QueryUtils.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityManager;
@@ -26,6 +27,7 @@ import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
@@ -36,7 +38,6 @@ import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.support.EntityMetadata;
import org.springframework.util.Assert;
@@ -53,7 +54,7 @@ import org.springframework.util.Assert;
public class SimpleJpaRepository<T, ID extends Serializable> implements
JpaRepository<T, ID> {
private final EntityMetadata<T> entityInformation;
private final JpaEntityInformation<T> entityInformation;
private final EntityManager em;
private final PersistenceProvider provider;
@@ -62,15 +63,15 @@ public class SimpleJpaRepository<T, ID extends Serializable> implements
* Creates a new {@link SimpleJpaRepository} to manage objects of the given
* domain type.
*
* @param entityInformation
* @param entityMetadata
* @param entityManager
*/
public SimpleJpaRepository(EntityMetadata<T> entityInformation,
public SimpleJpaRepository(JpaEntityInformation<T> entityMetadata,
EntityManager entityManager) {
Assert.notNull(entityInformation);
Assert.notNull(entityMetadata);
Assert.notNull(entityManager);
this.entityInformation = entityInformation;
this.entityInformation = entityMetadata;
this.em = entityManager;
this.provider = PersistenceProvider.fromEntityManager(entityManager);
}

View File

@@ -17,7 +17,12 @@ package org.springframework.data.jpa.repository.utils;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.metamodel.Metamodel;
import org.springframework.data.domain.Persistable;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation;
import org.springframework.data.jpa.repository.support.JpaPersistableEntityInformation;
import org.springframework.util.StringUtils;
@@ -75,4 +80,30 @@ public abstract class JpaClassUtils {
return hasName ? entity.name() : domainClass.getSimpleName();
}
/**
* Creates a {@link JpaEntityInformation} for the given domain class and
* {@link EntityManager}.
*
* @param domainClass
* @param em
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static JpaEntityInformation<?> getMetadata(Class<?> domainClass,
EntityManager em) {
Metamodel metamodel = em.getMetamodel();
if (Persistable.class.isAssignableFrom(domainClass)) {
return new JpaPersistableEntityInformation(domainClass, metamodel);
} else {
try {
return new JpaMetamodelEntityInformation(domainClass, metamodel);
} catch (IllegalArgumentException e) {
return null;
}
}
}
}

View File

@@ -19,8 +19,8 @@ import java.io.Serializable;
import javax.persistence.EntityManager;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.repository.support.EntityMetadata;
/**
@@ -36,7 +36,7 @@ public class CustomGenericJpaRepository<T, ID extends Serializable> extends
* @param domainClass
* @param entityManager
*/
public CustomGenericJpaRepository(EntityMetadata<T> metadata,
public CustomGenericJpaRepository(JpaEntityInformation<T> metadata,
EntityManager entityManager) {
super(metadata, entityManager);

View File

@@ -21,8 +21,8 @@ import java.io.Serializable;
import javax.persistence.EntityManager;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.repository.support.EntityMetadata;
import org.springframework.data.repository.support.RepositoryMetadata;
@@ -55,7 +55,8 @@ public class CustomGenericJpaRepositoryFactory extends JpaRepositoryFactory {
protected Object getTargetRepository(RepositoryMetadata metadata,
EntityManager em) {
EntityMetadata<Object> entityMetadata = mock(EntityMetadata.class);
JpaEntityInformation<Object> entityMetadata =
mock(JpaEntityInformation.class);
when(entityMetadata.getJavaType()).thenReturn(
(Class<Object>) metadata.getDomainClass());
return new CustomGenericJpaRepository<Object, Serializable>(

View File

@@ -20,18 +20,17 @@ import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import java.lang.reflect.Method;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.OngoingStubbing;
import org.springframework.data.jpa.repository.query.JpaQueryExecution.ModifyingExecution;
import org.springframework.data.repository.support.EntityMetadata;
/**
@@ -50,15 +49,8 @@ public class JpaQueryExecutionUnitTests {
ParameterBinder binder;
@Mock
Query query;
Method method;
@Before
public void setUp() throws Exception {
method = Dummy.class.getMethod("voidMethod");
}
@Mock
EntityMetadata<?> metadata;
@Test(expected = IllegalArgumentException.class)
@@ -113,20 +105,32 @@ public class JpaQueryExecutionUnitTests {
Query param = any();
when(binder.bind(param)).thenReturn(query);
when(query.executeUpdate()).thenReturn(0);
mock(metadata, void.class);
ModifyingExecution execution = new ModifyingExecution(method, em);
ModifyingExecution execution = new ModifyingExecution(metadata, em);
execution.execute(jpaQuery, binder);
verify(em, times(1)).clear();
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private void mock(EntityMetadata<?> method, Class<?> type,
Class<?>... others) {
OngoingStubbing stubbing = when(method.getJavaType());
stubbing.thenReturn(type);
}
@Test
public void allowsMethodReturnTypesForModifyingQuery() throws Exception {
new ModifyingExecution(Dummy.class.getMethod("voidMethod"), em);
new ModifyingExecution(Dummy.class.getMethod("intMethod"), em);
new ModifyingExecution(Dummy.class.getMethod("integerMethod"), em);
mock(metadata, void.class, int.class, Integer.class);
new ModifyingExecution(metadata, em);
new ModifyingExecution(metadata, em);
new ModifyingExecution(metadata, em);
}
@@ -134,7 +138,8 @@ public class JpaQueryExecutionUnitTests {
public void modifyingExecutionRejectsNonIntegerOrVoidReturnType()
throws Exception {
new ModifyingExecution(Dummy.class.getMethod("longMethod"), em);
mock(metadata, Long.class);
new ModifyingExecution(metadata, em);
}
static class StubQueryExecution extends JpaQueryExecution {
@@ -153,18 +158,4 @@ public class JpaQueryExecutionUnitTests {
return null;
}
}
static interface Dummy {
void voidMethod();
int intMethod();
Integer integerMethod();
Long longMethod();
}
}

View File

@@ -22,7 +22,6 @@ import static org.mockito.Mockito.*;
import java.lang.reflect.Method;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.QueryHint;
import org.junit.Before;
@@ -35,9 +34,9 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.sample.User;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.query.JpaQueryExecution.CollectionExecution;
import org.springframework.data.jpa.repository.sample.UserRepository;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.repository.query.QueryMethod.Type;
/**
@@ -53,8 +52,6 @@ public class JpaQueryMethodUnitTests {
@Mock
QueryExtractor extractor;
@Mock
EntityManager em;
Method repositoryMethod, invalidReturnType, pageableAndSort, pageableTwice,
sortableTwice, modifyingMethod;
@@ -91,40 +88,31 @@ public class JpaQueryMethodUnitTests {
@Test
public void testname() {
JpaQueryMethod method =
new JpaQueryMethod(repositoryMethod, extractor, em);
JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, extractor);
assertEquals("User.findByLastname", method.getNamedQueryName());
assertThat(method.getExecution(), is(CollectionExecution.class));
assertThat(method.getType(), is(Type.COLLECTION));
}
@Test(expected = IllegalArgumentException.class)
public void preventsNullRepositoryMethod() {
new JpaQueryMethod(null, extractor, em);
}
@Test(expected = IllegalArgumentException.class)
public void preventsNullEntityManager() {
new JpaQueryMethod(repositoryMethod, extractor, null);
new JpaQueryMethod(null, extractor);
}
@Test(expected = IllegalArgumentException.class)
public void preventsNullQueryExtractor() {
new JpaQueryMethod(repositoryMethod, null, em);
new JpaQueryMethod(repositoryMethod, null);
}
@Test
public void returnsCorrectName() {
JpaQueryMethod method =
new JpaQueryMethod(repositoryMethod, extractor, em);
JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, extractor);
assertEquals(repositoryMethod.getName(), method.getName());
}
@@ -132,8 +120,7 @@ public class JpaQueryMethodUnitTests {
@Test
public void returnsQueryIfAvailable() throws Exception {
JpaQueryMethod method =
new JpaQueryMethod(repositoryMethod, extractor, em);
JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, extractor);
assertNull(method.getAnnotatedQuery());
@@ -141,55 +128,36 @@ public class JpaQueryMethodUnitTests {
UserRepository.class.getMethod("findByAnnotatedQuery",
String.class);
assertNotNull(new JpaQueryMethod(repositoryMethod, extractor, em)
assertNotNull(new JpaQueryMethod(repositoryMethod, extractor)
.getAnnotatedQuery());
}
@Test
public void returnsCorrectDomainClassName() {
JpaQueryMethod method =
new JpaQueryMethod(repositoryMethod, extractor, em);
assertEquals(DOMAIN_CLASS, method.getDomainClass());
}
@Test
public void returnsCorrectNumberOfParameters() {
JpaQueryMethod method =
new JpaQueryMethod(repositoryMethod, extractor, em);
assertTrue(method.isCorrectNumberOfParameters(repositoryMethod
.getParameterTypes().length));
}
@Test(expected = IllegalStateException.class)
public void rejectsInvalidReturntypeOnPagebleFinder() {
new JpaQueryMethod(invalidReturnType, extractor, em);
new JpaQueryMethod(invalidReturnType, extractor);
}
@Test(expected = IllegalStateException.class)
public void rejectsPageableAndSortInFinderMethod() {
new JpaQueryMethod(pageableAndSort, extractor, em);
new JpaQueryMethod(pageableAndSort, extractor);
}
@Test(expected = IllegalStateException.class)
public void rejectsTwoPageableParameters() {
new JpaQueryMethod(pageableTwice, extractor, em);
new JpaQueryMethod(pageableTwice, extractor);
}
@Test(expected = IllegalStateException.class)
public void rejectsTwoSortableParameters() {
new JpaQueryMethod(sortableTwice, extractor, em);
new JpaQueryMethod(sortableTwice, extractor);
}
@@ -203,15 +171,14 @@ public class JpaQueryMethodUnitTests {
when(extractor.canExtractQuery()).thenReturn(false);
new JpaQueryMethod(method, extractor, em);
new JpaQueryMethod(method, extractor);
}
@Test
public void recognizesModifyingMethod() {
JpaQueryMethod method =
new JpaQueryMethod(modifyingMethod, extractor, em);
JpaQueryMethod method = new JpaQueryMethod(modifyingMethod, extractor);
assertTrue(method.isModifyingQuery());
}
@@ -223,7 +190,7 @@ public class JpaQueryMethodUnitTests {
InvalidRepository.class.getMethod("updateMethod", String.class,
Pageable.class);
new JpaQueryMethod(method, extractor, em);
new JpaQueryMethod(method, extractor);
}
@@ -234,15 +201,14 @@ public class JpaQueryMethodUnitTests {
InvalidRepository.class.getMethod("updateMethod", String.class,
Sort.class);
new JpaQueryMethod(method, extractor, em);
new JpaQueryMethod(method, extractor);
}
@Test
public void discoversHintsCorrectly() {
JpaQueryMethod method =
new JpaQueryMethod(repositoryMethod, extractor, em);
JpaQueryMethod method = new JpaQueryMethod(repositoryMethod, extractor);
List<QueryHint> hints = method.getHints();
assertNotNull(hints);

View File

@@ -43,14 +43,14 @@ import org.springframework.data.jpa.repository.sample.UserRepository;
@RunWith(MockitoJUnitRunner.class)
public class SimpleJpaQueryUnitTests {
private JpaQueryMethod method;
JpaQueryMethod method;
@Mock
private EntityManager em;
EntityManager em;
@Mock
private QueryExtractor extractor;
QueryExtractor extractor;
@Mock
private Query query;
Query query;
@Before
@@ -61,7 +61,7 @@ public class SimpleJpaQueryUnitTests {
Method setUp =
UserRepository.class.getMethod("findByLastname", String.class);
method = new JpaQueryMethod(setUp, extractor, em);
method = new JpaQueryMethod(setUp, extractor);
}

View File

@@ -34,6 +34,8 @@ import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.domain.Persistable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.support.RepositoryFactorySupport;
/**
@@ -47,18 +49,22 @@ import org.springframework.data.jpa.repository.JpaRepository;
@RunWith(MockitoJUnitRunner.class)
public class JpaRepositoryFactoryBeanUnitTests {
JpaRepositoryFactoryBean<SimpleSampleRepository> factory;
JpaRepositoryFactoryBean<SimpleSampleRepository> factoryBean;
@Mock
EntityManager entityManager;
@Mock
RepositoryFactorySupport factory;
@Mock
ListableBeanFactory beanFactory;
@Mock
PersistenceExceptionTranslator translator;
@Mock
Repository<?, ?> repository;
@Before
@SuppressWarnings("unchecked")
public void setUp() {
Map<String, PersistenceExceptionTranslator> beans =
@@ -68,12 +74,14 @@ public class JpaRepositoryFactoryBeanUnitTests {
beanFactory.getBeansOfType(
eq(PersistenceExceptionTranslator.class), anyBoolean(),
anyBoolean())).thenReturn(beans);
when(factory.getRepository(any(Class.class), any(Object.class)))
.thenReturn(repository);
// Setup standard factory configuration
factory =
JpaRepositoryFactoryBean.create(SimpleSampleRepository.class,
entityManager);
factory.setEntityManager(entityManager);
factoryBean =
new DummyJpaRepositoryFactoryBean<SimpleSampleRepository>();
factoryBean.setRepositoryInterface(SimpleSampleRepository.class);
factoryBean.setEntityManager(entityManager);
}
@@ -86,17 +94,17 @@ public class JpaRepositoryFactoryBeanUnitTests {
@Test
public void setsUpBasicInstanceCorrectly() throws Exception {
factory.setBeanFactory(beanFactory);
factory.afterPropertiesSet();
factoryBean.setBeanFactory(beanFactory);
factoryBean.afterPropertiesSet();
assertNotNull(factory.getObject());
assertNotNull(factoryBean.getObject());
}
@Test(expected = IllegalArgumentException.class)
public void requiresListableBeanFactory() throws Exception {
factory.setBeanFactory(mock(BeanFactory.class));
factoryBean.setBeanFactory(mock(BeanFactory.class));
}
@@ -109,7 +117,7 @@ public class JpaRepositoryFactoryBeanUnitTests {
@Test(expected = IllegalArgumentException.class)
public void preventsNullRepositoryInterface() {
factory.setRepositoryInterface(null);
factoryBean.setRepositoryInterface(null);
}
@@ -120,8 +128,25 @@ public class JpaRepositoryFactoryBeanUnitTests {
@Test(expected = IllegalArgumentException.class)
public void preventsUnsetRepositoryInterface() throws Exception {
factory = new JpaRepositoryFactoryBean<SimpleSampleRepository>();
factory.afterPropertiesSet();
factoryBean = new JpaRepositoryFactoryBean<SimpleSampleRepository>();
factoryBean.afterPropertiesSet();
}
private class DummyJpaRepositoryFactoryBean<T extends JpaRepository<?, ?>>
extends JpaRepositoryFactoryBean<T> {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean
* #createRepositoryFactory()
*/
@Override
protected RepositoryFactorySupport doCreateRepositoryFactory() {
return factory;
}
}
private interface SimpleSampleRepository extends

View File

@@ -30,7 +30,6 @@ import org.springframework.data.domain.Persistable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.custom.CustomGenericJpaRepositoryFactory;
import org.springframework.data.jpa.repository.custom.UserCustomExtendedRepository;
import org.springframework.transaction.annotation.Transactional;
/**
@@ -45,13 +44,23 @@ public class JpaRepositoryFactoryUnitTests {
@Mock
EntityManager entityManager;
@Mock
JpaEntityInformation<?> metadata;
@Before
public void setUp() {
// Setup standard factory configuration
factory = new JpaRepositoryFactory(entityManager);
factory = new JpaRepositoryFactory(entityManager) {
@Override
protected JpaEntityInformation<?> getEntityMetadata(
java.lang.Class<?> domainClass) {
return metadata;
}
};
}
@@ -136,8 +145,6 @@ public class JpaRepositoryFactoryUnitTests {
private interface SimpleSampleRepository extends
JpaRepository<User, Integer> {
@Transactional
User readByPrimaryKey(Integer primaryKey);
}
/**