Add n1ql.scope and n1ql.collection spel expressions for @Query.
This adds n1ql.scope and n1ql.collection spel expressions for @Query so that n1ql.bucket doesn't need to be overloaded with the collection name. This will make the bucket name available in n1q.bucket. This is a breaking change as queries that used n1ql.bucket to get the collection name (especially in the case of pre-scope- and-collection @Queries that (a) referenced n1ql.bucket instead of referencing other spel expressions that include the bucket/collection name; and (b) still worked after the repository was moved from a bucket onto a collection by virtue of n1ql.bucket having the value of the collection in such instances. Closes #1445.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors
|
||||
* Copyright 2012-2022 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.
|
||||
@@ -20,9 +20,11 @@ import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.data.couchbase.repository.Collection;
|
||||
import org.springframework.data.couchbase.repository.CouchbaseRepository;
|
||||
import org.springframework.data.couchbase.repository.Query;
|
||||
import org.springframework.data.couchbase.repository.ScanConsistency;
|
||||
import org.springframework.data.couchbase.repository.Scope;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@@ -59,6 +61,11 @@ public interface UserRepository extends CouchbaseRepository<User, String> {
|
||||
|
||||
List<User> findByVersionEqualsAndFirstnameEquals(Long version, String firstname);
|
||||
|
||||
@Query("#{#n1ql.selectEntity}|#{#n1ql.filter}|#{#n1ql.bucket}|#{#n1ql.scope}|#{#n1ql.collection}")
|
||||
@Scope("thisScope")
|
||||
@Collection("thisCollection")
|
||||
List<User> spelTests();
|
||||
|
||||
// simulate a slow operation
|
||||
@Cacheable("mySpringCache")
|
||||
default List<User> getByFirstname(String firstname) {
|
||||
|
||||
@@ -66,9 +66,9 @@ import com.couchbase.client.java.query.QueryScanConsistency;
|
||||
* @author Michael Nitschinger
|
||||
* @author Michael Reiche
|
||||
*/
|
||||
@SpringJUnitConfig(StringN1qlQueryCreatorTests.Config.class)
|
||||
@SpringJUnitConfig(StringN1qlQueryCreatorIntegrationTests.Config.class)
|
||||
@IgnoreWhen(clusterTypes = ClusterType.MOCKED)
|
||||
class StringN1qlQueryCreatorTests extends ClusterAwareIntegrationTests {
|
||||
class StringN1qlQueryCreatorIntegrationTests extends ClusterAwareIntegrationTests {
|
||||
|
||||
MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> context;
|
||||
CouchbaseConverter converter;
|
||||
@@ -98,8 +98,8 @@ class StringN1qlQueryCreatorTests extends ClusterAwareIntegrationTests {
|
||||
converter.getMappingContext());
|
||||
|
||||
StringN1qlQueryCreator creator = new StringN1qlQueryCreator(getAccessor(getParameters(method), "Continental"),
|
||||
queryMethod, converter, config().bucketname(), new SpelExpressionParser(),
|
||||
QueryMethodEvaluationContextProvider.DEFAULT, namedQueries);
|
||||
queryMethod, converter, new SpelExpressionParser(), QueryMethodEvaluationContextProvider.DEFAULT,
|
||||
namedQueries);
|
||||
|
||||
Query query = creator.createQuery();
|
||||
|
||||
@@ -131,8 +131,8 @@ class StringN1qlQueryCreatorTests extends ClusterAwareIntegrationTests {
|
||||
converter.getMappingContext());
|
||||
|
||||
StringN1qlQueryCreator creator = new StringN1qlQueryCreator(getAccessor(getParameters(method), "Continental"),
|
||||
queryMethod, converter, config().bucketname(), new SpelExpressionParser(),
|
||||
QueryMethodEvaluationContextProvider.DEFAULT, namedQueries);
|
||||
queryMethod, converter, new SpelExpressionParser(), QueryMethodEvaluationContextProvider.DEFAULT,
|
||||
namedQueries);
|
||||
|
||||
Query query = creator.createQuery();
|
||||
|
||||
@@ -84,13 +84,15 @@ class StringN1qlQueryCreatorMockedTests extends ClusterAwareIntegrationTests {
|
||||
converter.getMappingContext());
|
||||
|
||||
StringN1qlQueryCreator creator = new StringN1qlQueryCreator(getAccessor(getParameters(method), "Oliver", "Twist"),
|
||||
queryMethod, converter, "travel-sample", new SpelExpressionParser(),
|
||||
QueryMethodEvaluationContextProvider.DEFAULT, namedQueries);
|
||||
queryMethod, converter, new SpelExpressionParser(), QueryMethodEvaluationContextProvider.DEFAULT, namedQueries);
|
||||
|
||||
Query query = creator.createQuery();
|
||||
assertEquals(
|
||||
"SELECT `_class`, META(`travel-sample`).`cas` AS __cas, `createdBy`, `createdDate`, `lastModifiedBy`, `lastModifiedDate`, META(`travel-sample`).`id` AS __id, `firstname`, `lastname`, `subtype` FROM `travel-sample` where `_class` = \"abstractuser\" and firstname = $1 and lastname = $2",
|
||||
query.toN1qlSelectString(couchbaseTemplate.reactive(), User.class, false));
|
||||
"SELECT `_class`, META(`" + bucketName()
|
||||
+ "`).`cas` AS __cas, `createdBy`, `createdDate`, `lastModifiedBy`, `lastModifiedDate`, META(`"
|
||||
+ bucketName() + "`).`id` AS __id, `firstname`, `lastname`, `subtype` FROM `" + bucketName()
|
||||
+ "` where `_class` = \"abstractuser\" and firstname = $1 and lastname = $2",
|
||||
query.toN1qlSelectString(couchbaseTemplate.reactive(), null, null, User.class, User.class, false, null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -103,13 +105,15 @@ class StringN1qlQueryCreatorMockedTests extends ClusterAwareIntegrationTests {
|
||||
converter.getMappingContext());
|
||||
|
||||
StringN1qlQueryCreator creator = new StringN1qlQueryCreator(getAccessor(getParameters(method), "Oliver", "Twist"),
|
||||
queryMethod, converter, "travel-sample", new SpelExpressionParser(),
|
||||
QueryMethodEvaluationContextProvider.DEFAULT, namedQueries);
|
||||
queryMethod, converter, new SpelExpressionParser(), QueryMethodEvaluationContextProvider.DEFAULT, namedQueries);
|
||||
|
||||
Query query = creator.createQuery();
|
||||
assertEquals(
|
||||
"SELECT `_class`, META(`travel-sample`).`cas` AS __cas, `createdBy`, `createdDate`, `lastModifiedBy`, `lastModifiedDate`, META(`travel-sample`).`id` AS __id, `firstname`, `lastname`, `subtype` FROM `travel-sample` where `_class` = \"abstractuser\" and (firstname = $first or lastname = $last)",
|
||||
query.toN1qlSelectString(couchbaseTemplate.reactive(), User.class, false));
|
||||
"SELECT `_class`, META(`" + bucketName()
|
||||
+ "`).`cas` AS __cas, `createdBy`, `createdDate`, `lastModifiedBy`, `lastModifiedDate`, META(`"
|
||||
+ bucketName() + "`).`id` AS __id, `firstname`, `lastname`, `subtype` FROM `" + bucketName()
|
||||
+ "` where `_class` = \"abstractuser\" and (firstname = $first or lastname = $last)",
|
||||
query.toN1qlSelectString(couchbaseTemplate.reactive(), null, null, User.class, User.class, false, null, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -123,8 +127,8 @@ class StringN1qlQueryCreatorMockedTests extends ClusterAwareIntegrationTests {
|
||||
|
||||
try {
|
||||
StringN1qlQueryCreator creator = new StringN1qlQueryCreator(getAccessor(getParameters(method), "Oliver"),
|
||||
queryMethod, converter, "travel-sample", new SpelExpressionParser(),
|
||||
QueryMethodEvaluationContextProvider.DEFAULT, namedQueries);
|
||||
queryMethod, converter, new SpelExpressionParser(), QueryMethodEvaluationContextProvider.DEFAULT,
|
||||
namedQueries);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return;
|
||||
}
|
||||
@@ -141,14 +145,33 @@ class StringN1qlQueryCreatorMockedTests extends ClusterAwareIntegrationTests {
|
||||
|
||||
try {
|
||||
StringN1qlQueryCreator creator = new StringN1qlQueryCreator(getAccessor(getParameters(method), "Oliver"),
|
||||
queryMethod, converter, "travel-sample", new SpelExpressionParser(),
|
||||
QueryMethodEvaluationContextProvider.DEFAULT, namedQueries);
|
||||
queryMethod, converter, new SpelExpressionParser(), QueryMethodEvaluationContextProvider.DEFAULT,
|
||||
namedQueries);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return;
|
||||
}
|
||||
fail("should have failed with IllegalArgumentException: query has no inline Query or named Query not found");
|
||||
}
|
||||
|
||||
@Test
|
||||
void spelTests() throws Exception {
|
||||
String input = "spelTests";
|
||||
Method method = UserRepository.class.getMethod(input);
|
||||
CouchbaseQueryMethod queryMethod = new CouchbaseQueryMethod(method,
|
||||
new DefaultRepositoryMetadata(UserRepository.class), new SpelAwareProxyProjectionFactory(),
|
||||
converter.getMappingContext());
|
||||
|
||||
StringN1qlQueryCreator creator = new StringN1qlQueryCreator(getAccessor(getParameters(method)), queryMethod,
|
||||
converter, new SpelExpressionParser(), QueryMethodEvaluationContextProvider.DEFAULT, namedQueries);
|
||||
|
||||
Query query = creator.createQuery();
|
||||
|
||||
String s = query.toN1qlSelectString(couchbaseTemplate.reactive(), "myScope", "myCollection", User.class, null,
|
||||
false, null, null);
|
||||
System.out.println("query: " + s);
|
||||
|
||||
}
|
||||
|
||||
private ParameterAccessor getAccessor(Parameters<?, ?> params, Object... values) {
|
||||
return new ParametersParameterAccessor(params, values);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user