Skip to content

Commit 754379a

Browse files
committed
#80 allow collections from queries
1 parent 1a9fd3f commit 754379a

File tree

6 files changed

+88
-37
lines changed

6 files changed

+88
-37
lines changed

src/main/java/com/arangodb/springframework/repository/ArangoRepositoryFactory.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.lang.reflect.Method;
2424
import java.util.Optional;
2525

26+
import com.arangodb.springframework.repository.query.QueryTransactionBridge;
2627
import org.springframework.context.ApplicationContext;
2728
import org.springframework.data.mapping.context.MappingContext;
2829
import org.springframework.data.projection.ProjectionFactory;
@@ -58,11 +59,13 @@
5859
public class ArangoRepositoryFactory extends RepositoryFactorySupport {
5960

6061
private final ArangoOperations arangoOperations;
62+
private final QueryTransactionBridge transactionBridge;
6163
private final ApplicationContext applicationContext;
6264
private final MappingContext<? extends ArangoPersistentEntity<?>, ArangoPersistentProperty> context;
6365

64-
public ArangoRepositoryFactory(final ArangoOperations arangoOperations, final ApplicationContext applicationContext) {
66+
public ArangoRepositoryFactory(final ArangoOperations arangoOperations, final QueryTransactionBridge transactionBridge, final ApplicationContext applicationContext) {
6567
this.arangoOperations = arangoOperations;
68+
this.transactionBridge = transactionBridge;
6669
this.applicationContext = applicationContext;
6770
this.context = arangoOperations.getConverter().getMappingContext();
6871
}
@@ -101,7 +104,7 @@ protected Optional<QueryLookupStrategy> getQueryLookupStrategy(
101104
QueryLookupStrategy strategy = null;
102105
switch (key) {
103106
case CREATE_IF_NOT_FOUND:
104-
strategy = new DefaultArangoQueryLookupStrategy(arangoOperations, applicationContext);
107+
strategy = new DefaultArangoQueryLookupStrategy(arangoOperations, transactionBridge, applicationContext);
105108
break;
106109
case CREATE:
107110
break;
@@ -115,11 +118,13 @@ static class DefaultArangoQueryLookupStrategy implements QueryLookupStrategy {
115118

116119
private final ArangoOperations operations;
117120
private final ApplicationContext applicationContext;
121+
private final QueryTransactionBridge transactionBridge;
118122

119123
public DefaultArangoQueryLookupStrategy(final ArangoOperations operations,
120-
final ApplicationContext applicationContext) {
124+
final QueryTransactionBridge transactionBridge, final ApplicationContext applicationContext) {
121125
this.operations = operations;
122126
this.applicationContext = applicationContext;
127+
this.transactionBridge = transactionBridge;
123128
}
124129

125130
@Override
@@ -134,11 +139,11 @@ public RepositoryQuery resolveQuery(
134139

135140
if (namedQueries.hasQuery(namedQueryName)) {
136141
final String namedQuery = namedQueries.getQuery(namedQueryName);
137-
return new StringBasedArangoQuery(namedQuery, queryMethod, operations, applicationContext);
142+
return new StringBasedArangoQuery(namedQuery, queryMethod, operations, transactionBridge, applicationContext);
138143
} else if (queryMethod.hasAnnotatedQuery()) {
139-
return new StringBasedArangoQuery(queryMethod, operations, applicationContext);
144+
return new StringBasedArangoQuery(queryMethod, operations, transactionBridge, applicationContext);
140145
} else {
141-
return new DerivedArangoQuery(queryMethod, operations);
146+
return new DerivedArangoQuery(queryMethod, operations, transactionBridge);
142147
}
143148
}
144149

src/main/java/com/arangodb/springframework/repository/ArangoRepositoryFactoryBean.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
package com.arangodb.springframework.repository;
2222

23+
import com.arangodb.springframework.repository.query.QueryTransactionBridge;
2324
import org.springframework.beans.BeansException;
2425
import org.springframework.beans.factory.annotation.Autowired;
2526
import org.springframework.context.ApplicationContext;
@@ -38,6 +39,7 @@ public class ArangoRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
3839
extends RepositoryFactoryBeanSupport<T, S, ID> implements ApplicationContextAware {
3940

4041
private ArangoOperations arangoOperations;
42+
private QueryTransactionBridge transactionBridge;
4143
private ApplicationContext applicationContext;
4244

4345
@Autowired
@@ -50,10 +52,15 @@ public void setArangoOperations(final ArangoOperations arangoOperations) {
5052
this.arangoOperations = arangoOperations;
5153
}
5254

55+
@Autowired
56+
public void setArangoOperations(final QueryTransactionBridge transactionBridge) {
57+
this.transactionBridge = transactionBridge;
58+
}
59+
5360
@Override
5461
protected RepositoryFactorySupport createRepositoryFactory() {
5562
Assert.notNull(arangoOperations, "arangoOperations not configured");
56-
return new ArangoRepositoryFactory(arangoOperations, applicationContext);
63+
return new ArangoRepositoryFactory(arangoOperations, transactionBridge, applicationContext);
5764
}
5865

5966
@Override

src/main/java/com/arangodb/springframework/repository/query/AbstractArangoQuery.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.slf4j.LoggerFactory;
3030
import org.springframework.data.repository.query.RepositoryQuery;
3131
import org.springframework.data.repository.query.ResultProcessor;
32+
import org.springframework.data.util.Pair;
3233
import org.springframework.util.Assert;
3334

3435
import com.arangodb.ArangoCursor;
@@ -51,14 +52,18 @@ public abstract class AbstractArangoQuery implements RepositoryQuery {
5152
protected final ArangoOperations operations;
5253
protected final ArangoMappingContext mappingContext;
5354
protected final Class<?> domainClass;
55+
private final QueryTransactionBridge transactionBridge;
5456

55-
public AbstractArangoQuery(final ArangoQueryMethod method, final ArangoOperations operations) {
57+
public AbstractArangoQuery(final ArangoQueryMethod method, final ArangoOperations operations,
58+
final QueryTransactionBridge transactionBridge) {
5659
Assert.notNull(method, "ArangoQueryMethod must not be null!");
5760
Assert.notNull(operations, "ArangoOperations must not be null!");
61+
Assert.notNull(transactionBridge, "QueryTransactionBridge must not be null!");
5862
this.method = method;
5963
this.operations = operations;
6064
mappingContext = (ArangoMappingContext) operations.getConverter().getMappingContext();
6165
this.domainClass = method.getEntityInformation().getJavaType();
66+
this.transactionBridge = transactionBridge;
6267
}
6368

6469
@Override
@@ -75,12 +80,16 @@ public Object execute(final Object[] parameters) {
7580
options.fullCount(true);
7681
}
7782

78-
final String query = createQuery(accessor, bindVars, options);
83+
final Pair<String, ? extends Collection<String>> queryAndCollection = createQuery(accessor, bindVars);
84+
if (options.getStreamTransactionId() == null) {
85+
options.streamTransactionId(transactionBridge.beginCurrentTransaction(queryAndCollection.getSecond()));
86+
}
87+
7988

8089
final ResultProcessor processor = method.getResultProcessor().withDynamicProjection(accessor);
8190
final Class<?> typeToRead = getTypeToRead(processor);
8291

83-
final ArangoCursor<?> result = operations.query(query, bindVars, options, typeToRead);
92+
final ArangoCursor<?> result = operations.query(queryAndCollection.getFirst(), bindVars, options, typeToRead);
8493
logWarningsIfNecessary(result);
8594
return processor.processResult(convertResult(result, accessor));
8695
}
@@ -105,14 +114,11 @@ public ArangoQueryMethod getQueryMethod() {
105114
* provides access to the actual arguments
106115
* @param bindVars
107116
* the binding parameter map
108-
* @param options
109-
* contains the merged {@link com.arangodb.model.AqlQueryOptions}
110-
* @return the created AQL query
117+
* @return a pair of the created AQL query and all collection names
111118
*/
112-
protected abstract String createQuery(
113-
ArangoParameterAccessor accessor,
114-
Map<String, Object> bindVars,
115-
AqlQueryOptions options);
119+
protected abstract Pair<String, ? extends Collection<String>> createQuery(
120+
ArangoParameterAccessor accessor,
121+
Map<String, Object> bindVars);
116122

117123
protected abstract boolean isCountQuery();
118124

@@ -164,6 +170,10 @@ protected AqlQueryOptions mergeQueryOptions(final AqlQueryOptions oldStatic, fin
164170
if (rules != null) {
165171
oldStatic.rules(rules);
166172
}
173+
final String streamTransactionId = newDynamic.getStreamTransactionId();
174+
if (streamTransactionId != null) {
175+
oldStatic.streamTransactionId(streamTransactionId);
176+
}
167177
return oldStatic;
168178
}
169179

src/main/java/com/arangodb/springframework/repository/query/DerivedArangoQuery.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@
2222

2323
import com.arangodb.entity.IndexEntity;
2424
import com.arangodb.entity.IndexType;
25-
import com.arangodb.model.AqlQueryOptions;
2625
import com.arangodb.springframework.core.ArangoOperations;
2726
import com.arangodb.springframework.repository.query.derived.BindParameterBinding;
2827
import com.arangodb.springframework.repository.query.derived.DerivedQueryCreator;
2928
import org.springframework.data.repository.query.parser.PartTree;
29+
import org.springframework.data.util.Pair;
3030

31+
import java.util.Collection;
3132
import java.util.LinkedList;
3233
import java.util.List;
3334
import java.util.Map;
@@ -44,17 +45,17 @@ public class DerivedArangoQuery extends AbstractArangoQuery {
4445
private final PartTree tree;
4546
private final List<String> geoFields;
4647

47-
public DerivedArangoQuery(final ArangoQueryMethod method, final ArangoOperations operations) {
48-
super(method, operations);
48+
public DerivedArangoQuery(final ArangoQueryMethod method, final ArangoOperations operations,
49+
final QueryTransactionBridge transactionBridge) {
50+
super(method, operations, transactionBridge);
4951
tree = new PartTree(method.getName(), domainClass);
5052
geoFields = getGeoFields();
5153
}
5254

5355
@Override
54-
protected String createQuery(
55-
final ArangoParameterAccessor accessor,
56-
final Map<String, Object> bindVars,
57-
final AqlQueryOptions options) {
56+
protected Pair<String, ? extends Collection<String>> createQuery(
57+
final ArangoParameterAccessor accessor,
58+
final Map<String, Object> bindVars) {
5859

5960
return new DerivedQueryCreator(mappingContext, domainClass, tree, accessor, new BindParameterBinding(bindVars),
6061
geoFields).createQuery();

src/main/java/com/arangodb/springframework/repository/query/StringBasedArangoQuery.java

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,16 @@
2020

2121
package com.arangodb.springframework.repository.query;
2222

23-
import com.arangodb.model.AqlQueryOptions;
23+
import com.arangodb.springframework.annotation.Document;
24+
import com.arangodb.springframework.annotation.Edge;
2425
import com.arangodb.springframework.core.ArangoOperations;
2526
import com.arangodb.springframework.core.util.AqlUtils;
2627
import com.arangodb.springframework.repository.query.ArangoParameters.ArangoParameter;
2728
import org.springframework.context.ApplicationContext;
2829
import org.springframework.context.expression.BeanFactoryAccessor;
2930
import org.springframework.context.expression.BeanFactoryResolver;
31+
import org.springframework.core.annotation.AnnotationUtils;
32+
import org.springframework.data.util.Pair;
3033
import org.springframework.expression.Expression;
3134
import org.springframework.expression.ParserContext;
3235
import org.springframework.expression.spel.standard.SpelExpressionParser;
@@ -69,13 +72,14 @@ public class StringBasedArangoQuery extends AbstractArangoQuery {
6972
private final ApplicationContext applicationContext;
7073

7174
public StringBasedArangoQuery(final ArangoQueryMethod method, final ArangoOperations operations,
72-
final ApplicationContext applicationContext) {
73-
this(method.getAnnotatedQuery(), method, operations, applicationContext);
75+
final QueryTransactionBridge transactionBridge, final ApplicationContext applicationContext) {
76+
this(method.getAnnotatedQuery(), method, operations, transactionBridge, applicationContext);
7477
}
7578

7679
public StringBasedArangoQuery(final String query, final ArangoQueryMethod method,
77-
final ArangoOperations operations, final ApplicationContext applicationContext) {
78-
super(method, operations);
80+
final ArangoOperations operations, final QueryTransactionBridge transactionBridge,
81+
final ApplicationContext applicationContext) {
82+
super(method, operations, transactionBridge);
7983
Assert.notNull(query, "Query must not be null!");
8084

8185
this.query = query;
@@ -90,14 +94,37 @@ public StringBasedArangoQuery(final String query, final ArangoQueryMethod method
9094
}
9195

9296
@Override
93-
protected String createQuery(
94-
final ArangoParameterAccessor accessor,
95-
final Map<String, Object> bindVars,
96-
final AqlQueryOptions options) {
97+
protected Pair<String, ? extends Collection<String>> createQuery(
98+
final ArangoParameterAccessor accessor,
99+
final Map<String, Object> bindVars) {
97100

98101
extractBindVars(accessor, bindVars);
99102

100-
return prepareQuery(accessor);
103+
return Pair.of(prepareQuery(accessor), allCollectionNames(collectionName, bindVars));
104+
}
105+
106+
private Collection<String> allCollectionNames(String collectionName, Map<String, Object> bindVars) {
107+
HashSet<String> allCollections = new HashSet<>();
108+
allCollections.add(collectionName);
109+
bindVars.entrySet().stream()
110+
.filter(entry -> entry.getKey().startsWith("@"))
111+
.map(Map.Entry::getValue)
112+
.map(value -> value instanceof Class ? getCollectionName((Class<?>) value): value.toString())
113+
.filter(Objects::nonNull)
114+
.forEach(allCollections::add);
115+
return allCollections;
116+
}
117+
118+
private String getCollectionName(Class<?> value) {
119+
Document document = AnnotationUtils.findAnnotation(value, Document.class);
120+
if (document != null) {
121+
return document.value();
122+
}
123+
Edge edge = AnnotationUtils.findAnnotation(value, Edge.class);
124+
if (edge != null) {
125+
return edge.value();
126+
}
127+
return null;
101128
}
102129

103130
@Override

src/main/java/com/arangodb/springframework/repository/query/derived/DerivedQueryCreator.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
4343
import org.springframework.data.repository.query.parser.Part;
4444
import org.springframework.data.repository.query.parser.PartTree;
45+
import org.springframework.data.util.Pair;
4546
import org.springframework.util.Assert;
4647

4748
import java.util.*;
@@ -50,7 +51,7 @@
5051
/**
5152
* Creates a full AQL query from a PartTree and ArangoParameterAccessor
5253
*/
53-
public class DerivedQueryCreator extends AbstractQueryCreator<String, Criteria> {
54+
public class DerivedQueryCreator extends AbstractQueryCreator<Pair<String, ? extends Collection<String>>, Criteria> {
5455

5556
private static final Logger LOGGER = LoggerFactory.getLogger(DerivedQueryCreator.class);
5657
private static final Set<Part.Type> UNSUPPORTED_IGNORE_CASE = new HashSet<>();
@@ -120,7 +121,7 @@ protected Criteria or(final Criteria base, final Criteria criteria) {
120121
* @return
121122
*/
122123
@Override
123-
protected String complete(final Criteria criteria, final Sort sort) {
124+
protected Pair<String, ? extends Collection<String>> complete(final Criteria criteria, final Sort sort) {
124125
if (tree.isDistinct() && !tree.isCountProjection()) {
125126
LOGGER.debug("Use of 'Distinct' is meaningful only in count queries");
126127
}
@@ -191,7 +192,7 @@ protected String complete(final Criteria criteria, final Sort sort) {
191192
}
192193
}
193194
}
194-
return query.toString();
195+
return Pair.of(query.toString(), withCollections);
195196
}
196197

197198
public double[] getUniquePoint() {

0 commit comments

Comments
 (0)