Merge branch 'master' of github.com:SpringSource/spring-data-commons
This commit is contained in:
@@ -115,6 +115,14 @@ public interface Page<T> extends Iterable<T> {
|
||||
* @return
|
||||
*/
|
||||
List<T> getContent();
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the {@link Page} has content at all.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean hasContent();
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,10 +49,7 @@ public class PageImpl<T> implements Page<T> {
|
||||
|
||||
this.content.addAll(content);
|
||||
this.total = total;
|
||||
|
||||
this.pageable =
|
||||
null == pageable ? new PageRequest(0, content.size())
|
||||
: pageable;
|
||||
this.pageable = pageable;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +72,7 @@ public class PageImpl<T> implements Page<T> {
|
||||
*/
|
||||
public int getNumber() {
|
||||
|
||||
return pageable.getPageNumber();
|
||||
return pageable == null ? 0 : pageable.getPageNumber();
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +83,7 @@ public class PageImpl<T> implements Page<T> {
|
||||
*/
|
||||
public int getSize() {
|
||||
|
||||
return pageable.getPageSize();
|
||||
return pageable == null ? 0 : pageable.getPageSize();
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +94,7 @@ public class PageImpl<T> implements Page<T> {
|
||||
*/
|
||||
public int getTotalPages() {
|
||||
|
||||
return (int) Math.ceil((double) total / (double) getSize());
|
||||
return getSize() == 0 ? 0 : (int) Math.ceil((double) total / (double) getSize());
|
||||
}
|
||||
|
||||
|
||||
@@ -187,6 +184,17 @@ public class PageImpl<T> implements Page<T> {
|
||||
|
||||
return Collections.unmodifiableList(content);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.data.domain.Page#hasContent()
|
||||
*/
|
||||
@Override
|
||||
public boolean hasContent() {
|
||||
|
||||
return !content.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -196,7 +204,7 @@ public class PageImpl<T> implements Page<T> {
|
||||
*/
|
||||
public Sort getSort() {
|
||||
|
||||
return pageable.getSort();
|
||||
return pageable == null ? null : pageable.getSort();
|
||||
}
|
||||
|
||||
|
||||
@@ -239,7 +247,7 @@ public class PageImpl<T> implements Page<T> {
|
||||
|
||||
boolean totalEqual = this.total == that.total;
|
||||
boolean contentEqual = this.content.equals(that.content);
|
||||
boolean pageableEqual = this.pageable.equals(that.pageable);
|
||||
boolean pageableEqual = this.pageable == null ? that.pageable == null : this.pageable.equals(that.pageable);
|
||||
|
||||
return totalEqual && contentEqual && pageableEqual;
|
||||
}
|
||||
@@ -256,7 +264,7 @@ public class PageImpl<T> implements Page<T> {
|
||||
int result = 17;
|
||||
|
||||
result = 31 * result + (int) (total ^ total >>> 32);
|
||||
result = 31 * result + pageable.hashCode();
|
||||
result = 31 * result + (pageable == null ? 0 : pageable.hashCode());
|
||||
result = 31 * result + content.hashCode();
|
||||
|
||||
return result;
|
||||
|
||||
@@ -295,7 +295,7 @@ public class BasicMappingContext implements MappingContext, InitializingBean, Ap
|
||||
// Find the right constructor
|
||||
PreferredConstructor<T> preferredConstructor = null;
|
||||
|
||||
for (Constructor<?> constructor : type.getConstructors()) {
|
||||
for (Constructor<?> constructor : type.getDeclaredConstructors()) {
|
||||
if (constructor.getParameterTypes().length != 0) {
|
||||
// Non-no-arg constructor
|
||||
if (null == preferredConstructor || constructor.isAnnotationPresent(PersistenceConstructor.class)) {
|
||||
|
||||
@@ -1,47 +1,49 @@
|
||||
package org.springframework.data.persistence;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by classes that can synchronize
|
||||
* between data stores and ChangeSets.
|
||||
* @author Rod Johnson
|
||||
*
|
||||
* @param <K> entity key
|
||||
*/
|
||||
public interface ChangeSetPersister<K> {
|
||||
|
||||
String ID_KEY = "_id";
|
||||
|
||||
String CLASS_KEY = "_class";
|
||||
|
||||
/**
|
||||
* TODO how to tell when not found? throw exception?
|
||||
*/
|
||||
void getPersistentState(Class<? extends ChangeSetBacked> entityClass, K key, ChangeSet changeSet) throws DataAccessException, NotFoundException;
|
||||
|
||||
/**
|
||||
* Return id
|
||||
* @param cs
|
||||
* @return
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
K getPersistentId(Class<? extends ChangeSetBacked> entityClass, ChangeSet cs) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return key
|
||||
* @param cs Key may be null if not persistent
|
||||
* @return
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
K persistState(Class<? extends ChangeSetBacked> entityClass, ChangeSet cs) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Exception thrown in alternate control flow if getPersistentState
|
||||
* finds no entity data.
|
||||
*/
|
||||
class NotFoundException extends Exception {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
package org.springframework.data.persistence;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by classes that can synchronize
|
||||
* between data stores and ChangeSets.
|
||||
* @author Rod Johnson
|
||||
*
|
||||
* @param <K> entity key
|
||||
*/
|
||||
public interface ChangeSetPersister<K> {
|
||||
|
||||
String ID_KEY = "_id";
|
||||
|
||||
String CLASS_KEY = "_class";
|
||||
|
||||
/**
|
||||
* TODO how to tell when not found? throw exception?
|
||||
*/
|
||||
void getPersistentState(Class<? extends ChangeSetBacked> entityClass, K key, ChangeSet changeSet) throws DataAccessException, NotFoundException;
|
||||
|
||||
/**
|
||||
* Return id
|
||||
* @param entity
|
||||
* @param cs
|
||||
* @return
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
K getPersistentId(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Return key
|
||||
* @param entity
|
||||
* @param cs Key may be null if not persistent
|
||||
* @return
|
||||
* @throws DataAccessException
|
||||
*/
|
||||
K persistState(ChangeSetBacked entity, ChangeSet cs) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Exception thrown in alternate control flow if getPersistentState
|
||||
* finds no entity data.
|
||||
*/
|
||||
class NotFoundException extends Exception {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -115,6 +115,18 @@ public class Property {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the property will return the plain resolved type for
|
||||
* simple properties, the component type for any {@link Iterable} or the
|
||||
* value type of a {@link java.util.Map} if the property is one.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Class<?> getType() {
|
||||
|
||||
return this.type.getType();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the next nested {@link Property}.
|
||||
@@ -285,7 +297,7 @@ public class Property {
|
||||
IllegalArgumentException exception = null;
|
||||
|
||||
try {
|
||||
return new Property(source, type);
|
||||
return new Property(source, type, addTail);
|
||||
} catch (IllegalArgumentException e) {
|
||||
exception = e;
|
||||
}
|
||||
@@ -299,7 +311,7 @@ public class Property {
|
||||
String head = source.substring(0, position);
|
||||
String tail = source.substring(position);
|
||||
|
||||
return new Property(head, type, tail + addTail);
|
||||
return create(head, type, tail + addTail);
|
||||
}
|
||||
|
||||
throw exception;
|
||||
|
||||
@@ -190,14 +190,15 @@ public abstract class RepositoryFactorySupport {
|
||||
protected abstract Class<?> getRepositoryBaseClass(
|
||||
Class<?> repositoryInterface);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the {@link QueryLookupStrategy} for the given {@link Key}.
|
||||
*
|
||||
* @param key can be {@literal null}
|
||||
* @return
|
||||
*/
|
||||
protected abstract QueryLookupStrategy getQueryLookupStrategy(Key key);
|
||||
/**
|
||||
* Returns the {@link QueryLookupStrategy} for the given {@link Key}.
|
||||
*
|
||||
* @param key can be {@literal null}
|
||||
* @return the {@link QueryLookupStrategy} to use or {@literal null} if no queries should be looked up.
|
||||
*/
|
||||
protected QueryLookupStrategy getQueryLookupStrategy(Key key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -254,6 +255,18 @@ public abstract class RepositoryFactorySupport {
|
||||
|
||||
QueryLookupStrategy lookupStrategy =
|
||||
getQueryLookupStrategy(queryLookupStrategyKey);
|
||||
|
||||
if (lookupStrategy == null) {
|
||||
|
||||
if (repositoryMetadata.hasCustomMethod()) {
|
||||
throw new IllegalStateException(
|
||||
"You have defined query method in the repository but " +
|
||||
"you don't have no query lookup strategy defined. The " +
|
||||
"infrastructure apparently does not support query methods!");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (Method method : metadata.getQueryMethods()) {
|
||||
RepositoryQuery query =
|
||||
|
||||
@@ -23,7 +23,7 @@ public class ChangeSetBackedTransactionSynchronization implements TransactionSyn
|
||||
|
||||
public void afterCommit() {
|
||||
log.debug("After Commit called for " + entity);
|
||||
changeSetPersister.persistState(entity.getClass(), entity.getChangeSet());
|
||||
changeSetPersister.persistState(entity, entity.getChangeSet());
|
||||
changeSetTxStatus = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,12 @@
|
||||
|
||||
package org.springframework.data.domain;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.domain.UnitTestUtils.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -78,4 +81,22 @@ public class PageImplUnitTests {
|
||||
|
||||
new PageImpl<Object>(null, null, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsPageForEmptyContentCorrectly() {
|
||||
List<String> list = Collections.emptyList();
|
||||
Page<String> page = new PageImpl<String>(list);
|
||||
assertThat(page.getContent(), is(list));
|
||||
assertThat(page.getNumber(), is(0));
|
||||
assertThat(page.getNumberOfElements(), is(0));
|
||||
assertThat(page.getSize(), is(0));
|
||||
assertThat(page.getSort(), is((Sort) null));
|
||||
assertThat(page.getTotalElements(), is(0L));
|
||||
assertThat(page.getTotalPages(), is(0));
|
||||
assertThat(page.hasNextPage(), is(false));
|
||||
assertThat(page.hasPreviousPage(), is(false));
|
||||
assertThat(page.isFirstPage(), is(true));
|
||||
assertThat(page.isLastPage(), is(true));
|
||||
assertThat(page.hasContent(), is(false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +123,12 @@ public class PropertyUnitTests {
|
||||
|
||||
Property.from("userMapMame", Bar.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsNested() {
|
||||
|
||||
Property from = Property.from("barUserName", Sample.class);
|
||||
}
|
||||
|
||||
private class Foo {
|
||||
|
||||
@@ -146,6 +152,7 @@ public class PropertyUnitTests {
|
||||
|
||||
private String userName;
|
||||
private FooBar user;
|
||||
private Bar bar;
|
||||
}
|
||||
|
||||
private class Sample2 {
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.repository.support;
|
||||
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
import org.springframework.data.repository.support.RepositoryFactorySupport.QueryExecuterMethodInterceptor;
|
||||
|
||||
/**
|
||||
* Unit test for {@link QueryExecuterMethodInterceptor}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class QueryExecuterMethodInterceptorUnitTests {
|
||||
|
||||
@Mock
|
||||
RepositoryFactorySupport factory;
|
||||
@Mock
|
||||
RepositoryMetadata metadata;
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void rejectsRepositoryInterfaceWithQueryMethodsIfNoQueryLookupStrategyIsDefined() {
|
||||
|
||||
when(metadata.hasCustomMethod()).thenReturn(true);
|
||||
when(factory.getQueryLookupStrategy(any(Key.class))).thenReturn(null);
|
||||
|
||||
factory.new QueryExecuterMethodInterceptor(metadata, null, new Object());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void skipsQueryLookupsIfQueryLookupStrategyIsNull() {
|
||||
|
||||
when(metadata.hasCustomMethod()).thenReturn(false);
|
||||
when(factory.getQueryLookupStrategy(any(Key.class))).thenReturn(null);
|
||||
|
||||
factory.new QueryExecuterMethodInterceptor(metadata, null, new Object());
|
||||
verify(metadata, times(0)).getQueryMethods();
|
||||
}
|
||||
}
|
||||
@@ -286,6 +286,14 @@
|
||||
<showDeprecation>false</showDeprecation>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.3.1</version>
|
||||
<configuration>
|
||||
<useDefaultManifestFile>true</useDefaultManifestFile>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
|
||||
Reference in New Issue
Block a user