|
16 | 16 |
|
17 | 17 | package org.springframework.data.couchbase.repository;
|
18 | 18 |
|
| 19 | +import static com.couchbase.client.java.query.QueryScanConsistency.NOT_BOUNDED; |
| 20 | +import static com.couchbase.client.java.query.QueryScanConsistency.REQUEST_PLUS; |
19 | 21 | import static java.util.Arrays.asList;
|
20 | 22 | import static org.assertj.core.api.Assertions.assertThat;
|
21 | 23 | import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
25 | 27 | import static org.junit.jupiter.api.Assertions.assertNull;
|
26 | 28 | import static org.junit.jupiter.api.Assertions.assertThrows;
|
27 | 29 | import static org.junit.jupiter.api.Assertions.assertTrue;
|
| 30 | +import static org.springframework.data.couchbase.config.BeanNames.COUCHBASE_TEMPLATE; |
28 | 31 |
|
29 | 32 | import junit.framework.AssertionFailedError;
|
30 | 33 |
|
|
46 | 49 |
|
47 | 50 | import org.junit.jupiter.api.Test;
|
48 | 51 | import org.springframework.beans.factory.annotation.Autowired;
|
| 52 | +import org.springframework.context.ApplicationContext; |
| 53 | +import org.springframework.context.annotation.AnnotationConfigApplicationContext; |
49 | 54 | import org.springframework.context.annotation.Bean;
|
50 | 55 | import org.springframework.context.annotation.Configuration;
|
51 | 56 | import org.springframework.dao.DataIntegrityViolationException;
|
|
56 | 61 | import org.springframework.data.couchbase.core.CouchbaseQueryExecutionException;
|
57 | 62 | import org.springframework.data.couchbase.core.CouchbaseTemplate;
|
58 | 63 | import org.springframework.data.couchbase.core.RemoveResult;
|
59 |
| -import org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbaseEventListener; |
60 | 64 | import org.springframework.data.couchbase.core.query.N1QLExpression;
|
61 | 65 | import org.springframework.data.couchbase.core.query.QueryCriteria;
|
62 | 66 | import org.springframework.data.couchbase.domain.Address;
|
@@ -267,6 +271,78 @@ void findBySimplePropertyReturnType() {
|
267 | 271 | }
|
268 | 272 | }
|
269 | 273 |
|
| 274 | + @Test |
| 275 | + public void saveNotBounded() { |
| 276 | + // save() followed by query with NOT_BOUNDED will result in not finding the document |
| 277 | + Airport vie = new Airport("airports::vie", "vie", "low9"); |
| 278 | + Airport airport2 = null; |
| 279 | + for (int i = 1; i <= 100; i++) { |
| 280 | + // set version == 0 so save() will be an upsert, not a replace |
| 281 | + Airport saved = airportRepository.save(vie.clearVersion()); |
| 282 | + try { |
| 283 | + airport2 = airportRepository.iata(saved.getIata()); |
| 284 | + if (airport2 == null) { |
| 285 | + break; |
| 286 | + } |
| 287 | + } catch (DataRetrievalFailureException drfe) { |
| 288 | + airport2 = null; // |
| 289 | + } finally { |
| 290 | + // airportRepository.delete(vie); |
| 291 | + // instead of delete, use removeResult to test QueryOptions.consistentWith() |
| 292 | + RemoveResult removeResult = couchbaseTemplate.removeById().one(vie.getId()); |
| 293 | + assertEquals(vie.getId(), removeResult.getId()); |
| 294 | + assertTrue(removeResult.getCas() != 0); |
| 295 | + assertTrue(removeResult.getMutationToken().isPresent()); |
| 296 | + Airport airport3 = airportRepository.iata(vie.getIata()); |
| 297 | + assertNull(airport3, "should have been removed"); |
| 298 | + } |
| 299 | + } |
| 300 | + assertNull(airport2, "airport2 should have likely been null at least once"); |
| 301 | + Airport saved = airportRepository.save(vie.clearVersion()); |
| 302 | + couchbaseTemplate.findByQuery(Airport.class).withConsistency(REQUEST_PLUS).all(); |
| 303 | + airport2 = airportRepository.iata(vie.getIata()); |
| 304 | + RemoveResult removeResult = couchbaseTemplate.removeById().one(saved.getId()); |
| 305 | + assertNotNull(airport2, "airport2 should have been found"); |
| 306 | + } |
| 307 | + |
| 308 | + @Test |
| 309 | + public void saveNotBoundedRequestPlus() { |
| 310 | + ApplicationContext ac = new AnnotationConfigApplicationContext(ConfigRequestPlus.class); |
| 311 | + // the Config class has been modified, these need to be loaded again |
| 312 | + CouchbaseTemplate couchbaseTemplateRP = (CouchbaseTemplate) ac.getBean(COUCHBASE_TEMPLATE); |
| 313 | + AirportRepository airportRepositoryRP = (AirportRepository) ac.getBean("airportRepository"); |
| 314 | + |
| 315 | + // save() followed by query with NOT_BOUNDED will result in not finding the document |
| 316 | + Airport vie = new Airport("airports::vie", "vie", "low9"); |
| 317 | + Airport airport2 = null; |
| 318 | + for (int i = 1; i <= 100; i++) { |
| 319 | + // set version == 0 so save() will be an upsert, not a replace |
| 320 | + Airport saved = airportRepositoryRP.save(vie.clearVersion()); |
| 321 | + try { |
| 322 | + airport2 = airportRepositoryRP.iata(saved.getIata()); |
| 323 | + if (airport2 == null) { |
| 324 | + break; |
| 325 | + } |
| 326 | + } catch (DataRetrievalFailureException drfe) { |
| 327 | + airport2 = null; // |
| 328 | + } finally { |
| 329 | + // airportRepository.delete(vie); |
| 330 | + // instead of delete, use removeResult to test QueryOptions.consistentWith() |
| 331 | + RemoveResult removeResult = couchbaseTemplateRP.removeById().one(vie.getId()); |
| 332 | + assertEquals(vie.getId(), removeResult.getId()); |
| 333 | + assertTrue(removeResult.getCas() != 0); |
| 334 | + assertTrue(removeResult.getMutationToken().isPresent()); |
| 335 | + Airport airport3 = airportRepositoryRP.iata(vie.getIata()); |
| 336 | + assertNull(airport3, "should have been removed"); |
| 337 | + } |
| 338 | + } |
| 339 | + assertNotNull(airport2, "airport2 should have never been null"); |
| 340 | + Airport saved = airportRepositoryRP.save(vie.clearVersion()); |
| 341 | + List<Airport> airports = couchbaseTemplateRP.findByQuery(Airport.class).withConsistency(NOT_BOUNDED).all(); |
| 342 | + RemoveResult removeResult = couchbaseTemplateRP.removeById().one(saved.getId()); |
| 343 | + assertFalse(!airports.isEmpty(), "airports should have been empty"); |
| 344 | + } |
| 345 | + |
270 | 346 | @Test
|
271 | 347 | void findByTypeAlias() {
|
272 | 348 | Airport vie = null;
|
@@ -474,7 +550,7 @@ void count() {
|
474 | 550 | airportRepository.saveAll(
|
475 | 551 | Arrays.stream(iatas).map((iata) -> new Airport("airports::" + iata, iata, iata.toLowerCase(Locale.ROOT)))
|
476 | 552 | .collect(Collectors.toSet()));
|
477 |
| - couchbaseTemplate.findByQuery(Airport.class).withConsistency(QueryScanConsistency.REQUEST_PLUS).all(); |
| 553 | + couchbaseTemplate.findByQuery(Airport.class).withConsistency(REQUEST_PLUS).all(); |
478 | 554 | Long count = airportRepository.countFancyExpression(asList("JFK"), asList("jfk"), false);
|
479 | 555 | assertEquals(1, count);
|
480 | 556 |
|
@@ -677,7 +753,7 @@ void deleteAllById() {
|
677 | 753 | void couchbaseRepositoryQuery() throws Exception {
|
678 | 754 | User user = new User("1", "Dave", "Wilson");
|
679 | 755 | userRepository.save(user);
|
680 |
| - couchbaseTemplate.findByQuery(User.class).withConsistency(QueryScanConsistency.REQUEST_PLUS) |
| 756 | + couchbaseTemplate.findByQuery(User.class).withConsistency(REQUEST_PLUS) |
681 | 757 | .matching(QueryCriteria.where("firstname").is("Dave").and("`1`").is("`1`")).all();
|
682 | 758 | String input = "findByFirstname";
|
683 | 759 | Method method = UserRepository.class.getMethod(input, String.class);
|
@@ -809,4 +885,47 @@ public ValidatingCouchbaseEventListener validationEventListener() {
|
809 | 885 | return new ValidatingCouchbaseEventListener(validator());
|
810 | 886 | }
|
811 | 887 | }
|
| 888 | + |
| 889 | + } |
| 890 | + |
| 891 | + @Configuration |
| 892 | + @EnableCouchbaseRepositories("org.springframework.data.couchbase") |
| 893 | + @EnableCouchbaseAuditing(auditorAwareRef = "auditorAwareRef", dateTimeProviderRef = "dateTimeProviderRef") |
| 894 | + static class ConfigRequestPlus extends AbstractCouchbaseConfiguration { |
| 895 | + |
| 896 | + @Override |
| 897 | + public String getConnectionString() { |
| 898 | + return connectionString(); |
| 899 | + } |
| 900 | + |
| 901 | + @Override |
| 902 | + public String getUserName() { |
| 903 | + return config().adminUsername(); |
| 904 | + } |
| 905 | + |
| 906 | + @Override |
| 907 | + public String getPassword() { |
| 908 | + return config().adminPassword(); |
| 909 | + } |
| 910 | + |
| 911 | + @Override |
| 912 | + public String getBucketName() { |
| 913 | + return bucketName(); |
| 914 | + } |
| 915 | + |
| 916 | + @Bean(name = "auditorAwareRef") |
| 917 | + public NaiveAuditorAware testAuditorAware() { |
| 918 | + return new NaiveAuditorAware(); |
| 919 | + } |
| 920 | + |
| 921 | + @Bean(name = "dateTimeProviderRef") |
| 922 | + public DateTimeProvider testDateTimeProvider() { |
| 923 | + return new AuditingDateTimeProvider(); |
| 924 | + } |
| 925 | + |
| 926 | + @Override |
| 927 | + public QueryScanConsistency getDefaultConsistency() { |
| 928 | + return REQUEST_PLUS; |
| 929 | + } |
| 930 | + } |
812 | 931 | }
|
0 commit comments