Skip to content

Commit

Permalink
Issue #142 - Project fields in queries
Browse files Browse the repository at this point in the history
  • Loading branch information
derjust committed Mar 19, 2018
1 parent 937ace8 commit f5aa240
Show file tree
Hide file tree
Showing 24 changed files with 241 additions and 110 deletions.
3 changes: 3 additions & 0 deletions src/changes/changes.xml
Expand Up @@ -27,6 +27,9 @@
<action dev="derjust" type="fix" date="2018-03-05">
Fix Javadoc and cast warnings
</action>
<action dev="derjust" issue="142" type="add" date="">
Added support for @Query-based projections
</action>
</release>
<release version="5.0.2" date="2018-03-05" description="Maintenance release">
<action dev="vitolimandibhrata" issue="40" type="add" date="2017-01-07">
Expand Down
Expand Up @@ -27,6 +27,9 @@
import java.util.List;
import java.util.Map;

/**
* Interface to DynmaoDB - as seen from the Spring-Data world
*/
public interface DynamoDBOperations {

<T> int count(Class<T> domainClass, DynamoDBQueryExpression<T> queryExpression);
Expand Down
Expand Up @@ -25,15 +25,17 @@
*/
public abstract class AbstractQuery<T> implements Query<T> {

protected DynamoDBOperations dynamoDBOperations;
protected Class<T> clazz;
protected final DynamoDBOperations dynamoDBOperations;
protected final Class<T> clazz;
protected boolean scanEnabled = false;
protected boolean scanCountEnabled = false;



public boolean isScanCountEnabled() {
return scanCountEnabled;
return this.scanCountEnabled;
}

public boolean isScanEnabled() {
return this.scanEnabled;
}

@Override
Expand All @@ -46,10 +48,6 @@ public void setScanEnabled(boolean scanEnabled) {
this.scanEnabled = scanEnabled;
}

public boolean isScanEnabled() {
return scanEnabled;
}

public AbstractQuery(DynamoDBOperations dynamoDBOperations, Class<T> clazz) {
this.dynamoDBOperations = dynamoDBOperations;
this.clazz = clazz;
Expand Down
Expand Up @@ -34,7 +34,7 @@ public MultipleEntityQueryRequestQuery(DynamoDBOperations dynamoDBOperations,Cla
@Override
public List<T> getResultList() {

return dynamoDBOperations.query(clazz, queryRequest);
return dynamoDBOperations.query(clazz, queryRequest);
}

}
Expand Up @@ -18,7 +18,6 @@
import java.util.List;



public interface Query<T> {

/**
Expand Down
@@ -0,0 +1,36 @@
/**
* Copyright © 2018 spring-data-dynamodb (https://github.com/derjust/spring-data-dynamodb)
*
* 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.socialsignin.spring.data.dynamodb.repository;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Query {

/**
* A string that identifies the attributes you want. To retrieve a single attribute, specify its name.
* For multiple attributes, the names must be comma-separated.
*
* @see <a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ProjectionExpressions.html">Projection Expressions</a>
*/
String fields() default "";
}
Expand Up @@ -33,6 +33,7 @@

import java.util.Arrays;
import java.util.Iterator;
import java.util.Optional;

/**
* @author Michael Lavelle
Expand All @@ -41,21 +42,23 @@
public abstract class AbstractDynamoDBQueryCreator<T, ID, R> extends
AbstractQueryCreator<Query<R>, DynamoDBQueryCriteria<T, ID>> {

private DynamoDBEntityInformation<T, ID> entityMetadata;
protected DynamoDBOperations dynamoDBOperations;
protected final DynamoDBEntityInformation<T, ID> entityMetadata;
protected final DynamoDBOperations dynamoDBOperations;
protected final Optional<String> projection;

public AbstractDynamoDBQueryCreator(PartTree tree, DynamoDBEntityInformation<T, ID> entityMetadata, DynamoDBOperations dynamoDBOperations) {
public AbstractDynamoDBQueryCreator(PartTree tree, DynamoDBEntityInformation<T, ID> entityMetadata, Optional<String> projection, DynamoDBOperations dynamoDBOperations) {
super(tree);
this.entityMetadata = entityMetadata;
this.projection = projection;
this.dynamoDBOperations = dynamoDBOperations;
}

public AbstractDynamoDBQueryCreator(PartTree tree, ParameterAccessor parameterAccessor,
DynamoDBEntityInformation<T, ID> entityMetadata, DynamoDBOperations dynamoDBOperations) {
DynamoDBEntityInformation<T, ID> entityMetadata, Optional<String> projection, DynamoDBOperations dynamoDBOperations) {
super(tree, parameterAccessor);
this.entityMetadata = entityMetadata;
this.projection = projection;
this.dynamoDBOperations = dynamoDBOperations;

}

@Override
Expand Down
Expand Up @@ -48,6 +48,7 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;

/**
* @author Michael Lavelle
Expand All @@ -68,6 +69,7 @@ public abstract class AbstractDynamoDBQueryCriteria<T, ID> implements DynamoDBQu
protected Object hashKeyPropertyValue;
protected String globalSecondaryIndexName;
protected Sort sort = Sort.unsorted();
protected Optional<String> projection = Optional.empty();

public abstract boolean isApplicableForLoad();

Expand Down Expand Up @@ -120,7 +122,14 @@ protected QueryRequest buildQueryRequest(String tableName, String theIndexName,
}

queryRequest.setKeyConditions(keyConditions);
queryRequest.setSelect(Select.ALL_PROJECTED_ATTRIBUTES);
// Might be overwritten in the actual Query classes
if (projection.isPresent()) {
queryRequest.setSelect(Select.SPECIFIC_ATTRIBUTES);
queryRequest.setProjectionExpression(projection.get());
} else {
queryRequest.setSelect(Select.ALL_PROJECTED_ATTRIBUTES);
}

applySortIfSpecified(queryRequest, new ArrayList<>(new HashSet<>(allowedSortProperties)));
}
return queryRequest;
Expand Down Expand Up @@ -323,7 +332,6 @@ protected String getHashKeyAttributeName() {
return getAttributeName(getHashKeyPropertyName());
}


protected boolean hasIndexHashKeyEqualCondition()
{
boolean hasIndexHashKeyEqualCondition = false;
Expand Down Expand Up @@ -677,4 +685,9 @@ public DynamoDBQueryCriteria<T, ID> withSort(Sort sort) {
return this;
}

@Override
public DynamoDBQueryCriteria<T, ID> withProjection(Optional<String> projection) {
this.projection = projection;
return this;
}
}
Expand Up @@ -22,22 +22,24 @@
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.parser.PartTree;

import java.util.Optional;

public class DynamoDBCountQueryCreator<T ,ID> extends AbstractDynamoDBQueryCreator<T, ID, Long> {

private boolean pageQuery;

public DynamoDBCountQueryCreator(PartTree tree,
DynamoDBEntityInformation<T, ID> entityMetadata,
DynamoDBOperations dynamoDBOperations,boolean pageQuery) {
super(tree, entityMetadata, dynamoDBOperations);
super(tree, entityMetadata, Optional.empty(), dynamoDBOperations);
this.pageQuery = pageQuery;
}

public DynamoDBCountQueryCreator(PartTree tree,
ParameterAccessor parameterAccessor,
DynamoDBEntityInformation<T, ID> entityMetadata,
DynamoDBOperations dynamoDBOperations,boolean pageQuery) {
super(tree, parameterAccessor, entityMetadata, dynamoDBOperations);
super(tree, parameterAccessor, entityMetadata, Optional.empty(), dynamoDBOperations);
this.pageQuery = pageQuery;

}
Expand Down
Expand Up @@ -21,6 +21,7 @@
import com.amazonaws.services.dynamodbv2.model.ComparisonOperator;
import com.amazonaws.services.dynamodbv2.model.Condition;
import com.amazonaws.services.dynamodbv2.model.QueryRequest;
import com.amazonaws.services.dynamodbv2.model.Select;
import org.socialsignin.spring.data.dynamodb.core.DynamoDBOperations;
import org.socialsignin.spring.data.dynamodb.query.CountByHashAndRangeKeyQuery;
import org.socialsignin.spring.data.dynamodb.query.MultipleEntityQueryExpressionQuery;
Expand Down Expand Up @@ -77,7 +78,6 @@ public DynamoDBEntityWithHashAndRangeKeyCriteria(
indexRangeKeyPropertyNames = new HashSet<>();
}
this.entityInformation = entityInformation;

}

public Set<String> getIndexRangeKeyAttributeNames() {
Expand Down Expand Up @@ -184,6 +184,11 @@ public DynamoDBQueryExpression<T> buildQueryExpression() {
applySortIfSpecified(queryExpression, Arrays.asList(new String[] { getRangeKeyPropertyName() }));
}

if (projection.isPresent()) {
queryExpression.setSelect(Select.SPECIFIC_ATTRIBUTES);
queryExpression.setProjectionExpression(projection.get());
}

return queryExpression;
}

Expand All @@ -206,13 +211,13 @@ protected Query<T> buildFinderQuery(DynamoDBOperations dynamoDBOperations) {
QueryRequest queryRequest = buildQueryRequest(tableName, getGlobalSecondaryIndexName(),
getHashKeyAttributeName(), getRangeKeyAttributeName(), this.getRangeKeyPropertyName(),
getHashKeyConditions(), getRangeKeyConditions());
return new MultipleEntityQueryRequestQuery<T>(dynamoDBOperations,entityInformation.getJavaType(), queryRequest);
return new MultipleEntityQueryRequestQuery<>(dynamoDBOperations,entityInformation.getJavaType(), queryRequest);
} else {
DynamoDBQueryExpression<T> queryExpression = buildQueryExpression();
return new MultipleEntityQueryExpressionQuery<T>(dynamoDBOperations, entityInformation.getJavaType(), queryExpression);
return new MultipleEntityQueryExpressionQuery<>(dynamoDBOperations, entityInformation.getJavaType(), queryExpression);
}
} else {
return new MultipleEntityScanExpressionQuery<T>(dynamoDBOperations, clazz, buildScanExpression());
return new MultipleEntityScanExpressionQuery<>(dynamoDBOperations, clazz, buildScanExpression());
}
}

Expand All @@ -228,7 +233,7 @@ protected Query<Long> buildFinderCountQuery(DynamoDBOperations dynamoDBOperation

} else {
DynamoDBQueryExpression<T> queryExpression = buildQueryExpression();
return new QueryExpressionCountQuery<T>(dynamoDBOperations, entityInformation.getJavaType(), queryExpression);
return new QueryExpressionCountQuery<>(dynamoDBOperations, entityInformation.getJavaType(), queryExpression);

}
} else {
Expand Down
Expand Up @@ -20,6 +20,7 @@
import com.amazonaws.services.dynamodbv2.model.ComparisonOperator;
import com.amazonaws.services.dynamodbv2.model.Condition;
import com.amazonaws.services.dynamodbv2.model.QueryRequest;
import com.amazonaws.services.dynamodbv2.model.Select;
import org.socialsignin.spring.data.dynamodb.core.DynamoDBOperations;
import org.socialsignin.spring.data.dynamodb.query.CountByHashKeyQuery;
import org.socialsignin.spring.data.dynamodb.query.MultipleEntityQueryRequestQuery;
Expand Down Expand Up @@ -47,11 +48,11 @@ public DynamoDBEntityWithHashKeyOnlyCriteria(DynamoDBEntityInformation<T, ID> en
}

protected Query<T> buildSingleEntityLoadQuery(DynamoDBOperations dynamoDBOperations) {
return new SingleEntityLoadByHashKeyQuery<T>(dynamoDBOperations, clazz, getHashKeyPropertyValue());
return new SingleEntityLoadByHashKeyQuery<>(dynamoDBOperations, clazz, getHashKeyPropertyValue());
}

protected Query<Long> buildSingleEntityCountQuery(DynamoDBOperations dynamoDBOperations) {
return new CountByHashKeyQuery<T>(dynamoDBOperations, clazz, getHashKeyPropertyValue());
return new CountByHashKeyQuery<>(dynamoDBOperations, clazz, getHashKeyPropertyValue());
}

protected Query<T> buildFinderQuery(DynamoDBOperations dynamoDBOperations) {
Expand All @@ -72,6 +73,7 @@ protected Query<Long> buildFinderCountQuery(DynamoDBOperations dynamoDBOperation
List<Condition> hashKeyConditions = getHashKeyConditions();
QueryRequest queryRequest = buildQueryRequest(dynamoDBOperations.getOverriddenTableName(clazz, entityInformation.getDynamoDBTableName()),
getGlobalSecondaryIndexName(), getHashKeyAttributeName(), null, null, hashKeyConditions, null);
queryRequest.setSelect(Select.COUNT);
return new QueryRequestCountQuery(dynamoDBOperations, queryRequest);

} else {
Expand Down Expand Up @@ -106,6 +108,11 @@ public DynamoDBScanExpression buildScanExpression() {
scanExpression.addFilterCondition(conditionEntry.getKey(), condition);
}
}

if (projection.isPresent()) {
scanExpression.setSelect(Select.SPECIFIC_ATTRIBUTES);
scanExpression.setProjectionExpression(projection.get());
}
return scanExpression;
}

Expand Down
Expand Up @@ -22,29 +22,24 @@
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.parser.PartTree;

import java.util.Optional;

public class DynamoDBQueryCreator<T,ID> extends AbstractDynamoDBQueryCreator<T, ID,T> {
/*
public DynamoDBQueryCreator(PartTree tree,
DynamoDBEntityInformation<T, ID> entityMetadata,
DynamoDBOperations dynamoDBOperations) {
super(tree, entityMetadata, dynamoDBOperations);
}
*/

public DynamoDBQueryCreator(PartTree tree,
ParameterAccessor parameterAccessor,
DynamoDBEntityInformation<T, ID> entityMetadata,
Optional<String> projection,
DynamoDBOperations dynamoDBOperations) {
super(tree, parameterAccessor, entityMetadata, dynamoDBOperations);
super(tree, parameterAccessor, entityMetadata, projection, dynamoDBOperations);
}

@Override
protected Query<T> complete(DynamoDBQueryCriteria<T, ID> criteria, Sort sort) {
if (sort != null) {
criteria.withSort(sort);
}
criteria.withSort(sort);
criteria.withProjection(projection);

return criteria.buildQuery(dynamoDBOperations);

}

}
Expand Up @@ -20,6 +20,8 @@
import org.socialsignin.spring.data.dynamodb.query.Query;
import org.springframework.data.domain.Sort;

import java.util.Optional;

/**
* @author Michael Lavelle
* @author Sebastian Just
Expand All @@ -39,6 +41,8 @@ DynamoDBQueryCriteria<T, ID> withSingleValueCriteria(String propertyName, Compar

DynamoDBQueryCriteria<T, ID> withSort(Sort sort);

DynamoDBQueryCriteria<T, ID> withProjection(Optional<String> projection);

Query<T> buildQuery(DynamoDBOperations dynamoDBOperations);

Query<Long> buildCountQuery(DynamoDBOperations dynamoDBOperations, boolean pageQuery);
Expand Down

0 comments on commit f5aa240

Please sign in to comment.