Skip to content

Commit ff0079b

Browse files
committed
DefaultCouchbaseTypeMapper uses TypeAlias annotation if present.
DefaultCouchbaseTypeMapper uses TypeAlias annotation if present. Test case also uncovered that TypeAlias was being ignored for string queries. Closes #1119.
1 parent 37587a1 commit ff0079b

File tree

5 files changed

+84
-8
lines changed

5 files changed

+84
-8
lines changed

src/main/java/org/springframework/data/couchbase/core/convert/DefaultCouchbaseTypeMapper.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors
2+
* Copyright 2012-2021 the original author or authors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,17 +16,21 @@
1616

1717
package org.springframework.data.couchbase.core.convert;
1818

19+
import java.util.Collections;
20+
1921
import org.springframework.data.convert.DefaultTypeMapper;
2022
import org.springframework.data.convert.TypeAliasAccessor;
2123
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
2224
import org.springframework.data.mapping.Alias;
25+
import org.springframework.data.mapping.context.MappingContext;
2326
import org.springframework.data.util.TypeInformation;
2427

2528
/**
2629
* The Couchbase Type Mapper.
2730
*
2831
* @author Michael Nitschinger
2932
* @author Mark Paluch
33+
* @author Michael Reiche
3034
*/
3135
public class DefaultCouchbaseTypeMapper extends DefaultTypeMapper<CouchbaseDocument> implements CouchbaseTypeMapper {
3236

@@ -43,7 +47,8 @@ public class DefaultCouchbaseTypeMapper extends DefaultTypeMapper<CouchbaseDocum
4347
* @param typeKey the typeKey to use.
4448
*/
4549
public DefaultCouchbaseTypeMapper(final String typeKey) {
46-
super(new CouchbaseDocumentTypeAliasAccessor(typeKey));
50+
super(new CouchbaseDocumentTypeAliasAccessor(typeKey), (MappingContext) null,
51+
Collections.singletonList(new TypeAwareTypeInformationMapper()));
4752
this.typeKey = typeKey;
4853
}
4954

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2012-2021 the original author or authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.couchbase.core.convert;
17+
18+
import org.springframework.data.annotation.TypeAlias;
19+
import org.springframework.data.convert.SimpleTypeInformationMapper;
20+
import org.springframework.data.mapping.Alias;
21+
import org.springframework.data.util.TypeInformation;
22+
23+
/**
24+
* TypeAwareTypeInformationMapper - leverages @TypeAlias
25+
*
26+
* @author Michael Reiche
27+
*/
28+
public class TypeAwareTypeInformationMapper extends SimpleTypeInformationMapper {
29+
30+
@Override
31+
public Alias createAliasFor(TypeInformation<?> type) {
32+
TypeAlias[] typeAlias = type.getType().getAnnotationsByType(TypeAlias.class);
33+
34+
if (typeAlias.length == 1) {
35+
return Alias.of(typeAlias[0].value());
36+
}
37+
38+
return super.createAliasFor(type);
39+
}
40+
}

src/main/java/org/springframework/data/couchbase/repository/query/StringN1qlQueryCreator.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.data.couchbase.core.query.QueryCriteria;
2828
import org.springframework.data.couchbase.core.query.StringQuery;
2929
import org.springframework.data.domain.Sort;
30+
import org.springframework.data.mapping.Alias;
3031
import org.springframework.data.mapping.PersistentPropertyPath;
3132
import org.springframework.data.mapping.context.MappingContext;
3233
import org.springframework.data.repository.core.NamedQueries;
@@ -36,6 +37,8 @@
3637
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
3738
import org.springframework.data.repository.query.parser.Part;
3839
import org.springframework.data.repository.query.parser.PartTree;
40+
import org.springframework.data.util.ClassTypeInformation;
41+
import org.springframework.data.util.TypeInformation;
3942
import org.springframework.expression.spel.standard.SpelExpressionParser;
4043

4144
import com.couchbase.client.java.json.JsonArray;
@@ -81,8 +84,15 @@ public StringN1qlQueryCreator(final ParameterAccessor accessor, CouchbaseQueryMe
8184
} else {
8285
throw new IllegalArgumentException("query has no inline Query or named Query not found");
8386
}
87+
Class javaType = getType();
88+
String typeValue = javaType.getName();
89+
TypeInformation<?> typeInfo = ClassTypeInformation.from(javaType);
90+
Alias alias = couchbaseConverter.getTypeAlias(typeInfo);
91+
if (alias != null && alias.isPresent()) {
92+
typeValue = alias.toString();
93+
}
8494
this.queryParser = new StringBasedN1qlQueryParser(queryString, queryMethod, bucketName, couchbaseConverter,
85-
getTypeField(), getTypeValue(), accessor, spelExpressionParser, evaluationContextProvider);
95+
getTypeField(), typeValue, accessor, spelExpressionParser, evaluationContextProvider);
8696
this.parser = spelExpressionParser;
8797
this.parsedExpression = this.queryParser.parsedExpression;
8898
}
@@ -95,8 +105,8 @@ protected String getTypeField() {
95105
return couchbaseConverter.getTypeKey();
96106
}
97107

98-
protected String getTypeValue() {
99-
return getQueryMethod().getEntityInformation().getJavaType().getName();
108+
protected Class getType() {
109+
return getQueryMethod().getEntityInformation().getJavaType();
100110
}
101111

102112
@Override

src/test/java/org/springframework/data/couchbase/domain/Airport.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import org.springframework.data.annotation.Id;
2020
import org.springframework.data.annotation.PersistenceConstructor;
21+
import org.springframework.data.annotation.TypeAlias;
2122
import org.springframework.data.couchbase.core.mapping.Document;
2223

2324
/**
@@ -27,6 +28,7 @@
2728
* @author Michael Reiche
2829
*/
2930
@Document
31+
@TypeAlias("airport")
3032
public class Airport extends ComparableEntity {
3133
@Id String id;
3234

src/test/java/org/springframework/data/couchbase/repository/CouchbaseRepositoryQueryIntegrationTests.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import java.util.concurrent.Future;
3535
import java.util.stream.Collectors;
3636

37-
import com.couchbase.client.java.query.QueryScanConsistency;
3837
import org.junit.jupiter.api.BeforeEach;
3938
import org.junit.jupiter.api.Test;
4039
import org.springframework.beans.factory.annotation.Autowired;
@@ -43,6 +42,8 @@
4342
import org.springframework.data.couchbase.CouchbaseClientFactory;
4443
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
4544
import org.springframework.data.couchbase.core.CouchbaseTemplate;
45+
import org.springframework.data.couchbase.core.query.N1QLExpression;
46+
import org.springframework.data.couchbase.core.query.Query;
4647
import org.springframework.data.couchbase.core.query.QueryCriteria;
4748
import org.springframework.data.couchbase.domain.Address;
4849
import org.springframework.data.couchbase.domain.Airport;
@@ -67,6 +68,7 @@
6768
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
6869

6970
import com.couchbase.client.core.error.IndexExistsException;
71+
import com.couchbase.client.java.query.QueryScanConsistency;
7072

7173
/**
7274
* Repository tests
@@ -168,6 +170,20 @@ void findBySimpleProperty() {
168170
}
169171
}
170172

173+
@Test
174+
void findByTypeAlias() {
175+
Airport vie = null;
176+
try {
177+
vie = new Airport("airports::vie", "vie", "loww");
178+
vie = airportRepository.save(vie);
179+
List<Airport> airports = couchbaseTemplate.findByQuery(Airport.class)
180+
.matching(new Query(QueryCriteria.where(N1QLExpression.x("_class")).is("airport"))).all();
181+
assertFalse(airports.isEmpty(), "should have found aiport");
182+
} finally {
183+
airportRepository.delete(vie);
184+
}
185+
}
186+
171187
@Test
172188
void findByEnum() {
173189
Airport vie = null;
@@ -180,6 +196,7 @@ void findByEnum() {
180196
airportRepository.delete(vie);
181197
}
182198
}
199+
183200
@Test
184201
public void testCas() {
185202
User user = new User("1", "Dave", "Wilson");
@@ -200,6 +217,7 @@ void count() {
200217
airportRepository.saveAll(
201218
Arrays.stream(iatas).map((iata) -> new Airport("airports::" + iata, iata, iata.toLowerCase(Locale.ROOT)))
202219
.collect(Collectors.toSet()));
220+
couchbaseTemplate.findByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all();
203221
Long count = airportRepository.countFancyExpression(asList("JFK"), asList("jfk"), false);
204222
assertEquals(1, count);
205223

@@ -332,14 +350,15 @@ void deleteAllById() {
332350
void couchbaseRepositoryQuery() throws Exception {
333351
User user = new User("1", "Dave", "Wilson");
334352
userRepository.save(user);
335-
couchbaseTemplate.findByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).matching(QueryCriteria.where("firstname").is("Dave").and("`1`").is("`1`")).all();
353+
couchbaseTemplate.findByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS)
354+
.matching(QueryCriteria.where("firstname").is("Dave").and("`1`").is("`1`")).all();
336355
String input = "findByFirstname";
337356
Method method = UserRepository.class.getMethod(input, String.class);
338357
CouchbaseQueryMethod queryMethod = new CouchbaseQueryMethod(method,
339358
new DefaultRepositoryMetadata(UserRepository.class), new SpelAwareProxyProjectionFactory(),
340359
couchbaseTemplate.getConverter().getMappingContext());
341360
CouchbaseRepositoryQuery query = new CouchbaseRepositoryQuery(couchbaseTemplate, queryMethod, null);
342-
List<User> users = (List<User>)query.execute(new String[] { "Dave" });
361+
List<User> users = (List<User>) query.execute(new String[] { "Dave" });
343362
assertEquals(user, users.get(0));
344363
}
345364

0 commit comments

Comments
 (0)