Full Reactive Repository Support, Rebranding DocumentDb to CosmosDb (#434)
* Addind reactive repository support * deleteAll fix * Fixing deleteAll issue Rebranding DocumentDB types to Cosmos Removing docdb dependency Upgrading SDK to 3.2 Changing perf tests to use 3.2 sync api Other refactoring * Upgraded pom.xml to use new spring RC versions. Made other changes to support new versions * Updated pom.xml to milestone version * Removing unused imports * Renaming bean method * Renamed documentdb to cosmosdb * updated pom.xml with correct file name * Added new APIs for find by id with partitionkey * Updated cosmos factory to take in connection policy and consistency level in account while creating cosmos client * Removed and implemented some of the TODOs from spring feedback * Updated readme to reflect CosmosRepository * Updated Reactive Cosmos Entity MetaData to be used in Reactive Cosmos Query pipeline * Updated sample to full reactive support. Updated error handlers for reactive cosmos template to throw CosmosDbAccessException
This commit is contained in:
Родитель
6c207219a5
Коммит
d028e00ab9
|
@ -1,3 +1,3 @@
|
|||
exclude_paths:
|
||||
- 'src/test/java/com/microsoft/azure/spring/data/cosmosdb/domain/Person.java'
|
||||
- 'src/test/java/com/microsoft/azure/spring/data/cosmosdb/repository/support/DocumentDbEntityInformationUnitTest.java'
|
||||
- 'src/test/java/com/microsoft/azure/spring/data/cosmosdb/repository/support/CosmosEntityInformationUnitTest.java'
|
44
README.md
44
README.md
|
@ -29,7 +29,7 @@ Please refer to [sample project here](./samplecode).
|
|||
This repository supports both Spring Data 1.x and 2.x. Please see [this document](https://github.com/Microsoft/spring-data-cosmosdb/wiki/Spring-Data-dependency-version-management) about more details and corresponding branch mapping.
|
||||
|
||||
## Feature List
|
||||
- Spring Data CRUDRepository basic CRUD functionality
|
||||
- Spring Data ReactiveCrudRepository CrudRepository basic CRUD functionality
|
||||
- save
|
||||
- findAll
|
||||
- findOne by Id
|
||||
|
@ -73,7 +73,7 @@ If you are using Maven, add the following dependency.
|
|||
<dependency>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>spring-data-cosmosdb</artifactId>
|
||||
<version>2.1.7</version>
|
||||
<version>2.2.0.M1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
@ -83,10 +83,17 @@ Setup configuration class.
|
|||
CosmosKeyCredential feature provides capability to rotate keys on the fly. You can switch keys using switchToSecondaryKey().
|
||||
For more information on this, see the Sample Application code.
|
||||
|
||||
### Sync and Reactive Repository support
|
||||
2.2.x supports both sync and reactive repository support.
|
||||
|
||||
Use `@EnableCosmosRepositories` to enable sync repository support.
|
||||
|
||||
For reactive repository support, use `@EnableReactiveCosmosRepositories`
|
||||
|
||||
```java
|
||||
@Configuration
|
||||
@EnableDocumentDbRepositories
|
||||
public class AppConfiguration extends AbstractDocumentDbConfiguration {
|
||||
@EnableCosmosRepositories
|
||||
public class AppConfiguration extends AbstractCosmosConfiguration {
|
||||
|
||||
@Value("${azure.cosmosdb.uri}")
|
||||
private String uri;
|
||||
|
@ -102,9 +109,9 @@ public class AppConfiguration extends AbstractDocumentDbConfiguration {
|
|||
|
||||
private CosmosKeyCredential cosmosKeyCredential;
|
||||
|
||||
public DocumentDBConfig getConfig() {
|
||||
public CosmosDBConfig getConfig() {
|
||||
this.cosmosKeyCredential = new CosmosKeyCredential(key);
|
||||
return DocumentDBConfig.builder(uri, this.cosmosKeyCredential, dbName).build();
|
||||
return CosmosDBConfig.builder(uri, this.cosmosKeyCredential, dbName).build();
|
||||
}
|
||||
|
||||
public void switchToSecondaryKey() {
|
||||
|
@ -114,19 +121,19 @@ public class AppConfiguration extends AbstractDocumentDbConfiguration {
|
|||
```
|
||||
Or if you want to customize your config:
|
||||
```java
|
||||
public DocumentDBConfig getConfig() {
|
||||
public CosmosDBConfig getConfig() {
|
||||
this.cosmosKeyCredential = new CosmosKeyCredential(key);
|
||||
DocumentDBConfig dbConfig = DocumentDBConfig.builder(uri, this.cosmosKeyCredential, dbName).build();
|
||||
dbConfig.getConnectionPolicy().setConnectionMode(ConnectionMode.DirectHttps);
|
||||
dbConfig.getConnectionPolicy().setMaxPoolSize(1000);
|
||||
return dbConfig;
|
||||
CosmosDBConfig cosmosDbConfig = CosmosDBConfig.builder(uri, this.cosmosKeyCredential, dbName).build();
|
||||
cosmosDbConfig.getConnectionPolicy().setConnectionMode(ConnectionMode.DIRECT);
|
||||
cosmosDbConfig.getConnectionPolicy().setMaxPoolSize(1000);
|
||||
return cosmosDbConfig;
|
||||
}
|
||||
```
|
||||
By default, `@EnableDocumentDbRepositories` will scan the current package for any interfaces that extend one of Spring Data's repository interfaces. Using it to annotate your Configuration class to scan a different root package by type if your project layout has multiple projects and it's not finding your repositories.
|
||||
By default, `@EnableCosmosRepositories` will scan the current package for any interfaces that extend one of Spring Data's repository interfaces. Using it to annotate your Configuration class to scan a different root package by type if your project layout has multiple projects and it's not finding your repositories.
|
||||
```java
|
||||
@Configuration
|
||||
@EnableDocumentDbRepositories(basePackageClass=UserRepository.class)
|
||||
public class AppConfiguration extends AbstractDocumentDbConfiguration {
|
||||
@EnableCosmosRepositories(basePackageClass=UserRepository.class)
|
||||
public class AppConfiguration extends AbstractCosmosConfiguration {
|
||||
// configuration code
|
||||
}
|
||||
```
|
||||
|
@ -140,6 +147,7 @@ Define a simple entity as Document in Azure Cosmos DB.
|
|||
public class User {
|
||||
private String id;
|
||||
private String firstName;
|
||||
|
||||
@PartitionKey
|
||||
private String lastName;
|
||||
|
||||
|
@ -178,14 +186,14 @@ public class User {
|
|||
```
|
||||
|
||||
### Create repositories
|
||||
Extends DocumentDbRepository interface, which provides Spring Data repository support.
|
||||
Extends CosmosRepository interface, which provides Spring Data repository support.
|
||||
|
||||
```java
|
||||
import DocumentDbRepository;
|
||||
import CosmosRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface UserRepository extends DocumentDbRepository<User, String> {
|
||||
public interface UserRepository extends CosmosRepository<User, String> {
|
||||
List<User> findByFirstName(String firstName);
|
||||
}
|
||||
```
|
||||
|
@ -232,7 +240,7 @@ public class SampleApplication implements CommandLineRunner {
|
|||
}
|
||||
}
|
||||
```
|
||||
Autowired UserRepository interface, then can do save, delete and find operations. Spring Data Azure Cosmos DB uses the DocumentTemplate to execute the queries behind *find*, *save* methods. You can use the template yourself for more complex queries.
|
||||
Autowired UserRepository interface, then can do save, delete and find operations. Spring Data Azure Cosmos DB uses the CosmosTemplate to execute the queries behind *find*, *save* methods. You can use the template yourself for more complex queries.
|
||||
|
||||
## Snapshots
|
||||
[![Nexus OSS](https://img.shields.io/nexus/snapshots/https/oss.sonatype.org/com.microsoft.azure/spring-data-cosmosdb.svg)](https://oss.sonatype.org/content/repositories/snapshots/com/microsoft/azure/spring-data-cosmosdb/)
|
||||
|
|
32
pom.xml
32
pom.xml
|
@ -6,7 +6,7 @@
|
|||
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>spring-data-cosmosdb</artifactId>
|
||||
<version>2.1.8-SNAPSHOT</version>
|
||||
<version>2.2.0.M1</version>
|
||||
|
||||
<name>Spring Data for Azure Cosmos DB SQL API</name>
|
||||
<description>Spring Data for Azure Cosmos DB SQL API</description>
|
||||
|
@ -45,8 +45,8 @@
|
|||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.build.timestamp.format>MM-dd-HH-mm-ss</maven.build.timestamp.format>
|
||||
|
||||
<spring.springframework.version>5.1.9.RELEASE</spring.springframework.version>
|
||||
<spring.data.version>2.1.10.RELEASE</spring.data.version>
|
||||
<spring.springframework.version>5.2.0.RC2</spring.springframework.version>
|
||||
<spring.data.version>2.2.0.RC3</spring.data.version>
|
||||
<fasterxml.jackson.version>2.9.5</fasterxml.jackson.version>
|
||||
|
||||
<mockito.core.version>2.8.9</mockito.core.version>
|
||||
|
@ -58,8 +58,7 @@
|
|||
<gson.version>2.8.4</gson.version>
|
||||
<project.reactor.test.version>3.2.5.RELEASE</project.reactor.test.version>
|
||||
|
||||
<azure.documentdb.version>1.16.2</azure.documentdb.version>
|
||||
<azure.cosmos.version>3.1.0</azure.cosmos.version>
|
||||
<azure.cosmos.version>3.2.0</azure.cosmos.version>
|
||||
<azure.test.resourcegroup>spring-data-cosmosdb-test</azure.test.resourcegroup>
|
||||
<azure.test.dbname>testdb-${maven.build.timestamp}</azure.test.dbname>
|
||||
<skip.integration.tests>true</skip.integration.tests>
|
||||
|
@ -67,6 +66,14 @@
|
|||
<test.on.emualator>false</test.on.emualator>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-milestone</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>http://repo.spring.io/libs-milestone</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
|
@ -115,13 +122,6 @@
|
|||
<artifactId>spring-expression</artifactId>
|
||||
<version>${spring.springframework.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>azure-documentdb</artifactId>
|
||||
<version>${azure.documentdb.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>azure-cosmos</artifactId>
|
||||
|
@ -143,7 +143,11 @@
|
|||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>${fasterxml.jackson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>20140107</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
|
@ -232,7 +236,7 @@
|
|||
<failOnError>false</failOnError>
|
||||
<sourceFileExcludes>
|
||||
<exclude>
|
||||
com/microsoft/azure/spring/data/cosmosdb/documentdb/core/mapping/BasicDocumentDbPersistentProperty.java
|
||||
com/microsoft/azure/spring/data/cosmosdb/documentdb/core/mapping/BasicCosmosPersistentProperty.java
|
||||
</exclude>
|
||||
</sourceFileExcludes>
|
||||
</configuration>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>spring-data-cosmosdb-samples</artifactId>
|
||||
<version>2.1.8-SNAPSHOT</version>
|
||||
<version>2.2.0.M1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
|||
<dependency>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>spring-data-cosmosdb</artifactId>
|
||||
<version>2.1.8-SNAPSHOT</version>
|
||||
<version>2.2.0.M1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
|
|
@ -15,13 +15,11 @@
|
|||
*/
|
||||
package example.springdata.cosmosdb;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
@ -67,40 +65,28 @@ public class Application implements CommandLineRunner{
|
|||
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
printList(this.repository.findByEmailOrName(this.user_1.getEmail(), this.user_1.getName()));
|
||||
printList(this.repository.findByEmailOrName(this.user_1.getEmail(),
|
||||
this.user_1.getName()).collectList().block());
|
||||
|
||||
printList(this.repository.findByCount(COUNT, Sort.by(new Sort.Order(Sort.Direction.ASC, "count"))));
|
||||
printList(this.repository.findByCount(COUNT,
|
||||
Sort.by(new Sort.Order(Sort.Direction.ASC, "count"))).collectList().block());
|
||||
|
||||
printList(this.repository.findByNameIn(Arrays.asList(this.user_1.getName(), "fake-name")));
|
||||
|
||||
queryByPageable();
|
||||
}
|
||||
|
||||
private void queryByPageable() {
|
||||
final int pageSize = 2;
|
||||
final Pageable pageable = new DocumentDbPageRequest(0, pageSize, null);
|
||||
final Page<User> page = this.repository.findByAddress(address, pageable);
|
||||
System.out.println("***** Printing Page 1 *****");
|
||||
printList(page.getContent());
|
||||
|
||||
final Page<User> nextPage = this.repository.findByAddress(address, page.getPageable());
|
||||
System.out.println("***** Printing Page 2 *****");
|
||||
printList(nextPage.getContent());
|
||||
printList(this.repository.findByNameIn(Arrays.asList(this.user_1.getName(),
|
||||
"fake-name")).collectList().block());
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void setup() {
|
||||
this.repository.save(user_1);
|
||||
this.repository.save(user_2);
|
||||
this.repository.save(user_3);
|
||||
this.repository.save(user_1).block();
|
||||
this.repository.saveAll(Lists.newArrayList(user_2, user_3)).collectList().block();
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void cleanup() {
|
||||
this.repository.deleteAll();
|
||||
this.repository.deleteAll().block();
|
||||
}
|
||||
|
||||
private void printList(List<User> users) {
|
||||
users.forEach(user -> System.out.println(user));
|
||||
users.forEach(System.out::println);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||
@Getter
|
||||
@Setter
|
||||
@ConfigurationProperties(prefix = "azure.cosmosdb")
|
||||
public class DocumentDbProperties {
|
||||
public class CosmosDbProperties {
|
||||
|
||||
private String uri;
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
package example.springdata.cosmosdb;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
@ -37,6 +38,7 @@ public class User {
|
|||
|
||||
private String email;
|
||||
|
||||
@PartitionKey
|
||||
private String name;
|
||||
|
||||
private Long count;
|
||||
|
|
|
@ -16,30 +16,28 @@
|
|||
|
||||
package example.springdata.cosmosdb;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
@RepositoryRestResource(collectionResourceRel = "user", path = "user")
|
||||
public interface UserRepository extends DocumentDbRepository<User, String> {
|
||||
public interface UserRepository extends ReactiveCosmosRepository<User, String> {
|
||||
|
||||
List<User> findByName(String firstName);
|
||||
Flux<User> findByName(String firstName);
|
||||
|
||||
List<User> findByEmailAndAddress(String email, Address address);
|
||||
Flux<User> findByEmailAndAddress(String email, Address address);
|
||||
|
||||
List<User> findByEmailOrName(String email, String Name);
|
||||
Flux<User> findByEmailOrName(String email, String name);
|
||||
|
||||
List<User> findByCount(Long count, Sort sort);
|
||||
Flux<User> findByCount(Long count, Sort sort);
|
||||
|
||||
List<User> findByNameIn(Collection<String> names);
|
||||
Flux<User> findByNameIn(Collection<String> names);
|
||||
|
||||
Page<User> findByAddress(Address address, Pageable pageable);
|
||||
Flux<User> findByAddress(Address address);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,9 @@
|
|||
package example.springdata.cosmosdb;
|
||||
|
||||
import com.azure.data.cosmos.CosmosKeyCredential;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.AbstractDocumentDbConfiguration;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.config.EnableDocumentDbRepositories;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.AbstractCosmosConfiguration;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.config.EnableReactiveCosmosRepositories;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -27,20 +27,20 @@ import org.springframework.context.annotation.PropertySource;
|
|||
|
||||
|
||||
@Configuration
|
||||
@EnableDocumentDbRepositories
|
||||
@EnableConfigurationProperties(DocumentDbProperties.class)
|
||||
@EnableConfigurationProperties(CosmosDbProperties.class)
|
||||
@EnableReactiveCosmosRepositories
|
||||
@PropertySource("classpath:application.properties")
|
||||
public class UserRepositoryConfiguration extends AbstractDocumentDbConfiguration {
|
||||
public class UserRepositoryConfiguration extends AbstractCosmosConfiguration {
|
||||
|
||||
@Autowired
|
||||
private DocumentDbProperties properties;
|
||||
private CosmosDbProperties properties;
|
||||
|
||||
private CosmosKeyCredential cosmosKeyCredential;
|
||||
|
||||
@Bean
|
||||
public DocumentDBConfig documentDBConfig() {
|
||||
public CosmosDBConfig cosmosDbConfig() {
|
||||
this.cosmosKeyCredential = new CosmosKeyCredential(properties.getKey());
|
||||
return DocumentDBConfig.builder(properties.getUri(), cosmosKeyCredential, properties.getDatabase()).build();
|
||||
return CosmosDBConfig.builder(properties.getUri(), cosmosKeyCredential, properties.getDatabase()).build();
|
||||
}
|
||||
|
||||
public void switchToSecondaryKey() {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=example.springdata.cosmosdb.UserRepositoryConfiguration
|
|
@ -15,20 +15,18 @@
|
|||
*/
|
||||
package example.springdata.cosmosdb;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.DocumentDBAccessException;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
@ -55,11 +53,6 @@ public class UserRepositoryIntegrationTest {
|
|||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.repository.deleteAll();
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
// Switch back to primary key to reset the invalid key
|
||||
|
@ -67,7 +60,7 @@ public class UserRepositoryIntegrationTest {
|
|||
final UserRepositoryConfiguration bean =
|
||||
applicationContext.getBean(UserRepositoryConfiguration.class);
|
||||
bean.switchToPrimaryKey();
|
||||
this.repository.deleteAll();
|
||||
this.repository.deleteAll().block();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -77,15 +70,15 @@ public class UserRepositoryIntegrationTest {
|
|||
final Role contributor = new Role(ROLE_CONTRIBUTOR, COST_CONTRIBUTOR);
|
||||
final User user = new User(ID, EMAIL, NAME, COUNT, address, Arrays.asList(creator, contributor));
|
||||
|
||||
this.repository.save(user);
|
||||
this.repository.save(user).block();
|
||||
|
||||
// Test for findById
|
||||
User result = this.repository.findById(ID).get();
|
||||
User result = this.repository.findById(ID).block();
|
||||
Assert.notNull(result, "should be exist in database");
|
||||
Assert.isTrue(result.getId().equals(ID), "should be the same id");
|
||||
|
||||
// Test for findByName
|
||||
List<User> resultList = this.repository.findByName(user.getName());
|
||||
List<User> resultList = this.repository.findByName(user.getName()).collectList().block();
|
||||
Assert.isTrue(resultList.size() == 1, "should be only one user here");
|
||||
Assert.isTrue(resultList.get(0).getName().equals(user.getName()), "should be same Name");
|
||||
Assert.notNull(result.getRoleList(), "roleList should not be null");
|
||||
|
@ -100,7 +93,7 @@ public class UserRepositoryIntegrationTest {
|
|||
}
|
||||
|
||||
// Test for findByEmailAndAddress
|
||||
resultList = this.repository.findByEmailAndAddress(user.getEmail(), user.getAddress());
|
||||
resultList = this.repository.findByEmailAndAddress(user.getEmail(), user.getAddress()).collectList().block();
|
||||
Assert.isTrue(resultList.size() == 1, "should be only one user here");
|
||||
|
||||
result = resultList.get(0);
|
||||
|
@ -110,22 +103,22 @@ public class UserRepositoryIntegrationTest {
|
|||
Assert.isTrue(result.getAddress().getCity().equals(user.getAddress().getCity()), "should be same City");
|
||||
Assert.isTrue(result.getAddress().getStreet().equals(user.getAddress().getStreet()), "should be same street");
|
||||
|
||||
resultList = this.repository.findByEmailOrName(user.getEmail(), user.getName());
|
||||
resultList = this.repository.findByEmailOrName(user.getEmail(), user.getName()).collectList().block();
|
||||
result = resultList.get(0);
|
||||
Assert.isTrue(result.getId().equals(user.getId()), "should be the same Id");
|
||||
|
||||
resultList = this.repository.findByCount(COUNT, Sort.by(new Sort.Order(Sort.Direction.ASC, "count")));
|
||||
resultList = this.repository.findByCount(COUNT,
|
||||
Sort.by(new Sort.Order(Sort.Direction.ASC, "count"))).collectList().block();
|
||||
result = resultList.get(0);
|
||||
Assert.isTrue(result.getId().equals(user.getId()), "should be the same Id");
|
||||
|
||||
resultList = this.repository.findByNameIn(Arrays.asList(user.getName(), "fake-name"));
|
||||
resultList = this.repository.findByNameIn(Arrays.asList(user.getName(), "fake-name")).collectList().block();
|
||||
result = resultList.get(0);
|
||||
Assert.isTrue(result.getId().equals(user.getId()), "should be the same Id");
|
||||
|
||||
// Test for findByAddress
|
||||
final Pageable pageable = new DocumentDbPageRequest(0, 2, null);
|
||||
Page<User> page = this.repository.findByAddress(address, pageable);
|
||||
resultList = page.getContent();
|
||||
final Flux<User> findByAddressFlux = this.repository.findByAddress(address);
|
||||
resultList = findByAddressFlux.collectList().block();
|
||||
result = resultList.get(0);
|
||||
Assert.isTrue(result.getId().equals(user.getId()), "should be the same Id");
|
||||
}
|
||||
|
@ -143,32 +136,32 @@ public class UserRepositoryIntegrationTest {
|
|||
final Role contributor = new Role(ROLE_CONTRIBUTOR, COST_CONTRIBUTOR);
|
||||
final User user = new User(ID, EMAIL, NAME, COUNT, address, Arrays.asList(creator, contributor));
|
||||
|
||||
this.repository.save(user);
|
||||
this.repository.save(user).block();
|
||||
|
||||
// Test for findById
|
||||
final User result = this.repository.findById(ID).get();
|
||||
final User result = this.repository.findById(ID).block();
|
||||
Assert.notNull(result, "should be exist in database");
|
||||
Assert.isTrue(result.getId().equals(ID), "should be the same id");
|
||||
|
||||
// Test for findByName
|
||||
final List<User> resultList = this.repository.findByName(user.getName());
|
||||
final List<User> resultList = this.repository.findByName(user.getName()).collectList().block();
|
||||
Assert.isTrue(resultList.size() == 1, "should be only one user here");
|
||||
Assert.isTrue(resultList.get(0).getName().equals(user.getName()), "should be same Name");
|
||||
Assert.notNull(result.getRoleList(), "roleList should not be null");
|
||||
Assert.isTrue(result.getRoleList().size() == user.getRoleList().size(), "must be the same list size");
|
||||
}
|
||||
|
||||
@Test(expected = DocumentDBAccessException.class)
|
||||
@Test(expected = CosmosDBAccessException.class)
|
||||
public void testInvalidSecondaryKey() {
|
||||
final Address address = new Address(POSTAL_CODE, STREET, CITY);
|
||||
final Role creator = new Role(ROLE_CREATOR, COST_CREATOR);
|
||||
final Role contributor = new Role(ROLE_CONTRIBUTOR, COST_CONTRIBUTOR);
|
||||
final User user = new User(ID, EMAIL, NAME, COUNT, address, Arrays.asList(creator, contributor));
|
||||
|
||||
this.repository.save(user);
|
||||
this.repository.save(user).block();
|
||||
|
||||
// Test for findById
|
||||
final User result = this.repository.findById(ID).get();
|
||||
final User result = this.repository.findById(ID).block();
|
||||
Assert.notNull(result, "should be exist in database");
|
||||
Assert.isTrue(result.getId().equals(ID), "should be the same id");
|
||||
|
||||
|
@ -178,7 +171,7 @@ public class UserRepositoryIntegrationTest {
|
|||
bean.switchKey("Invalid key");
|
||||
|
||||
// Test for findByName
|
||||
this.repository.findByName(user.getName());
|
||||
this.repository.findById(user.getId()).block();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>spring-data-cosmosdb-samples</artifactId>
|
||||
<version>2.1.8-SNAPSHOT</version>
|
||||
<version>2.2.0.M1</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<parent>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb;
|
||||
|
||||
import com.microsoft.azure.documentdb.IndexingMode;
|
||||
import com.azure.data.cosmos.IndexingMode;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
|
@ -15,15 +15,15 @@ public class Constants {
|
|||
public static final String DEFAULT_COLLECTION_NAME = "";
|
||||
public static final String DEFAULT_REQUEST_UNIT = "4000";
|
||||
public static final boolean DEFAULT_INDEXINGPOLICY_AUTOMATIC = true;
|
||||
public static final IndexingMode DEFAULT_INDEXINGPOLICY_MODE = IndexingMode.Consistent;
|
||||
public static final IndexingMode DEFAULT_INDEXINGPOLICY_MODE = IndexingMode.CONSISTENT;
|
||||
public static final String DEFAULT_REPOSITORY_IMPLEMENT_POSTFIX = "Impl";
|
||||
public static final int DEFAULT_TIME_TO_LIVE = -1; // Indicates never expire
|
||||
|
||||
public static final String ID_PROPERTY_NAME = "id";
|
||||
|
||||
public static final String DOCUMENTDB_MODULE_NAME = "cosmosdb";
|
||||
public static final String DOCUMENTDB_MODULE_PREFIX = "cosmosdb";
|
||||
public static final String DOCUMENTDB_MAPPING_CONTEXT_NAME = "documentDbMappingContext";
|
||||
public static final String COSMOSDB_MODULE_NAME = "cosmosdb";
|
||||
public static final String COSMOSDB_MODULE_PREFIX = "cosmosdb";
|
||||
public static final String COSMOS_MAPPING_CONTEXT = "cosmosMappingContext";
|
||||
|
||||
public static final String USER_AGENT_SUFFIX = "spring-data/";
|
||||
|
||||
|
|
|
@ -6,12 +6,13 @@
|
|||
|
||||
package com.microsoft.azure.spring.data.cosmosdb;
|
||||
|
||||
import com.azure.data.cosmos.ConnectionPolicy;
|
||||
import com.azure.data.cosmos.CosmosClient;
|
||||
import com.microsoft.azure.documentdb.ConnectionPolicy;
|
||||
import com.azure.data.cosmos.sync.CosmosSyncClient;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.MacAddress;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.PropertyLoader;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.TelemetrySender;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
|
@ -22,7 +23,7 @@ import javax.annotation.PostConstruct;
|
|||
public class CosmosDbFactory {
|
||||
|
||||
@Getter
|
||||
private final DocumentDBConfig config;
|
||||
private final CosmosDBConfig config;
|
||||
|
||||
private static final boolean IS_TELEMETRY_ALLOWED = PropertyLoader.isApplicationTelemetryAllowed();
|
||||
|
||||
|
@ -38,7 +39,7 @@ public class CosmosDbFactory {
|
|||
return suffix;
|
||||
}
|
||||
|
||||
public CosmosDbFactory(@NonNull DocumentDBConfig config) {
|
||||
public CosmosDbFactory(@NonNull CosmosDBConfig config) {
|
||||
validateConfig(config);
|
||||
|
||||
this.config = config;
|
||||
|
@ -46,17 +47,33 @@ public class CosmosDbFactory {
|
|||
|
||||
public CosmosClient getCosmosClient() {
|
||||
final ConnectionPolicy policy = config.getConnectionPolicy();
|
||||
final String userAgent = getUserAgentSuffix() + ";" + policy.getUserAgentSuffix();
|
||||
final String userAgent = getUserAgentSuffix() + ";" + policy.userAgentSuffix();
|
||||
|
||||
policy.setUserAgentSuffix(userAgent);
|
||||
policy.userAgentSuffix(userAgent);
|
||||
return CosmosClient.builder()
|
||||
.endpoint(config.getUri())
|
||||
.key(config.getKey())
|
||||
.cosmosKeyCredential(config.getCosmosKeyCredential())
|
||||
.connectionPolicy(policy)
|
||||
.consistencyLevel(config.getConsistencyLevel())
|
||||
.build();
|
||||
}
|
||||
|
||||
private void validateConfig(@NonNull DocumentDBConfig config) {
|
||||
public CosmosSyncClient getCosmosSyncClient() {
|
||||
final ConnectionPolicy policy = config.getConnectionPolicy();
|
||||
final String userAgent = getUserAgentSuffix() + ";" + policy.userAgentSuffix();
|
||||
|
||||
policy.userAgentSuffix(userAgent);
|
||||
return CosmosClient.builder()
|
||||
.endpoint(config.getUri())
|
||||
.key(config.getKey())
|
||||
.cosmosKeyCredential(config.getCosmosKeyCredential())
|
||||
.connectionPolicy(policy)
|
||||
.consistencyLevel(config.getConsistencyLevel())
|
||||
.buildSyncClient();
|
||||
}
|
||||
|
||||
private void validateConfig(@NonNull CosmosDBConfig config) {
|
||||
Assert.hasText(config.getUri(), "cosmosdb host url should have text!");
|
||||
if (config.getCosmosKeyCredential() == null) {
|
||||
Assert.hasText(config.getKey(), "cosmosdb host key should have text!");
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb;
|
||||
|
||||
import com.microsoft.azure.documentdb.ConnectionPolicy;
|
||||
import com.microsoft.azure.documentdb.DocumentClient;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.MacAddress;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.PropertyLoader;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.TelemetrySender;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
public class DocumentDbFactory {
|
||||
|
||||
@Getter
|
||||
private final DocumentDBConfig config;
|
||||
|
||||
private static final boolean IS_TELEMETRY_ALLOWED = PropertyLoader.isApplicationTelemetryAllowed();
|
||||
|
||||
private static final String USER_AGENT_SUFFIX = Constants.USER_AGENT_SUFFIX + PropertyLoader.getProjectVersion();
|
||||
|
||||
private String getUserAgentSuffix() {
|
||||
String suffix = ";" + USER_AGENT_SUFFIX;
|
||||
|
||||
if (IS_TELEMETRY_ALLOWED) {
|
||||
suffix += ";" + MacAddress.getHashMac();
|
||||
}
|
||||
|
||||
return suffix;
|
||||
}
|
||||
|
||||
public DocumentDbFactory(@NonNull DocumentDBConfig config) {
|
||||
validateConfig(config);
|
||||
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public DocumentClient getDocumentClient() {
|
||||
final ConnectionPolicy policy = config.getConnectionPolicy();
|
||||
final String userAgent = getUserAgentSuffix() + ";" + policy.getUserAgentSuffix();
|
||||
|
||||
policy.setUserAgentSuffix(userAgent);
|
||||
|
||||
// With introduction to com.azure.data.cosmos.CosmosKeyCredential,
|
||||
// we are giving preference to config.getCosmosKeyCredential()
|
||||
if (config.getCosmosKeyCredential() != null &&
|
||||
!StringUtils.isEmpty(config.getCosmosKeyCredential().key())) {
|
||||
return new DocumentClient(config.getUri(), config.getCosmosKeyCredential().key(),
|
||||
policy, config.getConsistencyLevel());
|
||||
}
|
||||
return new DocumentClient(config.getUri(), config.getKey(), policy, config.getConsistencyLevel());
|
||||
}
|
||||
|
||||
private void validateConfig(@NonNull DocumentDBConfig config) {
|
||||
Assert.hasText(config.getUri(), "cosmosdb host url should have text!");
|
||||
if (config.getCosmosKeyCredential() == null) {
|
||||
Assert.hasText(config.getKey(), "cosmosdb host key should have text!");
|
||||
} else if (StringUtils.isEmpty(config.getKey())) {
|
||||
Assert.hasText(config.getCosmosKeyCredential().key(),
|
||||
"cosmosdb credential host key should have text!");
|
||||
}
|
||||
Assert.hasText(config.getDatabase(), "cosmosdb database should have text!");
|
||||
Assert.notNull(config.getConnectionPolicy(), "cosmosdb connection policy should not be null!");
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
private void sendTelemetry() {
|
||||
if (IS_TELEMETRY_ALLOWED) {
|
||||
final TelemetrySender sender = new TelemetrySender();
|
||||
|
||||
sender.send(this.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,24 +6,30 @@
|
|||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.config;
|
||||
|
||||
import com.azure.data.cosmos.CosmosClient;
|
||||
import com.azure.data.cosmos.sync.CosmosSyncClient;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.microsoft.azure.documentdb.DocumentClient;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.Constants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.DocumentDbFactory;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbTemplate;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosTemplate;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosTemplate;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public abstract class AbstractDocumentDbConfiguration extends DocumentDbConfigurationSupport {
|
||||
public abstract class AbstractCosmosConfiguration extends CosmosConfigurationSupport {
|
||||
|
||||
@Bean
|
||||
public DocumentClient documentClient(DocumentDBConfig config) {
|
||||
return this.documentDbFactory(config).getDocumentClient();
|
||||
public CosmosClient cosmosClient(CosmosDBConfig config) {
|
||||
return this.cosmosDbFactory(config).getCosmosClient();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CosmosSyncClient cosmosSyncClient(CosmosDBConfig config) {
|
||||
return this.cosmosDbFactory(config).getCosmosSyncClient();
|
||||
}
|
||||
|
||||
@Qualifier(Constants.OBJECTMAPPER_BEAN_NAME)
|
||||
|
@ -31,29 +37,24 @@ public abstract class AbstractDocumentDbConfiguration extends DocumentDbConfigur
|
|||
private ObjectMapper objectMapper;
|
||||
|
||||
@Bean
|
||||
public DocumentDbFactory documentDbFactory(DocumentDBConfig config) {
|
||||
return new DocumentDbFactory(config);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CosmosDbFactory cosmosDbFactory(DocumentDBConfig config) {
|
||||
public CosmosDbFactory cosmosDbFactory(CosmosDBConfig config) {
|
||||
return new CosmosDbFactory(config);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DocumentDbTemplate documentDbTemplate(DocumentDBConfig config) throws ClassNotFoundException {
|
||||
return new DocumentDbTemplate(this.cosmosDbFactory(config), this.mappingDocumentDbConverter(),
|
||||
public CosmosTemplate cosmosTemplate(CosmosDBConfig config) throws ClassNotFoundException {
|
||||
return new CosmosTemplate(this.cosmosDbFactory(config), this.mappingCosmosConverter(),
|
||||
config.getDatabase());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ReactiveCosmosTemplate cosmosDbTemplate(DocumentDBConfig config) throws ClassNotFoundException {
|
||||
return new ReactiveCosmosTemplate(this.cosmosDbFactory(config), this.mappingDocumentDbConverter(),
|
||||
public ReactiveCosmosTemplate reactiveCosmosTemplate(CosmosDBConfig config) throws ClassNotFoundException {
|
||||
return new ReactiveCosmosTemplate(this.cosmosDbFactory(config), this.mappingCosmosConverter(),
|
||||
config.getDatabase());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MappingDocumentDbConverter mappingDocumentDbConverter() throws ClassNotFoundException {
|
||||
return new MappingDocumentDbConverter(this.documentDbMappingContext(), objectMapper);
|
||||
public MappingCosmosConverter mappingCosmosConverter() throws ClassNotFoundException {
|
||||
return new MappingCosmosConverter(this.cosmosMappingContext(), objectMapper);
|
||||
}
|
||||
}
|
|
@ -7,30 +7,23 @@
|
|||
package com.microsoft.azure.spring.data.cosmosdb.config;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.ExpressionResolver;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.context.MappingContextIsNewStrategyFactory;
|
||||
import org.springframework.data.mapping.context.PersistentEntities;
|
||||
import org.springframework.data.support.CachingIsNewStrategyFactory;
|
||||
import org.springframework.data.support.IsNewStrategyFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public abstract class DocumentDbConfigurationSupport {
|
||||
public abstract class CosmosConfigurationSupport {
|
||||
|
||||
@Bean
|
||||
public ExpressionResolver expressionResolver(BeanFactory beanFactory) {
|
||||
|
@ -38,8 +31,8 @@ public abstract class DocumentDbConfigurationSupport {
|
|||
}
|
||||
|
||||
@Bean
|
||||
public DocumentDbMappingContext documentDbMappingContext() throws ClassNotFoundException {
|
||||
final DocumentDbMappingContext mappingContext = new DocumentDbMappingContext();
|
||||
public CosmosMappingContext cosmosMappingContext() throws ClassNotFoundException {
|
||||
final CosmosMappingContext mappingContext = new CosmosMappingContext();
|
||||
mappingContext.setInitialEntitySet(getInitialEntitySet());
|
||||
|
||||
return mappingContext;
|
||||
|
@ -50,13 +43,6 @@ public abstract class DocumentDbConfigurationSupport {
|
|||
return Collections.singleton(mappingBasePackage == null ? null : mappingBasePackage.getName());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IsNewStrategyFactory isNewStrategyFactory() throws ClassNotFoundException {
|
||||
return new CachingIsNewStrategyFactory(new MappingContextIsNewStrategyFactory(
|
||||
new PersistentEntities(Arrays.<MappingContext<?, ?>>asList(
|
||||
new MappingContext[]{documentDbMappingContext()}))));
|
||||
}
|
||||
|
||||
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
|
||||
final Set<Class<?>> initialEntitySet = new HashSet<>();
|
||||
|
||||
|
@ -85,7 +71,7 @@ public abstract class DocumentDbConfigurationSupport {
|
|||
Assert.notNull(className, "Bean class name is null.");
|
||||
|
||||
initialEntitySet
|
||||
.add(ClassUtils.forName(className, DocumentDbConfigurationSupport.class.getClassLoader()));
|
||||
.add(ClassUtils.forName(className, CosmosConfigurationSupport.class.getClassLoader()));
|
||||
}
|
||||
}
|
||||
|
|
@ -5,18 +5,18 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.config;
|
||||
|
||||
import com.azure.data.cosmos.ConnectionPolicy;
|
||||
import com.azure.data.cosmos.ConsistencyLevel;
|
||||
import com.azure.data.cosmos.CosmosKeyCredential;
|
||||
import com.microsoft.azure.documentdb.ConnectionPolicy;
|
||||
import com.microsoft.azure.documentdb.ConsistencyLevel;
|
||||
import com.microsoft.azure.documentdb.RequestOptions;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.DocumentDBAccessException;
|
||||
import com.azure.data.cosmos.internal.RequestOptions;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@Getter
|
||||
@Builder(builderMethodName = "defaultBuilder")
|
||||
public class DocumentDBConfig {
|
||||
public class CosmosDBConfig {
|
||||
private String uri;
|
||||
|
||||
private String key;
|
||||
|
@ -33,35 +33,35 @@ public class DocumentDBConfig {
|
|||
|
||||
private CosmosKeyCredential cosmosKeyCredential;
|
||||
|
||||
public static DocumentDBConfigBuilder builder(String uri, CosmosKeyCredential cosmosKeyCredential,
|
||||
public static CosmosDBConfigBuilder builder(String uri, CosmosKeyCredential cosmosKeyCredential,
|
||||
String database) {
|
||||
return defaultBuilder()
|
||||
.uri(uri)
|
||||
.cosmosKeyCredential(cosmosKeyCredential)
|
||||
.database(database)
|
||||
.connectionPolicy(ConnectionPolicy.GetDefault())
|
||||
.consistencyLevel(ConsistencyLevel.Session)
|
||||
.connectionPolicy(ConnectionPolicy.defaultPolicy())
|
||||
.consistencyLevel(ConsistencyLevel.SESSION)
|
||||
.requestOptions(new RequestOptions());
|
||||
}
|
||||
|
||||
public static DocumentDBConfigBuilder builder(String uri, String key, String database) {
|
||||
public static CosmosDBConfigBuilder builder(String uri, String key, String database) {
|
||||
return defaultBuilder()
|
||||
.uri(uri)
|
||||
.key(key)
|
||||
.database(database)
|
||||
.connectionPolicy(ConnectionPolicy.GetDefault())
|
||||
.consistencyLevel(ConsistencyLevel.Session)
|
||||
.connectionPolicy(ConnectionPolicy.defaultPolicy())
|
||||
.consistencyLevel(ConsistencyLevel.SESSION)
|
||||
.requestOptions(new RequestOptions());
|
||||
}
|
||||
|
||||
public static DocumentDBConfigBuilder builder(String connectionString, String database) {
|
||||
public static CosmosDBConfigBuilder builder(String connectionString, String database) {
|
||||
Assert.hasText(connectionString, "connection string should have text!");
|
||||
try {
|
||||
final String uri = connectionString.split(";")[0].split("=")[1];
|
||||
final String key = connectionString.split(";")[1].split("=")[1];
|
||||
return builder(uri, key, database);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
throw new DocumentDBAccessException("could not parse connection string");
|
||||
throw new CosmosDBAccessException("could not parse connection string");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,22 +6,21 @@
|
|||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.core;
|
||||
|
||||
import com.microsoft.azure.documentdb.DocumentCollection;
|
||||
import com.microsoft.azure.documentdb.PartitionKey;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
|
||||
import com.azure.data.cosmos.CosmosContainerProperties;
|
||||
import com.azure.data.cosmos.PartitionKey;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface DocumentDbOperations {
|
||||
public interface CosmosOperations {
|
||||
|
||||
String getCollectionName(Class<?> entityClass);
|
||||
|
||||
DocumentCollection createCollectionIfNotExists(DocumentDbEntityInformation<?, ?> information);
|
||||
CosmosContainerProperties createCollectionIfNotExists(CosmosEntityInformation<?, ?> information);
|
||||
|
||||
<T> List<T> findAll(Class<T> entityClass);
|
||||
|
||||
|
@ -63,5 +62,5 @@ public interface DocumentDbOperations {
|
|||
|
||||
<T> long count(DocumentQuery query, Class<T> domainClass, String collectionName);
|
||||
|
||||
MappingDocumentDbConverter getConverter();
|
||||
MappingCosmosConverter getConverter();
|
||||
}
|
|
@ -9,26 +9,26 @@ package com.microsoft.azure.spring.data.cosmosdb.core;
|
|||
import com.azure.data.cosmos.AccessCondition;
|
||||
import com.azure.data.cosmos.AccessConditionType;
|
||||
import com.azure.data.cosmos.CosmosClient;
|
||||
import com.azure.data.cosmos.CosmosContainerProperties;
|
||||
import com.azure.data.cosmos.CosmosContainerResponse;
|
||||
import com.azure.data.cosmos.CosmosItemProperties;
|
||||
import com.azure.data.cosmos.CosmosItemRequestOptions;
|
||||
import com.azure.data.cosmos.CosmosItemResponse;
|
||||
import com.azure.data.cosmos.FeedOptions;
|
||||
import com.azure.data.cosmos.FeedResponse;
|
||||
import com.azure.data.cosmos.PartitionKey;
|
||||
import com.azure.data.cosmos.SqlQuerySpec;
|
||||
import com.microsoft.azure.documentdb.DocumentCollection;
|
||||
import com.microsoft.azure.documentdb.PartitionKey;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.Memoizer;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.generator.CountQueryGenerator;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.generator.FindQuerySpecGenerator;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.DocumentDBAccessException;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
@ -50,30 +50,25 @@ import java.util.List;
|
|||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Domenico Sibilio
|
||||
*
|
||||
*/
|
||||
@Slf4j
|
||||
public class DocumentDbTemplate implements DocumentDbOperations, ApplicationContextAware {
|
||||
public class CosmosTemplate implements CosmosOperations, ApplicationContextAware {
|
||||
|
||||
private static final String COUNT_VALUE_KEY = "_aggregate";
|
||||
|
||||
private final MappingDocumentDbConverter mappingDocumentDbConverter;
|
||||
private final MappingCosmosConverter mappingCosmosConverter;
|
||||
private final String databaseName;
|
||||
|
||||
private final CosmosClient cosmosClient;
|
||||
private Function<Class<?>, DocumentDbEntityInformation<?, ?>> entityInfoCreator =
|
||||
Memoizer.memoize(this::getDocumentDbEntityInformation);
|
||||
private Function<Class<?>, CosmosEntityInformation<?, ?>> entityInfoCreator =
|
||||
Memoizer.memoize(this::getCosmosEntityInformation);
|
||||
|
||||
public DocumentDbTemplate(CosmosDbFactory cosmosDbFactory,
|
||||
MappingDocumentDbConverter mappingDocumentDbConverter,
|
||||
String dbName) {
|
||||
public CosmosTemplate(CosmosDbFactory cosmosDbFactory,
|
||||
MappingCosmosConverter mappingCosmosConverter,
|
||||
String dbName) {
|
||||
Assert.notNull(cosmosDbFactory, "CosmosDbFactory must not be null!");
|
||||
Assert.notNull(mappingDocumentDbConverter, "MappingDocumentDbConverter must not be null!");
|
||||
Assert.notNull(mappingCosmosConverter, "MappingCosmosConverter must not be null!");
|
||||
|
||||
this.mappingDocumentDbConverter = mappingDocumentDbConverter;
|
||||
this.mappingCosmosConverter = mappingCosmosConverter;
|
||||
|
||||
this.databaseName = dbName;
|
||||
this.cosmosClient = cosmosDbFactory.getCosmosClient();
|
||||
|
@ -92,13 +87,13 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
Assert.hasText(collectionName, "collectionName should not be null, empty or only whitespaces");
|
||||
Assert.notNull(objectToSave, "objectToSave should not be null");
|
||||
|
||||
final CosmosItemProperties originalItem = mappingDocumentDbConverter.writeCosmosItemProperties(objectToSave);
|
||||
final CosmosItemProperties originalItem = mappingCosmosConverter.writeCosmosItemProperties(objectToSave);
|
||||
|
||||
log.debug("execute createDocument in database {} collection {}", this.databaseName, collectionName);
|
||||
|
||||
try {
|
||||
final CosmosItemRequestOptions options = new CosmosItemRequestOptions();
|
||||
options.partitionKey(toCosmosPartitionKey(partitionKey));
|
||||
options.partitionKey(partitionKey);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
final Class<T> domainClass = (Class<T>) objectToSave.getClass();
|
||||
|
@ -110,13 +105,13 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
.block();
|
||||
|
||||
if (response == null) {
|
||||
throw new DocumentDBAccessException("Failed to insert item");
|
||||
throw new CosmosDBAccessException("Failed to insert item");
|
||||
}
|
||||
|
||||
return mappingDocumentDbConverter.read(domainClass, response.properties());
|
||||
return mappingCosmosConverter.read(domainClass, response.properties());
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new DocumentDBAccessException("insert exception", e);
|
||||
throw new CosmosDBAccessException("insert exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,6 +121,29 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
return findById(getCollectionName(entityClass), id, entityClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T findById(Object id, Class<T> entityClass, PartitionKey partitionKey) {
|
||||
Assert.notNull(entityClass, "entityClass should not be null");
|
||||
Assert.notNull(partitionKey, "partitionKey should not be null");
|
||||
assertValidId(id);
|
||||
|
||||
try {
|
||||
final String collectionName = getCollectionName(entityClass);
|
||||
return cosmosClient
|
||||
.getDatabase(databaseName)
|
||||
.getContainer(collectionName)
|
||||
.getItem(id.toString(), partitionKey)
|
||||
.read()
|
||||
.flatMap(cosmosItemResponse -> Mono.justOrEmpty(toDomainObject(entityClass,
|
||||
cosmosItemResponse.properties())))
|
||||
.onErrorResume(Mono::error)
|
||||
.block();
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new CosmosDBAccessException("findById exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T findById(String collectionName, Object id, Class<T> domainClass) {
|
||||
Assert.hasText(collectionName, "collectionName should not be null, empty or only whitespaces");
|
||||
Assert.notNull(domainClass, "entityClass should not be null");
|
||||
|
@ -143,42 +161,16 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
.flatMap(cosmosItemFeedResponse -> Mono.justOrEmpty(cosmosItemFeedResponse
|
||||
.results()
|
||||
.stream()
|
||||
.map(cosmosItem -> mappingDocumentDbConverter.read(domainClass, cosmosItem))
|
||||
.map(cosmosItem -> mappingCosmosConverter.read(domainClass, cosmosItem))
|
||||
.findFirst()))
|
||||
.onErrorResume(Mono::error)
|
||||
.blockFirst();
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new DocumentDBAccessException("findById exception", e);
|
||||
throw new CosmosDBAccessException("findById exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T findById(Object id, Class<T> entityClass, PartitionKey partitionKey) {
|
||||
Assert.notNull(entityClass, "entityClass should not be null");
|
||||
Assert.notNull(partitionKey, "partitionKey should not be null");
|
||||
assertValidId(id);
|
||||
|
||||
final com.azure.data.cosmos.PartitionKey pk = toCosmosPartitionKey(partitionKey);
|
||||
|
||||
try {
|
||||
final String collectionName = getCollectionName(entityClass);
|
||||
return cosmosClient
|
||||
.getDatabase(databaseName)
|
||||
.getContainer(collectionName)
|
||||
.getItem(id.toString(), pk)
|
||||
.read()
|
||||
.flatMap(cosmosItemResponse -> Mono.justOrEmpty(toDomainObject(entityClass,
|
||||
cosmosItemResponse.properties())))
|
||||
.onErrorResume(Mono::error)
|
||||
.block();
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new DocumentDBAccessException("findById exception", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public <T> void upsert(T object, PartitionKey partitionKey) {
|
||||
Assert.notNull(object, "Upsert object should not be null");
|
||||
|
||||
|
@ -190,12 +182,12 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
Assert.notNull(object, "Upsert object should not be null");
|
||||
|
||||
try {
|
||||
final CosmosItemProperties originalItem = mappingDocumentDbConverter.writeCosmosItemProperties(object);
|
||||
final CosmosItemProperties originalItem = mappingCosmosConverter.writeCosmosItemProperties(object);
|
||||
|
||||
log.debug("execute upsert document in database {} collection {}", this.databaseName, collectionName);
|
||||
|
||||
final CosmosItemRequestOptions options = new CosmosItemRequestOptions();
|
||||
options.partitionKey(toCosmosPartitionKey(partitionKey));
|
||||
options.partitionKey(partitionKey);
|
||||
applyVersioning(object.getClass(), originalItem, options);
|
||||
|
||||
final CosmosItemResponse cosmosItemResponse = cosmosClient.getDatabase(this.databaseName)
|
||||
|
@ -205,10 +197,10 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
.block();
|
||||
|
||||
if (cosmosItemResponse == null) {
|
||||
throw new DocumentDBAccessException("Failed to upsert item");
|
||||
throw new CosmosDBAccessException("Failed to upsert item");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new DocumentDBAccessException("Failed to upsert document to database.", ex);
|
||||
throw new CosmosDBAccessException("Failed to upsert document to database.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,7 +236,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
try {
|
||||
cosmosClient.getDatabase(this.databaseName).getContainer(collectionName).delete().block();
|
||||
} catch (Exception e) {
|
||||
throw new DocumentDBAccessException("failed to delete collection: " + collectionName,
|
||||
throw new CosmosDBAccessException("failed to delete collection: " + collectionName,
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
@ -256,7 +248,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
}
|
||||
|
||||
@Override
|
||||
public DocumentCollection createCollectionIfNotExists(@NonNull DocumentDbEntityInformation<?, ?> information) {
|
||||
public CosmosContainerProperties createCollectionIfNotExists(@NonNull CosmosEntityInformation<?, ?> information) {
|
||||
final CosmosContainerResponse response = cosmosClient
|
||||
.createDatabaseIfNotExists(this.databaseName)
|
||||
.flatMap(cosmosDatabaseResponse -> cosmosDatabaseResponse
|
||||
|
@ -266,9 +258,9 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
.map(cosmosContainerResponse -> cosmosContainerResponse))
|
||||
.block();
|
||||
if (response == null) {
|
||||
throw new DocumentDBAccessException("Failed to create collection");
|
||||
throw new CosmosDBAccessException("Failed to create collection");
|
||||
}
|
||||
return new DocumentCollection(response.properties().toJson());
|
||||
return response.properties();
|
||||
}
|
||||
|
||||
public void deleteById(String collectionName, Object id, PartitionKey partitionKey) {
|
||||
|
@ -277,13 +269,12 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
|
||||
log.debug("execute deleteById in database {} collection {}", this.databaseName, collectionName);
|
||||
|
||||
com.azure.data.cosmos.PartitionKey pk = toCosmosPartitionKey(partitionKey);
|
||||
if (pk == null) {
|
||||
pk = com.azure.data.cosmos.PartitionKey.None;
|
||||
if (partitionKey == null) {
|
||||
partitionKey = PartitionKey.None;
|
||||
}
|
||||
try {
|
||||
final CosmosItemRequestOptions options = new CosmosItemRequestOptions();
|
||||
options.partitionKey(pk);
|
||||
options.partitionKey(partitionKey);
|
||||
cosmosClient.getDatabase(this.databaseName)
|
||||
.getContainer(collectionName)
|
||||
.getItem(id.toString(), partitionKey)
|
||||
|
@ -292,7 +283,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
.then()
|
||||
.block();
|
||||
} catch (Exception e) {
|
||||
throw new DocumentDBAccessException("deleteById exception", e);
|
||||
throw new CosmosDBAccessException("deleteById exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,7 +309,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
.map(cosmosItemProperties -> toDomainObject(domainClass, cosmosItemProperties))
|
||||
.collect(Collectors.toList());
|
||||
} catch (Exception e) {
|
||||
throw new DocumentDBAccessException("Failed to execute find operation from " + collectionName, e);
|
||||
throw new CosmosDBAccessException("Failed to execute find operation from " + collectionName, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -371,8 +362,8 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
|
||||
final Pageable pageable = query.getPageable();
|
||||
final FeedOptions feedOptions = new FeedOptions();
|
||||
if (pageable instanceof DocumentDbPageRequest) {
|
||||
feedOptions.requestContinuation(((DocumentDbPageRequest) pageable).getRequestContinuation());
|
||||
if (pageable instanceof CosmosPageRequest) {
|
||||
feedOptions.requestContinuation(((CosmosPageRequest) pageable).getRequestContinuation());
|
||||
}
|
||||
|
||||
feedOptions.maxItemCount(pageable.getPageSize());
|
||||
|
@ -387,7 +378,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
.block();
|
||||
|
||||
if (feedResponse == null) {
|
||||
throw new DocumentDBAccessException("Failed to query documents");
|
||||
throw new CosmosDBAccessException("Failed to query documents");
|
||||
}
|
||||
|
||||
final Iterator<CosmosItemProperties> it = feedResponse.results().iterator();
|
||||
|
@ -400,11 +391,11 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
continue;
|
||||
}
|
||||
|
||||
final T entity = mappingDocumentDbConverter.read(domainClass, cosmosItemProperties);
|
||||
final T entity = mappingCosmosConverter.read(domainClass, cosmosItemProperties);
|
||||
result.add(entity);
|
||||
}
|
||||
|
||||
final DocumentDbPageRequest pageRequest = DocumentDbPageRequest.of(pageable.getPageNumber(),
|
||||
final CosmosPageRequest pageRequest = CosmosPageRequest.of(pageable.getPageNumber(),
|
||||
pageable.getPageSize(),
|
||||
feedResponse.continuationToken(),
|
||||
query.getSort());
|
||||
|
@ -419,7 +410,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
final DocumentQuery query = new DocumentQuery(Criteria.getInstance(CriteriaType.ALL));
|
||||
final Long count = getCountValue(query, true, collectionName);
|
||||
if (count == null) {
|
||||
throw new DocumentDBAccessException("Failed to get count for collectionName: " + collectionName);
|
||||
throw new CosmosDBAccessException("Failed to get count for collectionName: " + collectionName);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -433,14 +424,14 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
query.isCrossPartitionQuery(getPartitionKeyNames(domainClass));
|
||||
final Long count = getCountValue(query, isCrossPartitionQuery, collectionName);
|
||||
if (count == null) {
|
||||
throw new DocumentDBAccessException("Failed to get count for collectionName: " + collectionName);
|
||||
throw new CosmosDBAccessException("Failed to get count for collectionName: " + collectionName);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingDocumentDbConverter getConverter() {
|
||||
return this.mappingDocumentDbConverter;
|
||||
public MappingCosmosConverter getConverter() {
|
||||
return this.mappingCosmosConverter;
|
||||
}
|
||||
|
||||
private Long getCountValue(DocumentQuery query, boolean isCrossPartitionQuery, String containerName) {
|
||||
|
@ -457,7 +448,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
}
|
||||
|
||||
private <T> Mono<T> databaseAccessExceptionHandler(Throwable e) {
|
||||
throw new DocumentDBAccessException("failed to access cosmosdb database", e);
|
||||
throw new CosmosDBAccessException("failed to access cosmosdb database", e);
|
||||
}
|
||||
|
||||
private Flux<FeedResponse<CosmosItemProperties>> executeQuery(SqlQuerySpec sqlQuerySpec, String collectionName,
|
||||
|
@ -468,7 +459,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
}
|
||||
|
||||
private List<String> getPartitionKeyNames(Class<?> domainClass) {
|
||||
final DocumentDbEntityInformation<?, ?> entityInfo = entityInfoCreator.apply(domainClass);
|
||||
final CosmosEntityInformation<?, ?> entityInfo = entityInfoCreator.apply(domainClass);
|
||||
|
||||
if (entityInfo.getPartitionKeyFieldName() == null) {
|
||||
return new ArrayList<>();
|
||||
|
@ -477,13 +468,6 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
return Collections.singletonList(entityInfo.getPartitionKeyFieldName());
|
||||
}
|
||||
|
||||
private com.azure.data.cosmos.PartitionKey toCosmosPartitionKey(PartitionKey partitionKey) {
|
||||
if (partitionKey == null) {
|
||||
return null;
|
||||
}
|
||||
return com.azure.data.cosmos.PartitionKey.fromJsonString(partitionKey.getInternalPartitionKey().toJson());
|
||||
}
|
||||
|
||||
private void assertValidId(Object id) {
|
||||
Assert.notNull(id, "id should not be null");
|
||||
if (id instanceof String) {
|
||||
|
@ -520,13 +504,11 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
partitionKey = new PartitionKey(cosmosItemProperties.get(partitionKeyNames.get(0)));
|
||||
}
|
||||
|
||||
com.azure.data.cosmos.PartitionKey pk = toCosmosPartitionKey(partitionKey);
|
||||
|
||||
if (pk == null) {
|
||||
pk = com.azure.data.cosmos.PartitionKey.None;
|
||||
if (partitionKey == null) {
|
||||
partitionKey = PartitionKey.None;
|
||||
}
|
||||
|
||||
final CosmosItemRequestOptions options = new CosmosItemRequestOptions(pk);
|
||||
final CosmosItemRequestOptions options = new CosmosItemRequestOptions(partitionKey);
|
||||
applyVersioning(domainClass, cosmosItemProperties, options);
|
||||
|
||||
return cosmosClient
|
||||
|
@ -538,7 +520,7 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
}
|
||||
|
||||
private <T> T toDomainObject(@NonNull Class<T> domainClass, CosmosItemProperties cosmosItemProperties) {
|
||||
return mappingDocumentDbConverter.read(domainClass, cosmosItemProperties);
|
||||
return mappingCosmosConverter.read(domainClass, cosmosItemProperties);
|
||||
}
|
||||
|
||||
private void applyVersioning(Class<?> domainClass,
|
||||
|
@ -553,8 +535,8 @@ public class DocumentDbTemplate implements DocumentDbOperations, ApplicationCont
|
|||
}
|
||||
}
|
||||
|
||||
private DocumentDbEntityInformation<?, ?> getDocumentDbEntityInformation(Class<?> domainClass) {
|
||||
return new DocumentDbEntityInformation<>(domainClass);
|
||||
private CosmosEntityInformation<?, ?> getCosmosEntityInformation(Class<?> domainClass) {
|
||||
return new CosmosEntityInformation<>(domainClass);
|
||||
}
|
||||
|
||||
}
|
|
@ -8,15 +8,17 @@ package com.microsoft.azure.spring.data.cosmosdb.core;
|
|||
|
||||
import com.azure.data.cosmos.CosmosContainerResponse;
|
||||
import com.azure.data.cosmos.PartitionKey;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public interface ReactiveCosmosOperations {
|
||||
|
||||
Mono<CosmosContainerResponse> createCollectionIfNotExists(DocumentDbEntityInformation information);
|
||||
String getContainerName(Class<?> domainClass);
|
||||
|
||||
Mono<CosmosContainerResponse> createCollectionIfNotExists(CosmosEntityInformation information);
|
||||
|
||||
<T> Flux<T> findAll(String collectionName, Class<T> entityClass);
|
||||
|
||||
|
@ -42,7 +44,7 @@ public interface ReactiveCosmosOperations {
|
|||
|
||||
void deleteContainer(String collectionName);
|
||||
|
||||
<T> Mono<T> delete(DocumentQuery query, Class<T> entityClass, String collectionName);
|
||||
<T> Flux<T> delete(DocumentQuery query, Class<T> entityClass, String collectionName);
|
||||
|
||||
<T> Flux<T> find(DocumentQuery query, Class<T> entityClass, String collectionName);
|
||||
|
||||
|
@ -54,5 +56,5 @@ public interface ReactiveCosmosOperations {
|
|||
|
||||
Mono<Long> count(DocumentQuery query, String containerName);
|
||||
|
||||
MappingDocumentDbConverter getConverter();
|
||||
MappingCosmosConverter getConverter();
|
||||
}
|
||||
|
|
|
@ -15,14 +15,14 @@ import com.azure.data.cosmos.FeedResponse;
|
|||
import com.azure.data.cosmos.PartitionKey;
|
||||
import com.azure.data.cosmos.SqlQuerySpec;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.generator.CountQueryGenerator;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.generator.FindQuerySpecGenerator;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.DocumentDBAccessException;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
@ -41,10 +41,9 @@ import java.util.List;
|
|||
public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, ApplicationContextAware {
|
||||
private static final String COUNT_VALUE_KEY = "_aggregate";
|
||||
|
||||
private final MappingCosmosConverter mappingCosmosConverter;
|
||||
private final String databaseName;
|
||||
|
||||
private final MappingDocumentDbConverter mappingDocumentDbConverter;
|
||||
|
||||
private final CosmosClient cosmosClient;
|
||||
|
||||
private final List<String> collectionCache;
|
||||
|
@ -53,18 +52,18 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
* Constructor
|
||||
*
|
||||
* @param cosmosDbFactory the cosmosdbfactory
|
||||
* @param mappingDocumentDbConverter the mappingDocumentDbConverter
|
||||
* @param mappingCosmosConverter the mappingCosmosConverter
|
||||
* @param dbName database name
|
||||
*/
|
||||
public ReactiveCosmosTemplate(CosmosDbFactory cosmosDbFactory,
|
||||
MappingDocumentDbConverter mappingDocumentDbConverter,
|
||||
MappingCosmosConverter mappingCosmosConverter,
|
||||
String dbName) {
|
||||
Assert.notNull(cosmosDbFactory, "CosmosDbFactory must not be null!");
|
||||
Assert.notNull(mappingDocumentDbConverter, "MappingDocumentDbConverter must not be null!");
|
||||
Assert.notNull(mappingCosmosConverter, "MappingCosmosConverter must not be null!");
|
||||
|
||||
this.mappingCosmosConverter = mappingCosmosConverter;
|
||||
this.databaseName = dbName;
|
||||
this.collectionCache = new ArrayList<>();
|
||||
this.mappingDocumentDbConverter = mappingDocumentDbConverter;
|
||||
|
||||
this.cosmosClient = cosmosDbFactory.getCosmosClient();
|
||||
}
|
||||
|
@ -77,19 +76,14 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
// NOTE: When application context instance variable gets introduced, assign it here.
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingDocumentDbConverter getConverter() {
|
||||
return this.mappingDocumentDbConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a collection if it doesn't already exist
|
||||
*
|
||||
* @param information the DocumentDbEntityInformation
|
||||
* @param information the CosmosEntityInformation
|
||||
* @return Mono containing CosmosContainerResponse
|
||||
*/
|
||||
@Override
|
||||
public Mono<CosmosContainerResponse> createCollectionIfNotExists(DocumentDbEntityInformation information) {
|
||||
public Mono<CosmosContainerResponse> createCollectionIfNotExists(CosmosEntityInformation information) {
|
||||
|
||||
return cosmosClient
|
||||
.createDatabaseIfNotExists(this.databaseName)
|
||||
|
@ -167,7 +161,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
.stream()
|
||||
.map(cosmosItem -> toDomainObject(entityClass, cosmosItem))
|
||||
.findFirst()))
|
||||
.onErrorResume(Mono::error)
|
||||
.onErrorResume(this::databaseAccessExceptionHandler)
|
||||
.next();
|
||||
}
|
||||
|
||||
|
@ -191,10 +185,9 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
.read()
|
||||
.flatMap(cosmosItemResponse -> Mono.justOrEmpty(toDomainObject(entityClass,
|
||||
cosmosItemResponse.properties())))
|
||||
.onErrorResume(Mono::error);
|
||||
.onErrorResume(this::databaseAccessExceptionHandler);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Insert
|
||||
*
|
||||
|
@ -221,7 +214,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
return cosmosClient.getDatabase(this.databaseName)
|
||||
.getContainer(getContainerName(objectToSave.getClass()))
|
||||
.createItem(objectToSave, new CosmosItemRequestOptions())
|
||||
.onErrorResume(Mono::error)
|
||||
.onErrorResume(this::databaseAccessExceptionHandler)
|
||||
.flatMap(cosmosItemResponse -> Mono.just(toDomainObject(domainClass, cosmosItemResponse.properties())));
|
||||
}
|
||||
|
||||
|
@ -246,7 +239,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
return cosmosClient.getDatabase(this.databaseName)
|
||||
.getContainer(containerName)
|
||||
.createItem(objectToSave, options)
|
||||
.onErrorResume(Mono::error)
|
||||
.onErrorResume(this::databaseAccessExceptionHandler)
|
||||
.flatMap(cosmosItemResponse -> Mono.just(toDomainObject(domainClass, cosmosItemResponse.properties())));
|
||||
}
|
||||
|
||||
|
@ -282,7 +275,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
.getContainer(containerName)
|
||||
.upsertItem(object, options)
|
||||
.flatMap(cosmosItemResponse -> Mono.just(toDomainObject(domainClass, cosmosItemResponse.properties())))
|
||||
.onErrorResume(Mono::error);
|
||||
.onErrorResume(this::databaseAccessExceptionHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -302,11 +295,11 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
final CosmosItemRequestOptions options = new CosmosItemRequestOptions();
|
||||
options.partitionKey(partitionKey);
|
||||
return cosmosClient.getDatabase(this.databaseName)
|
||||
.getContainer(containerName)
|
||||
.getItem(id.toString(), partitionKey)
|
||||
.delete(options)
|
||||
.onErrorResume(Mono::error)
|
||||
.then();
|
||||
.getContainer(containerName)
|
||||
.getItem(id.toString(), partitionKey)
|
||||
.delete(options)
|
||||
.onErrorResume(this::databaseAccessExceptionHandler)
|
||||
.then();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -328,16 +321,16 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
final boolean isCrossPartitionQuery = query.isCrossPartitionQuery(Collections.singletonList(partitionKeyName));
|
||||
options.enableCrossPartitionQuery(isCrossPartitionQuery);
|
||||
return cosmosClient.getDatabase(this.databaseName)
|
||||
.getContainer(containerName)
|
||||
.queryItems(sqlQuerySpec, options)
|
||||
.flatMap(cosmosItemFeedResponse -> Flux.fromIterable(cosmosItemFeedResponse.results()))
|
||||
.flatMap(cosmosItemProperties -> cosmosClient
|
||||
.getDatabase(this.databaseName)
|
||||
.getContainer(containerName)
|
||||
.getItem(cosmosItemProperties.id(), cosmosItemProperties.get(partitionKeyName))
|
||||
.delete())
|
||||
.onErrorResume(this::databaseAccessExceptionHandler)
|
||||
.then();
|
||||
.getContainer(containerName)
|
||||
.queryItems(sqlQuerySpec, options)
|
||||
.flatMap(cosmosItemFeedResponse -> Flux.fromIterable(cosmosItemFeedResponse.results()))
|
||||
.flatMap(cosmosItemProperties -> cosmosClient
|
||||
.getDatabase(this.databaseName)
|
||||
.getContainer(containerName)
|
||||
.getItem(cosmosItemProperties.id(), cosmosItemProperties.get(partitionKeyName))
|
||||
.delete())
|
||||
.onErrorResume(this::databaseAccessExceptionHandler)
|
||||
.then();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -349,7 +342,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
* @return Mono
|
||||
*/
|
||||
@Override
|
||||
public <T> Mono<T> delete(DocumentQuery query, Class<T> entityClass, String containerName) {
|
||||
public <T> Flux<T> delete(DocumentQuery query, Class<T> entityClass, String containerName) {
|
||||
Assert.notNull(query, "DocumentQuery should not be null.");
|
||||
Assert.notNull(entityClass, "domainClass should not be null.");
|
||||
Assert.hasText(containerName, "container name should not be null, empty or only whitespaces");
|
||||
|
@ -357,9 +350,8 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
final Flux<CosmosItemProperties> results = findDocuments(query, entityClass, containerName);
|
||||
final List<String> partitionKeyName = getPartitionKeyNames(entityClass);
|
||||
|
||||
results.flatMap(d -> deleteDocument(d, partitionKeyName, containerName));
|
||||
|
||||
return null;
|
||||
return results.flatMap(d -> deleteDocument(d, partitionKeyName, containerName))
|
||||
.flatMap(cosmosItemProperties -> Mono.just(toDomainObject(entityClass, cosmosItemProperties)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -425,6 +417,11 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
return count(query, true, containerName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingCosmosConverter getConverter() {
|
||||
return mappingCosmosConverter;
|
||||
}
|
||||
|
||||
public Mono<Long> count(DocumentQuery query, boolean isCrossPartitionQuery, String containerName) {
|
||||
return getCountValue(query, isCrossPartitionQuery, containerName);
|
||||
}
|
||||
|
@ -450,7 +447,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
}
|
||||
|
||||
private <T> Mono<T> databaseAccessExceptionHandler(Throwable e) {
|
||||
throw new DocumentDBAccessException("failed to access cosmosdb database", e);
|
||||
throw new CosmosDBAccessException("failed to access cosmosdb database", e);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -465,7 +462,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
cosmosClient.getDatabase(this.databaseName).getContainer(containerName).delete().block();
|
||||
this.collectionCache.remove(containerName);
|
||||
} catch (Exception e) {
|
||||
throw new DocumentDBAccessException("failed to delete collection: " + containerName, e);
|
||||
throw new CosmosDBAccessException("failed to delete collection: " + containerName, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -476,7 +473,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
public String getContainerName(Class<?> domainClass) {
|
||||
Assert.notNull(domainClass, "domainClass should not be null");
|
||||
|
||||
return new DocumentDbEntityInformation<>(domainClass).getCollectionName();
|
||||
return new CosmosEntityInformation<>(domainClass).getCollectionName();
|
||||
}
|
||||
|
||||
private Flux<CosmosItemProperties> findDocuments(@NonNull DocumentQuery query, @NonNull Class<?> domainClass,
|
||||
|
@ -500,7 +497,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
}
|
||||
|
||||
private List<String> getPartitionKeyNames(Class<?> domainClass) {
|
||||
final DocumentDbEntityInformation entityInfo = new DocumentDbEntityInformation(domainClass);
|
||||
final CosmosEntityInformation<?, ?> entityInfo = new CosmosEntityInformation<>(domainClass);
|
||||
|
||||
if (entityInfo.getPartitionKeyFieldName() == null) {
|
||||
return new ArrayList<>();
|
||||
|
@ -531,8 +528,7 @@ public class ReactiveCosmosTemplate implements ReactiveCosmosOperations, Applica
|
|||
}
|
||||
|
||||
private <T> T toDomainObject(@NonNull Class<T> domainClass, CosmosItemProperties cosmosItemProperties) {
|
||||
return this.mappingDocumentDbConverter.read(domainClass, cosmosItemProperties);
|
||||
return mappingCosmosConverter.read(domainClass, cosmosItemProperties);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -7,14 +7,11 @@ package com.microsoft.azure.spring.data.cosmosdb.core.convert;
|
|||
|
||||
import com.azure.data.cosmos.CosmosItemProperties;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||
import com.microsoft.azure.documentdb.Document;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.Constants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbPersistentEntity;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbPersistentProperty;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.DocumentDBAccessException;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentEntity;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
@ -35,19 +32,19 @@ import java.util.Date;
|
|||
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.Constants.ISO_8601_COMPATIBLE_DATE_PATTERN;
|
||||
|
||||
public class MappingDocumentDbConverter
|
||||
implements EntityConverter<DocumentDbPersistentEntity<?>, DocumentDbPersistentProperty,
|
||||
public class MappingCosmosConverter
|
||||
implements EntityConverter<CosmosPersistentEntity<?>, CosmosPersistentProperty,
|
||||
Object, CosmosItemProperties>,
|
||||
ApplicationContextAware {
|
||||
|
||||
protected final MappingContext<? extends DocumentDbPersistentEntity<?>,
|
||||
DocumentDbPersistentProperty> mappingContext;
|
||||
protected final MappingContext<? extends CosmosPersistentEntity<?>,
|
||||
CosmosPersistentProperty> mappingContext;
|
||||
protected GenericConversionService conversionService;
|
||||
private ApplicationContext applicationContext;
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
public MappingDocumentDbConverter(
|
||||
MappingContext<? extends DocumentDbPersistentEntity<?>, DocumentDbPersistentProperty> mappingContext,
|
||||
public MappingCosmosConverter(
|
||||
MappingContext<? extends CosmosPersistentEntity<?>, CosmosPersistentProperty> mappingContext,
|
||||
@Qualifier(Constants.OBJECTMAPPER_BEAN_NAME) ObjectMapper objectMapper) {
|
||||
this.mappingContext = mappingContext;
|
||||
this.conversionService = new GenericConversionService();
|
||||
|
@ -61,18 +58,17 @@ public class MappingDocumentDbConverter
|
|||
return null;
|
||||
}
|
||||
|
||||
final DocumentDbPersistentEntity<?> entity = mappingContext.getPersistentEntity(type);
|
||||
final CosmosPersistentEntity<?> entity = mappingContext.getPersistentEntity(type);
|
||||
Assert.notNull(entity, "Entity is null.");
|
||||
|
||||
return readInternal(entity, type, cosmosItemProperties);
|
||||
}
|
||||
|
||||
|
||||
private <R> R readInternal(final DocumentDbPersistentEntity<?> entity, Class<R> type,
|
||||
private <R> R readInternal(final CosmosPersistentEntity<?> entity, Class<R> type,
|
||||
final CosmosItemProperties cosmosItemProperties) {
|
||||
|
||||
try {
|
||||
final DocumentDbPersistentProperty idProperty = entity.getIdProperty();
|
||||
final CosmosPersistentProperty idProperty = entity.getIdProperty();
|
||||
final Object idValue = cosmosItemProperties.id();
|
||||
final JSONObject jsonObject = new JSONObject(cosmosItemProperties.toJson());
|
||||
|
||||
|
@ -95,12 +91,12 @@ public class MappingDocumentDbConverter
|
|||
throw new UnsupportedOperationException("The feature is not implemented yet");
|
||||
}
|
||||
|
||||
public Document writeDoc(Object sourceEntity) {
|
||||
public CosmosItemProperties writeDoc(Object sourceEntity) {
|
||||
if (sourceEntity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final DocumentDbPersistentEntity<?> persistentEntity =
|
||||
final CosmosPersistentEntity<?> persistentEntity =
|
||||
mappingContext.getPersistentEntity(sourceEntity.getClass());
|
||||
|
||||
if (persistentEntity == null) {
|
||||
|
@ -108,19 +104,19 @@ public class MappingDocumentDbConverter
|
|||
}
|
||||
|
||||
final ConvertingPropertyAccessor accessor = getPropertyAccessor(sourceEntity);
|
||||
final DocumentDbPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||
final Document document;
|
||||
final CosmosPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||
final CosmosItemProperties document;
|
||||
|
||||
try {
|
||||
document = new Document(objectMapper.writeValueAsString(sourceEntity));
|
||||
document = new CosmosItemProperties(objectMapper.writeValueAsString(sourceEntity));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new DocumentDBAccessException("Failed to map document value.", e);
|
||||
throw new CosmosDBAccessException("Failed to map document value.", e);
|
||||
}
|
||||
|
||||
if (idProperty != null) {
|
||||
final Object value = accessor.getProperty(idProperty);
|
||||
final String id = value == null ? null : value.toString();
|
||||
document.setId(id);
|
||||
document.id(id);
|
||||
}
|
||||
|
||||
return document;
|
||||
|
@ -131,7 +127,7 @@ public class MappingDocumentDbConverter
|
|||
return null;
|
||||
}
|
||||
|
||||
final DocumentDbPersistentEntity<?> persistentEntity =
|
||||
final CosmosPersistentEntity<?> persistentEntity =
|
||||
mappingContext.getPersistentEntity(sourceEntity.getClass());
|
||||
|
||||
if (persistentEntity == null) {
|
||||
|
@ -139,14 +135,14 @@ public class MappingDocumentDbConverter
|
|||
}
|
||||
|
||||
final ConvertingPropertyAccessor accessor = getPropertyAccessor(sourceEntity);
|
||||
final DocumentDbPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||
final CosmosPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||
final CosmosItemProperties cosmosItemProperties;
|
||||
|
||||
try {
|
||||
cosmosItemProperties =
|
||||
new CosmosItemProperties(objectMapper.writeValueAsString(sourceEntity));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new DocumentDBAccessException("Failed to map document value.", e);
|
||||
throw new CosmosDBAccessException("Failed to map document value.", e);
|
||||
}
|
||||
|
||||
if (idProperty != null) {
|
||||
|
@ -172,13 +168,13 @@ public class MappingDocumentDbConverter
|
|||
return conversionService;
|
||||
}
|
||||
|
||||
public MappingContext<? extends DocumentDbPersistentEntity<?>, DocumentDbPersistentProperty> getMappingContext() {
|
||||
public MappingContext<? extends CosmosPersistentEntity<?>, CosmosPersistentProperty> getMappingContext() {
|
||||
return mappingContext;
|
||||
}
|
||||
|
||||
|
||||
private ConvertingPropertyAccessor getPropertyAccessor(Object entity) {
|
||||
final DocumentDbPersistentEntity<?> entityInformation =
|
||||
final CosmosPersistentEntity<?> entityInformation =
|
||||
mappingContext.getPersistentEntity(entity.getClass());
|
||||
|
||||
Assert.notNull(entityInformation, "EntityInformation should not be null.");
|
||||
|
@ -192,17 +188,19 @@ public class MappingDocumentDbConverter
|
|||
* @param fromPropertyValue
|
||||
* @return
|
||||
*/
|
||||
public static Object toDocumentDBValue(Object fromPropertyValue) {
|
||||
public static Object toCosmosDbValue(Object fromPropertyValue) {
|
||||
if (fromPropertyValue == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// com.microsoft.azure.documentdb.JsonSerializable#set(String, T) cannot set values for Date and Enum correctly
|
||||
// com.microsoft.azure.data.cosmos.JsonSerializable#set(String, T) cannot set values for Date and Enum correctly
|
||||
|
||||
if (fromPropertyValue instanceof Date) {
|
||||
fromPropertyValue = ((Date) fromPropertyValue).getTime();
|
||||
} else if (fromPropertyValue instanceof ZonedDateTime) {
|
||||
} else
|
||||
if (fromPropertyValue instanceof ZonedDateTime) {
|
||||
fromPropertyValue = ((ZonedDateTime) fromPropertyValue)
|
||||
.format(DateTimeFormatter.ofPattern(ISO_8601_COMPATIBLE_DATE_PATTERN));
|
||||
.format(DateTimeFormatter.ofPattern(ISO_8601_COMPATIBLE_DATE_PATTERN));
|
||||
} else if (fromPropertyValue instanceof Enum) {
|
||||
fromPropertyValue = fromPropertyValue.toString();
|
||||
}
|
|
@ -5,9 +5,7 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.core.generator;
|
||||
|
||||
import com.microsoft.azure.documentdb.SqlParameter;
|
||||
import com.microsoft.azure.documentdb.SqlParameterCollection;
|
||||
import com.microsoft.azure.documentdb.SqlQuerySpec;
|
||||
import com.azure.data.cosmos.SqlQuerySpec;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
|
@ -25,7 +23,7 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter.toDocumentDBValue;
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter.toCosmosDbValue;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public abstract class AbstractQueryGenerator {
|
||||
|
@ -51,7 +49,7 @@ public abstract class AbstractQueryGenerator {
|
|||
Assert.isTrue(CriteriaType.isBinary(criteria.getType()), "Criteria type should be binary operation");
|
||||
|
||||
final String subject = criteria.getSubject();
|
||||
final Object subjectValue = toDocumentDBValue(criteria.getSubjectValues().get(0));
|
||||
final Object subjectValue = toCosmosDbValue(criteria.getSubjectValues().get(0));
|
||||
final String parameter = generateQueryParameter(subject);
|
||||
|
||||
parameters.add(Pair.with(parameter, subjectValue));
|
||||
|
@ -65,8 +63,8 @@ public abstract class AbstractQueryGenerator {
|
|||
|
||||
private String generateBetween(@NonNull Criteria criteria, @NonNull List<Pair<String, Object>> parameters) {
|
||||
final String subject = criteria.getSubject();
|
||||
final Object value1 = toDocumentDBValue(criteria.getSubjectValues().get(0));
|
||||
final Object value2 = toDocumentDBValue(criteria.getSubjectValues().get(1));
|
||||
final Object value1 = toCosmosDbValue(criteria.getSubjectValues().get(0));
|
||||
final Object value2 = toCosmosDbValue(criteria.getSubjectValues().get(1));
|
||||
final String subject1 = "start";
|
||||
final String subject2 = "end";
|
||||
final String parameter1 = generateQueryParameter(subject1);
|
||||
|
@ -200,32 +198,8 @@ public abstract class AbstractQueryGenerator {
|
|||
return String.join(" ", queryTails.stream().filter(StringUtils::hasText).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate SqlQuerySpec with given DocumentQuery and query head.
|
||||
*
|
||||
* @param query DocumentQuery represent one query method.
|
||||
* @param queryHead
|
||||
* @return The SqlQuerySpec for DocumentClient.
|
||||
*/
|
||||
protected SqlQuerySpec generateQuery(@NonNull DocumentQuery query, @NonNull String queryHead) {
|
||||
Assert.hasText(queryHead, "query head should have text.");
|
||||
|
||||
final Pair<String, List<Pair<String, Object>>> queryBody = generateQueryBody(query);
|
||||
final String queryString = String.join(" ", queryHead, queryBody.getValue0(), generateQueryTail(query));
|
||||
final List<Pair<String, Object>> parameters = queryBody.getValue1();
|
||||
final SqlParameterCollection sqlParameters = new SqlParameterCollection();
|
||||
|
||||
sqlParameters.addAll(
|
||||
parameters.stream()
|
||||
.map(p -> new SqlParameter("@" + p.getValue0(), toDocumentDBValue(p.getValue1())))
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
|
||||
return new SqlQuerySpec(queryString, sqlParameters);
|
||||
}
|
||||
|
||||
|
||||
protected com.azure.data.cosmos.SqlQuerySpec generateCosmosQuery(@NonNull DocumentQuery query,
|
||||
protected SqlQuerySpec generateCosmosQuery(@NonNull DocumentQuery query,
|
||||
@NonNull String queryHead) {
|
||||
final Pair<String, List<Pair<String, Object>>> queryBody = generateQueryBody(query);
|
||||
final String queryString = String.join(" ", queryHead, queryBody.getValue0(), generateQueryTail(query));
|
||||
|
@ -236,7 +210,7 @@ public abstract class AbstractQueryGenerator {
|
|||
sqlParameters.addAll(
|
||||
parameters.stream()
|
||||
.map(p -> new com.azure.data.cosmos.SqlParameter("@" + p.getValue0(),
|
||||
toDocumentDBValue(p.getValue1())))
|
||||
toCosmosDbValue(p.getValue1())))
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
|
||||
|
|
|
@ -5,16 +5,10 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.core.generator;
|
||||
|
||||
import com.microsoft.azure.documentdb.SqlQuerySpec;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
|
||||
public class CountQueryGenerator extends AbstractQueryGenerator implements QuerySpecGenerator {
|
||||
|
||||
@Override
|
||||
public SqlQuerySpec generate(DocumentQuery query) {
|
||||
return super.generateQuery(query, "SELECT VALUE COUNT(1) FROM r");
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.azure.data.cosmos.SqlQuerySpec generateCosmos(DocumentQuery query) {
|
||||
return super.generateCosmosQuery(query, "SELECT VALUE COUNT(1) FROM r");
|
||||
|
|
|
@ -5,19 +5,12 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.core.generator;
|
||||
|
||||
import com.microsoft.azure.documentdb.SqlQuerySpec;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
@NoArgsConstructor
|
||||
public class FindQuerySpecGenerator extends AbstractQueryGenerator implements QuerySpecGenerator {
|
||||
|
||||
@Override
|
||||
public SqlQuerySpec generate(@NonNull DocumentQuery query) {
|
||||
return super.generateQuery(query, "SELECT * FROM ROOT r");
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.azure.data.cosmos.SqlQuerySpec generateCosmos(DocumentQuery query) {
|
||||
return super.generateCosmosQuery(query, "SELECT * FROM ROOT r");
|
||||
|
|
|
@ -5,23 +5,14 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.core.generator;
|
||||
|
||||
import com.microsoft.azure.documentdb.SqlQuerySpec;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
|
||||
public interface QuerySpecGenerator {
|
||||
|
||||
/**
|
||||
* Generate find/delete/update SqlQuerySpec for documentDb client.
|
||||
*
|
||||
* @param query tree structured query condition.
|
||||
* @return SqlQuerySpec executed by documentDb client.
|
||||
*/
|
||||
SqlQuerySpec generate(DocumentQuery query);
|
||||
|
||||
/**
|
||||
* Generate the SqlQuerySpec for cosmosDB client.
|
||||
* @param query tree structured query condition.
|
||||
* @return SqlQuerySpec executed by documentDb client.
|
||||
* @return SqlQuerySpec executed by cosmos client.
|
||||
*/
|
||||
com.azure.data.cosmos.SqlQuerySpec generateCosmos(DocumentQuery query);
|
||||
}
|
||||
|
|
|
@ -16,12 +16,12 @@ import org.springframework.data.util.TypeInformation;
|
|||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
|
||||
|
||||
public class BasicDocumentDbPersistentEntity<T> extends BasicPersistentEntity<T, DocumentDbPersistentProperty>
|
||||
implements DocumentDbPersistentEntity<T>, ApplicationContextAware {
|
||||
public class BasicCosmosPersistentEntity<T> extends BasicPersistentEntity<T, CosmosPersistentProperty>
|
||||
implements CosmosPersistentEntity<T>, ApplicationContextAware {
|
||||
|
||||
private final StandardEvaluationContext context;
|
||||
|
||||
public BasicDocumentDbPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
public BasicCosmosPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
super(typeInformation);
|
||||
this.context = new StandardEvaluationContext();
|
||||
}
|
|
@ -13,16 +13,16 @@ import org.springframework.data.mapping.model.Property;
|
|||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
|
||||
|
||||
public class BasicDocumentDbPersistentProperty extends AnnotationBasedPersistentProperty<DocumentDbPersistentProperty>
|
||||
implements DocumentDbPersistentProperty {
|
||||
public class BasicCosmosPersistentProperty extends AnnotationBasedPersistentProperty<CosmosPersistentProperty>
|
||||
implements CosmosPersistentProperty {
|
||||
|
||||
public BasicDocumentDbPersistentProperty(Property property, DocumentDbPersistentEntity<?> owner,
|
||||
SimpleTypeHolder simpleTypeHolder) {
|
||||
public BasicCosmosPersistentProperty(Property property, CosmosPersistentEntity<?> owner,
|
||||
SimpleTypeHolder simpleTypeHolder) {
|
||||
super(property, owner, simpleTypeHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Association<DocumentDbPersistentProperty> createAssociation() {
|
||||
protected Association<CosmosPersistentProperty> createAssociation() {
|
||||
return new Association<>(this, null);
|
||||
}
|
||||
|
|
@ -13,14 +13,14 @@ import org.springframework.data.mapping.model.SimpleTypeHolder;
|
|||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
|
||||
public class DocumentDbMappingContext
|
||||
extends AbstractMappingContext<BasicDocumentDbPersistentEntity<?>, DocumentDbPersistentProperty> {
|
||||
public class CosmosMappingContext
|
||||
extends AbstractMappingContext<BasicCosmosPersistentEntity<?>, CosmosPersistentProperty> {
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
@Override
|
||||
protected <T> BasicDocumentDbPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
final BasicDocumentDbPersistentEntity<T> entity = new BasicDocumentDbPersistentEntity<>(typeInformation);
|
||||
protected <T> BasicCosmosPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
final BasicCosmosPersistentEntity<T> entity = new BasicCosmosPersistentEntity<>(typeInformation);
|
||||
|
||||
if (context != null) {
|
||||
entity.setApplicationContext(context);
|
||||
|
@ -29,10 +29,10 @@ public class DocumentDbMappingContext
|
|||
}
|
||||
|
||||
@Override
|
||||
public DocumentDbPersistentProperty createPersistentProperty(Property property,
|
||||
BasicDocumentDbPersistentEntity<?> owner,
|
||||
SimpleTypeHolder simpleTypeHolder) {
|
||||
return new BasicDocumentDbPersistentProperty(property, owner, simpleTypeHolder);
|
||||
public CosmosPersistentProperty createPersistentProperty(Property property,
|
||||
BasicCosmosPersistentEntity<?> owner,
|
||||
SimpleTypeHolder simpleTypeHolder) {
|
||||
return new BasicCosmosPersistentProperty(property, owner, simpleTypeHolder);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -9,7 +9,7 @@ package com.microsoft.azure.spring.data.cosmosdb.core.mapping;
|
|||
import org.springframework.data.mapping.PersistentEntity;
|
||||
|
||||
|
||||
public interface DocumentDbPersistentEntity<T> extends PersistentEntity<T, DocumentDbPersistentProperty> {
|
||||
public interface CosmosPersistentEntity<T> extends PersistentEntity<T, CosmosPersistentProperty> {
|
||||
|
||||
String getCollection();
|
||||
|
|
@ -9,5 +9,5 @@ package com.microsoft.azure.spring.data.cosmosdb.core.mapping;
|
|||
import org.springframework.data.mapping.PersistentProperty;
|
||||
|
||||
|
||||
public interface DocumentDbPersistentProperty extends PersistentProperty<DocumentDbPersistentProperty> {
|
||||
public interface CosmosPersistentProperty extends PersistentProperty<CosmosPersistentProperty> {
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.core.mapping;
|
||||
|
||||
import com.microsoft.azure.documentdb.IndexingMode;
|
||||
import com.azure.data.cosmos.IndexingMode;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.Constants;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
|
||||
|
@ -18,7 +18,7 @@ import java.lang.annotation.*;
|
|||
public @interface DocumentIndexingPolicy {
|
||||
boolean automatic() default Constants.DEFAULT_INDEXINGPOLICY_AUTOMATIC;
|
||||
|
||||
IndexingMode mode() default IndexingMode.Consistent; // Enum is not really compile time constant
|
||||
IndexingMode mode() default IndexingMode.CONSISTENT; // Enum is not really compile time constant
|
||||
|
||||
String[] includePaths() default {};
|
||||
|
||||
|
|
|
@ -5,38 +5,39 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.core.query;
|
||||
|
||||
import com.azure.data.cosmos.FeedResponse;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
||||
/**
|
||||
* DocumentDbPageRequest representing page request during pagination query, field
|
||||
* {@link com.microsoft.azure.documentdb.FeedResponse#getResponseContinuation response continuation token} is saved
|
||||
* CosmosPageRequest representing page request during pagination query, field
|
||||
* {@link FeedResponse#continuationToken()} response continuation token} is saved
|
||||
* to help query next page.
|
||||
* <p>
|
||||
* The requestContinuation token should be saved after each request and reused in later queries.
|
||||
*/
|
||||
public class DocumentDbPageRequest extends PageRequest {
|
||||
public class CosmosPageRequest extends PageRequest {
|
||||
private static final long serialVersionUID = 6093304300037688375L;
|
||||
|
||||
// Request continuation token used to resume query
|
||||
private String requestContinuation;
|
||||
|
||||
public DocumentDbPageRequest(int page, int size, String requestContinuation) {
|
||||
super(page, size);
|
||||
public CosmosPageRequest(int page, int size, String requestContinuation) {
|
||||
super(page, size, Sort.unsorted());
|
||||
this.requestContinuation = requestContinuation;
|
||||
}
|
||||
|
||||
public static DocumentDbPageRequest of(int page, int size, String requestContinuation) {
|
||||
return new DocumentDbPageRequest(page, size, requestContinuation);
|
||||
public static CosmosPageRequest of(int page, int size, String requestContinuation) {
|
||||
return new CosmosPageRequest(page, size, requestContinuation);
|
||||
}
|
||||
|
||||
public DocumentDbPageRequest(int page, int size, String requestContinuation, Sort sort) {
|
||||
public CosmosPageRequest(int page, int size, String requestContinuation, Sort sort) {
|
||||
super(page, size, sort);
|
||||
this.requestContinuation = requestContinuation;
|
||||
}
|
||||
|
||||
public static DocumentDbPageRequest of(int page, int size, String requestContinuation, Sort sort) {
|
||||
return new DocumentDbPageRequest(page, size, requestContinuation, sort);
|
||||
public static CosmosPageRequest of(int page, int size, String requestContinuation, Sort sort) {
|
||||
return new CosmosPageRequest(page, size, requestContinuation, sort);
|
||||
}
|
||||
|
||||
public String getRequestContinuation() {
|
||||
|
@ -58,11 +59,11 @@ public class DocumentDbPageRequest extends PageRequest {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof DocumentDbPageRequest)) {
|
||||
if (!(obj instanceof CosmosPageRequest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final DocumentDbPageRequest that = (DocumentDbPageRequest) obj;
|
||||
final CosmosPageRequest that = (CosmosPageRequest) obj;
|
||||
|
||||
final boolean continuationTokenEquals = requestContinuation != null ?
|
||||
requestContinuation.equals(that.requestContinuation) : that.requestContinuation == null;
|
|
@ -42,7 +42,6 @@ public enum CriteriaType {
|
|||
@Getter
|
||||
private String sqlKeyword;
|
||||
|
||||
// Map Part.Type to CriteriaType
|
||||
private static final Map<Part.Type, CriteriaType> PART_TREE_TYPE_TO_CRITERIA;
|
||||
|
||||
static {
|
||||
|
|
|
@ -8,12 +8,12 @@ package com.microsoft.azure.spring.data.cosmosdb.exception;
|
|||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
public class DocumentDBAccessException extends DataAccessException {
|
||||
public DocumentDBAccessException(String msg) {
|
||||
public class CosmosDBAccessException extends DataAccessException {
|
||||
public CosmosDBAccessException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public DocumentDBAccessException(@Nullable String msg, @Nullable Throwable cause) {
|
||||
public CosmosDBAccessException(@Nullable String msg, @Nullable Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository;
|
||||
|
||||
import com.microsoft.azure.documentdb.PartitionKey;
|
||||
import com.azure.data.cosmos.PartitionKey;
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
|
||||
|
@ -14,7 +14,7 @@ import java.io.Serializable;
|
|||
import java.util.Optional;
|
||||
|
||||
@NoRepositoryBean
|
||||
public interface DocumentDbRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
|
||||
public interface CosmosRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
|
||||
|
||||
/**
|
||||
* Retrieves an entity by its id.
|
|
@ -12,16 +12,16 @@ import org.springframework.data.repository.config.RepositoryConfigurationExtensi
|
|||
import java.lang.annotation.Annotation;
|
||||
|
||||
|
||||
public class DocumentDbRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport {
|
||||
public class CosmosRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport {
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotation() {
|
||||
return EnableDocumentDbRepositories.class;
|
||||
return EnableCosmosRepositories.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoryConfigurationExtension getExtension() {
|
||||
return new DocumentDbRepositoryConfigurationExtension();
|
||||
return new CosmosRepositoryConfigurationExtension();
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.config;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.Constants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosRepositoryFactoryBean;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationSource;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
|
||||
public class CosmosRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {
|
||||
|
||||
@Override
|
||||
public String getModuleName() {
|
||||
return Constants.COSMOSDB_MODULE_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModulePrefix() {
|
||||
return Constants.COSMOSDB_MODULE_PREFIX;
|
||||
}
|
||||
|
||||
public String getRepositoryFactoryBeanClassName() {
|
||||
return CosmosRepositoryFactoryBean.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<?>> getIdentifyingTypes() {
|
||||
return Collections.<Class<?>>singleton(CosmosRepository.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<? extends Annotation>> getIdentifyingAnnotations() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConfigurationSource config) {
|
||||
super.registerBeansForRoot(registry, config);
|
||||
|
||||
if (!registry.containsBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT)) {
|
||||
final RootBeanDefinition definition = new RootBeanDefinition(CosmosMappingContext.class);
|
||||
definition.setRole(AbstractBeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
definition.setSource(config.getSource());
|
||||
|
||||
registry.registerBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT, definition);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcess(BeanDefinitionBuilder builder, RepositoryConfigurationSource source) {
|
||||
super.postProcess(builder, source);
|
||||
}
|
||||
|
||||
// Overriding this to provide reactive repository support.
|
||||
@Override
|
||||
protected boolean useRepositoryConfiguration(RepositoryMetadata metadata) {
|
||||
// CosmosRepository is the sync repository, and hence returning !isReactiveRepository.
|
||||
// ReactiveCosmosRepository is reactive repository.
|
||||
return !metadata.isReactiveRepository();
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@
|
|||
package com.microsoft.azure.spring.data.cosmosdb.repository.config;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.Constants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbRepositoryFactoryBean;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosRepositoryFactoryBean;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.repository.config.DefaultRepositoryBaseClass;
|
||||
|
@ -20,8 +20,8 @@ import java.lang.annotation.*;
|
|||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
@Import(DocumentDbRepositoriesRegistrar.class)
|
||||
public @interface EnableDocumentDbRepositories {
|
||||
@Import(CosmosRepositoriesRegistrar.class)
|
||||
public @interface EnableCosmosRepositories {
|
||||
|
||||
String[] value() default {};
|
||||
|
||||
|
@ -39,7 +39,7 @@ public @interface EnableDocumentDbRepositories {
|
|||
|
||||
QueryLookupStrategy.Key queryLookupStrategy() default QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND;
|
||||
|
||||
Class<?> repositoryFactoryBeanClass() default DocumentDbRepositoryFactoryBean.class;
|
||||
Class<?> repositoryFactoryBeanClass() default CosmosRepositoryFactoryBean.class;
|
||||
|
||||
Class<?> repositoryBaseClass() default DefaultRepositoryBaseClass.class;
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.config;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.Constants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.ReactiveCosmosRepositoryFactoryBean;
|
||||
import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.repository.config.DefaultRepositoryBaseClass;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
@Import(ReactiveCosmosRepositoriesRegistrar.class)
|
||||
public @interface EnableReactiveCosmosRepositories {
|
||||
|
||||
String[] value() default {};
|
||||
|
||||
String[] basePackages() default {};
|
||||
|
||||
Class<?>[] basePackageClasses() default {};
|
||||
|
||||
Filter[] includeFilters() default {};
|
||||
|
||||
Filter[] excludeFilters() default {};
|
||||
|
||||
String repositoryImplementationPostfix() default Constants.DEFAULT_REPOSITORY_IMPLEMENT_POSTFIX;
|
||||
|
||||
String namedQueriesLocation() default "";
|
||||
|
||||
QueryLookupStrategy.Key queryLookupStrategy() default QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND;
|
||||
|
||||
Class<?> repositoryFactoryBeanClass() default ReactiveCosmosRepositoryFactoryBean.class;
|
||||
|
||||
Class<?> repositoryBaseClass() default DefaultRepositoryBaseClass.class;
|
||||
|
||||
boolean considerNestedRepositories() default false;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.config;
|
||||
|
||||
import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
|
||||
public class ReactiveCosmosRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport {
|
||||
|
||||
@Override
|
||||
protected Class<? extends Annotation> getAnnotation() {
|
||||
return EnableReactiveCosmosRepositories.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoryConfigurationExtension getExtension() {
|
||||
return new ReactiveCosmosRepositoryConfigurationExtension();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -7,40 +7,41 @@
|
|||
package com.microsoft.azure.spring.data.cosmosdb.repository.config;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.Constants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbRepositoryFactoryBean;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.ReactiveCosmosRepositoryFactoryBean;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationSource;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
|
||||
public class DocumentDbRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {
|
||||
public class ReactiveCosmosRepositoryConfigurationExtension extends RepositoryConfigurationExtensionSupport {
|
||||
|
||||
@Override
|
||||
public String getModuleName() {
|
||||
return Constants.DOCUMENTDB_MODULE_NAME;
|
||||
return Constants.COSMOSDB_MODULE_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModulePrefix() {
|
||||
return Constants.DOCUMENTDB_MODULE_PREFIX;
|
||||
return Constants.COSMOSDB_MODULE_PREFIX;
|
||||
}
|
||||
|
||||
public String getRepositoryFactoryBeanClassName() {
|
||||
return DocumentDbRepositoryFactoryBean.class.getName();
|
||||
return ReactiveCosmosRepositoryFactoryBean.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<Class<?>> getIdentifyingTypes() {
|
||||
return Collections.<Class<?>>singleton(DocumentDbRepository.class);
|
||||
return Collections.<Class<?>>singleton(ReactiveCosmosRepository.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,12 +54,12 @@ public class DocumentDbRepositoryConfigurationExtension extends RepositoryConfig
|
|||
public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConfigurationSource config) {
|
||||
super.registerBeansForRoot(registry, config);
|
||||
|
||||
if (!registry.containsBeanDefinition(Constants.DOCUMENTDB_MAPPING_CONTEXT_NAME)) {
|
||||
final RootBeanDefinition definition = new RootBeanDefinition(DocumentDbMappingContext.class);
|
||||
if (!registry.containsBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT)) {
|
||||
final RootBeanDefinition definition = new RootBeanDefinition(CosmosMappingContext.class);
|
||||
definition.setRole(AbstractBeanDefinition.ROLE_INFRASTRUCTURE);
|
||||
definition.setSource(config.getSource());
|
||||
|
||||
registry.registerBeanDefinition(Constants.DOCUMENTDB_MAPPING_CONTEXT_NAME, definition);
|
||||
registry.registerBeanDefinition(Constants.COSMOS_MAPPING_CONTEXT, definition);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,4 +67,10 @@ public class DocumentDbRepositoryConfigurationExtension extends RepositoryConfig
|
|||
public void postProcess(BeanDefinitionBuilder builder, RepositoryConfigurationSource source) {
|
||||
super.postProcess(builder, source);
|
||||
}
|
||||
|
||||
// Overriding this to provide reactive repository support.
|
||||
@Override
|
||||
protected boolean useRepositoryConfiguration(RepositoryMetadata metadata) {
|
||||
return metadata.isReactiveRepository();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
|
||||
public abstract class AbstractCosmosQuery implements RepositoryQuery {
|
||||
|
||||
private final CosmosQueryMethod method;
|
||||
private final CosmosOperations operations;
|
||||
|
||||
public AbstractCosmosQuery(CosmosQueryMethod method, CosmosOperations operations) {
|
||||
this.method = method;
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
public Object execute(Object[] parameters) {
|
||||
final CosmosParameterAccessor accessor = new CosmosParameterParameterAccessor(method, parameters);
|
||||
final DocumentQuery query = createQuery(accessor);
|
||||
|
||||
final ResultProcessor processor = method.getResultProcessor().withDynamicProjection(accessor);
|
||||
final String collection = ((CosmosEntityMetadata) method.getEntityInformation()).getCollectionName();
|
||||
|
||||
final CosmosQueryExecution execution = getExecution(accessor);
|
||||
return execution.execute(query, processor.getReturnedType().getDomainType(), collection);
|
||||
}
|
||||
|
||||
|
||||
private CosmosQueryExecution getExecution(CosmosParameterAccessor accessor) {
|
||||
if (isDeleteQuery()) {
|
||||
return new CosmosQueryExecution.DeleteExecution(operations);
|
||||
} else if (method.isPageQuery()) {
|
||||
return new CosmosQueryExecution.PagedExecution(operations, accessor.getPageable());
|
||||
} else if (isExistsQuery()) {
|
||||
return new CosmosQueryExecution.ExistsExecution(operations);
|
||||
} else {
|
||||
return new CosmosQueryExecution.MultiEntityExecution(operations);
|
||||
}
|
||||
}
|
||||
|
||||
public CosmosQueryMethod getQueryMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
protected abstract DocumentQuery createQuery(CosmosParameterAccessor accessor);
|
||||
|
||||
protected abstract boolean isDeleteQuery();
|
||||
|
||||
protected abstract boolean isExistsQuery();
|
||||
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
|
||||
public abstract class AbstractDocumentDbQuery implements RepositoryQuery {
|
||||
|
||||
private final DocumentDbQueryMethod method;
|
||||
private final DocumentDbOperations operations;
|
||||
|
||||
public AbstractDocumentDbQuery(DocumentDbQueryMethod method, DocumentDbOperations operations) {
|
||||
this.method = method;
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
public Object execute(Object[] parameters) {
|
||||
final DocumentDbParameterAccessor accessor = new DocumentDbParameterParameterAccessor(method, parameters);
|
||||
final DocumentQuery query = createQuery(accessor);
|
||||
|
||||
final ResultProcessor processor = method.getResultProcessor().withDynamicProjection(accessor);
|
||||
final String collection = ((DocumentDbEntityMetadata) method.getEntityInformation()).getCollectionName();
|
||||
|
||||
final DocumentDbQueryExecution execution = getExecution(accessor);
|
||||
return execution.execute(query, processor.getReturnedType().getDomainType(), collection);
|
||||
}
|
||||
|
||||
|
||||
private DocumentDbQueryExecution getExecution(DocumentDbParameterAccessor accessor) {
|
||||
if (isDeleteQuery()) {
|
||||
return new DocumentDbQueryExecution.DeleteExecution(operations);
|
||||
} else if (method.isPageQuery()) {
|
||||
return new DocumentDbQueryExecution.PagedExecution(operations, accessor.getPageable());
|
||||
} else if (isExistsQuery()) {
|
||||
return new DocumentDbQueryExecution.ExistsExecution(operations);
|
||||
} else {
|
||||
return new DocumentDbQueryExecution.MultiEntityExecution(operations);
|
||||
}
|
||||
}
|
||||
|
||||
public DocumentDbQueryMethod getQueryMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
protected abstract DocumentQuery createQuery(DocumentDbParameterAccessor accessor);
|
||||
|
||||
protected abstract boolean isDeleteQuery();
|
||||
|
||||
protected abstract boolean isExistsQuery();
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
|
||||
public abstract class AbstractReactiveCosmosQuery implements RepositoryQuery {
|
||||
|
||||
private final ReactiveCosmosQueryMethod method;
|
||||
private final ReactiveCosmosOperations operations;
|
||||
|
||||
public AbstractReactiveCosmosQuery(ReactiveCosmosQueryMethod method,
|
||||
ReactiveCosmosOperations operations) {
|
||||
this.method = method;
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
public Object execute(Object[] parameters) {
|
||||
final ReactiveCosmosParameterAccessor accessor =
|
||||
new ReactiveCosmosParameterParameterAccessor(method, parameters);
|
||||
final DocumentQuery query = createQuery(accessor);
|
||||
|
||||
final ResultProcessor processor =
|
||||
method.getResultProcessor().withDynamicProjection(accessor);
|
||||
final String collection =
|
||||
((ReactiveCosmosEntityMetadata) method.getEntityInformation()).getCollectionName();
|
||||
|
||||
final ReactiveCosmosQueryExecution execution = getExecution(accessor);
|
||||
return execution.execute(query, processor.getReturnedType().getDomainType(), collection);
|
||||
}
|
||||
|
||||
|
||||
private ReactiveCosmosQueryExecution getExecution(ReactiveCosmosParameterAccessor accessor) {
|
||||
if (isDeleteQuery()) {
|
||||
return new ReactiveCosmosQueryExecution.DeleteExecution(operations);
|
||||
} else if (method.isPageQuery()) {
|
||||
throw new IllegalArgumentException("Paged Query is not supported by reactive cosmos " +
|
||||
"db");
|
||||
} else if (isExistsQuery()) {
|
||||
return new ReactiveCosmosQueryExecution.ExistsExecution(operations);
|
||||
} else {
|
||||
return new ReactiveCosmosQueryExecution.MultiEntityExecution(operations);
|
||||
}
|
||||
}
|
||||
|
||||
public ReactiveCosmosQueryMethod getQueryMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
protected abstract DocumentQuery createQuery(ReactiveCosmosParameterAccessor accessor);
|
||||
|
||||
protected abstract boolean isDeleteQuery();
|
||||
|
||||
protected abstract boolean isExistsQuery();
|
||||
|
||||
}
|
|
@ -7,6 +7,6 @@ package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
|||
|
||||
import org.springframework.data.repository.core.EntityMetadata;
|
||||
|
||||
public interface DocumentDbEntityMetadata<T> extends EntityMetadata {
|
||||
public interface CosmosEntityMetadata<T> extends EntityMetadata {
|
||||
String getCollectionName();
|
||||
}
|
|
@ -8,9 +8,9 @@ package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
|||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.repository.query.Parameter;
|
||||
|
||||
public class DocumentDbParameter extends Parameter {
|
||||
public class CosmosParameter extends Parameter {
|
||||
|
||||
public DocumentDbParameter(MethodParameter parameter) {
|
||||
public CosmosParameter(MethodParameter parameter) {
|
||||
super(parameter);
|
||||
}
|
||||
|
|
@ -7,6 +7,6 @@ package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
|||
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
|
||||
public interface DocumentDbParameterAccessor extends ParameterAccessor {
|
||||
public interface CosmosParameterAccessor extends ParameterAccessor {
|
||||
Object[] getValues();
|
||||
}
|
|
@ -10,12 +10,12 @@ import org.springframework.data.repository.query.ParametersParameterAccessor;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class DocumentDbParameterParameterAccessor extends ParametersParameterAccessor
|
||||
implements DocumentDbParameterAccessor {
|
||||
public class CosmosParameterParameterAccessor extends ParametersParameterAccessor
|
||||
implements CosmosParameterAccessor {
|
||||
|
||||
private final List<Object> values;
|
||||
|
||||
public DocumentDbParameterParameterAccessor(DocumentDbQueryMethod method, Object[] values) {
|
||||
public CosmosParameterParameterAccessor(CosmosQueryMethod method, Object[] values) {
|
||||
super(method.getParameters(), values);
|
||||
|
||||
this.values = Arrays.asList(values);
|
|
@ -11,23 +11,23 @@ import org.springframework.data.repository.query.Parameters;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
public class DocumentDbParameters extends Parameters<DocumentDbParameters, DocumentDbParameter> {
|
||||
public class CosmosParameters extends Parameters<CosmosParameters, CosmosParameter> {
|
||||
|
||||
public DocumentDbParameters(Method method) {
|
||||
public CosmosParameters(Method method) {
|
||||
super(method);
|
||||
}
|
||||
|
||||
private DocumentDbParameters(List<DocumentDbParameter> parameters) {
|
||||
private CosmosParameters(List<CosmosParameter> parameters) {
|
||||
super(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DocumentDbParameters createFrom(List<DocumentDbParameter> parameters) {
|
||||
return new DocumentDbParameters(parameters);
|
||||
protected CosmosParameters createFrom(List<CosmosParameter> parameters) {
|
||||
return new CosmosParameters(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DocumentDbParameter createParameter(MethodParameter parameter) {
|
||||
return new DocumentDbParameter(parameter);
|
||||
protected CosmosParameter createParameter(MethodParameter parameter) {
|
||||
return new CosmosParameter(parameter);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.Constants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
|
||||
import org.springframework.data.repository.query.parser.Part;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
// TODO: String based query, based on how cosmosdb provides.
|
||||
// StringCosmosQuery class,
|
||||
// How to bind values to the query. if CosmosDb already has binding capability, if not we would have to do it here in
|
||||
// some creative way.query creator are associated with part tree queries,
|
||||
public class CosmosQueryCreator extends AbstractQueryCreator<DocumentQuery, Criteria> {
|
||||
|
||||
private final MappingContext<?, CosmosPersistentProperty> mappingContext;
|
||||
|
||||
public CosmosQueryCreator(PartTree tree, CosmosParameterAccessor accessor,
|
||||
MappingContext<?, CosmosPersistentProperty> mappingContext) {
|
||||
super(tree, accessor);
|
||||
|
||||
this.mappingContext = mappingContext;
|
||||
}
|
||||
|
||||
private String getSubject(@NonNull Part part) {
|
||||
String subject = mappingContext.getPersistentPropertyPath(part.getProperty()).toDotPath();
|
||||
final Class<?> domainClass = part.getProperty().getOwningType().getType();
|
||||
|
||||
@SuppressWarnings("unchecked") final CosmosEntityInformation information =
|
||||
new CosmosEntityInformation(domainClass);
|
||||
|
||||
if (information.getIdField().getName().equals(subject)) {
|
||||
subject = Constants.ID_PROPERTY_NAME;
|
||||
}
|
||||
|
||||
return subject;
|
||||
}
|
||||
|
||||
@Override // Note (panli): side effect here, this method will change the iterator status of parameters.
|
||||
protected Criteria create(Part part, Iterator<Object> parameters) {
|
||||
final Part.Type type = part.getType();
|
||||
final String subject = getSubject(part);
|
||||
final List<Object> values = new ArrayList<>();
|
||||
|
||||
if (CriteriaType.isPartTypeUnSupported(type)) {
|
||||
throw new UnsupportedOperationException("Unsupported keyword: " + type);
|
||||
}
|
||||
|
||||
for (int i = 0; i < part.getNumberOfArguments(); i++) {
|
||||
Assert.isTrue(parameters.hasNext(), "should not reach the end of iterator");
|
||||
values.add(parameters.next());
|
||||
}
|
||||
|
||||
return Criteria.getInstance(CriteriaType.toCriteriaType(type), subject, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Criteria and(@NonNull Part part, @NonNull Criteria base, @NonNull Iterator<Object> parameters) {
|
||||
final Criteria right = this.create(part, parameters);
|
||||
|
||||
return Criteria.getInstance(CriteriaType.AND, base, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Criteria or(@NonNull Criteria base, @NonNull Criteria criteria) {
|
||||
return Criteria.getInstance(CriteriaType.OR, base, criteria);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DocumentQuery complete(@NonNull Criteria criteria, @NonNull Sort sort) {
|
||||
return new DocumentQuery(criteria).with(sort);
|
||||
}
|
||||
}
|
|
@ -5,19 +5,19 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
public interface DocumentDbQueryExecution {
|
||||
public interface CosmosQueryExecution {
|
||||
Object execute(DocumentQuery query, Class<?> type, String collection);
|
||||
|
||||
final class CollectionExecution implements DocumentDbQueryExecution {
|
||||
final class CollectionExecution implements CosmosQueryExecution {
|
||||
|
||||
private final DocumentDbOperations operations;
|
||||
private final CosmosOperations operations;
|
||||
|
||||
public CollectionExecution(DocumentDbOperations operations) {
|
||||
public CollectionExecution(CosmosOperations operations) {
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
|
@ -27,11 +27,11 @@ public interface DocumentDbQueryExecution {
|
|||
}
|
||||
}
|
||||
|
||||
final class MultiEntityExecution implements DocumentDbQueryExecution {
|
||||
final class MultiEntityExecution implements CosmosQueryExecution {
|
||||
|
||||
private final DocumentDbOperations operations;
|
||||
private final CosmosOperations operations;
|
||||
|
||||
public MultiEntityExecution(DocumentDbOperations operations) {
|
||||
public MultiEntityExecution(CosmosOperations operations) {
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
|
@ -41,11 +41,11 @@ public interface DocumentDbQueryExecution {
|
|||
}
|
||||
}
|
||||
|
||||
final class ExistsExecution implements DocumentDbQueryExecution {
|
||||
final class ExistsExecution implements CosmosQueryExecution {
|
||||
|
||||
private final DocumentDbOperations operations;
|
||||
private final CosmosOperations operations;
|
||||
|
||||
public ExistsExecution(DocumentDbOperations operations) {
|
||||
public ExistsExecution(CosmosOperations operations) {
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
|
@ -55,11 +55,11 @@ public interface DocumentDbQueryExecution {
|
|||
}
|
||||
}
|
||||
|
||||
final class DeleteExecution implements DocumentDbQueryExecution {
|
||||
final class DeleteExecution implements CosmosQueryExecution {
|
||||
|
||||
private final DocumentDbOperations operations;
|
||||
private final CosmosOperations operations;
|
||||
|
||||
public DeleteExecution(DocumentDbOperations operations) {
|
||||
public DeleteExecution(CosmosOperations operations) {
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
|
@ -69,20 +69,20 @@ public interface DocumentDbQueryExecution {
|
|||
}
|
||||
}
|
||||
|
||||
final class PagedExecution implements DocumentDbQueryExecution {
|
||||
private final DocumentDbOperations operations;
|
||||
final class PagedExecution implements CosmosQueryExecution {
|
||||
private final CosmosOperations operations;
|
||||
private final Pageable pageable;
|
||||
|
||||
public PagedExecution(DocumentDbOperations operations, Pageable pageable) {
|
||||
public PagedExecution(CosmosOperations operations, Pageable pageable) {
|
||||
this.operations = operations;
|
||||
this.pageable = pageable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(DocumentQuery query, Class<?> type, String collection) {
|
||||
if (pageable.getPageNumber() != 0 && !(pageable instanceof DocumentDbPageRequest)) {
|
||||
if (pageable.getPageNumber() != 0 && !(pageable instanceof CosmosPageRequest)) {
|
||||
throw new IllegalStateException("Not the first page but Pageable is not a valid " +
|
||||
"DocumentDbPageRequest, requestContinuation is required for non first page request");
|
||||
"CosmosPageRequest, requestContinuation is required for non first page request");
|
||||
}
|
||||
|
||||
query.with(pageable);
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.EntityMetadata;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
|
@ -13,11 +13,11 @@ import org.springframework.data.repository.query.QueryMethod;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class DocumentDbQueryMethod extends QueryMethod {
|
||||
public class CosmosQueryMethod extends QueryMethod {
|
||||
|
||||
private DocumentDbEntityMetadata<?> metadata;
|
||||
private CosmosEntityMetadata<?> metadata;
|
||||
|
||||
public DocumentDbQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
|
||||
public CosmosQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
|
||||
super(method, metadata, factory);
|
||||
}
|
||||
|
||||
|
@ -25,10 +25,10 @@ public class DocumentDbQueryMethod extends QueryMethod {
|
|||
@SuppressWarnings("unchecked")
|
||||
public EntityMetadata<?> getEntityInformation() {
|
||||
final Class<Object> domainClass = (Class<Object>) getDomainClass();
|
||||
final DocumentDbEntityInformation entityInformation =
|
||||
new DocumentDbEntityInformation<Object, String>(domainClass);
|
||||
final CosmosEntityInformation entityInformation =
|
||||
new CosmosEntityInformation<Object, String>(domainClass);
|
||||
|
||||
this.metadata = new SimpleDocumentDbEntityMetadata<Object>(domainClass, entityInformation);
|
||||
this.metadata = new SimpleCosmosEntityMetadata<Object>(domainClass, entityInformation);
|
||||
return this.metadata;
|
||||
}
|
||||
}
|
|
@ -5,21 +5,21 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbPersistentProperty;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty;
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
public class PartTreeDocumentDbQuery extends AbstractDocumentDbQuery {
|
||||
public class PartTreeCosmosQuery extends AbstractCosmosQuery {
|
||||
|
||||
private final PartTree tree;
|
||||
private final MappingContext<?, DocumentDbPersistentProperty> mappingContext;
|
||||
private final MappingContext<?, CosmosPersistentProperty> mappingContext;
|
||||
private final ResultProcessor processor;
|
||||
|
||||
public PartTreeDocumentDbQuery(DocumentDbQueryMethod method, DocumentDbOperations operations) {
|
||||
public PartTreeCosmosQuery(CosmosQueryMethod method, CosmosOperations operations) {
|
||||
super(method, operations);
|
||||
|
||||
this.processor = method.getResultProcessor();
|
||||
|
@ -28,8 +28,8 @@ public class PartTreeDocumentDbQuery extends AbstractDocumentDbQuery {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected DocumentQuery createQuery(DocumentDbParameterAccessor accessor) {
|
||||
final DocumentDbQueryCreator creator = new DocumentDbQueryCreator(tree, accessor, mappingContext);
|
||||
protected DocumentQuery createQuery(CosmosParameterAccessor accessor) {
|
||||
final CosmosQueryCreator creator = new CosmosQueryCreator(tree, accessor, mappingContext);
|
||||
|
||||
final DocumentQuery query = creator.createQuery();
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.repository.query.ResultProcessor;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
public class PartTreeReactiveCosmosQuery extends AbstractReactiveCosmosQuery {
|
||||
|
||||
private final PartTree tree;
|
||||
private final MappingContext<?, CosmosPersistentProperty> mappingContext;
|
||||
private final ResultProcessor processor;
|
||||
|
||||
public PartTreeReactiveCosmosQuery(ReactiveCosmosQueryMethod method, ReactiveCosmosOperations operations) {
|
||||
super(method, operations);
|
||||
|
||||
this.processor = method.getResultProcessor();
|
||||
this.tree = new PartTree(method.getName(), processor.getReturnedType().getDomainType());
|
||||
this.mappingContext = operations.getConverter().getMappingContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DocumentQuery createQuery(ReactiveCosmosParameterAccessor accessor) {
|
||||
final ReactiveCosmosQueryCreator creator = new ReactiveCosmosQueryCreator(tree, accessor, mappingContext);
|
||||
|
||||
final DocumentQuery query = creator.createQuery();
|
||||
|
||||
if (tree.isLimiting()) {
|
||||
throw new NotImplementedException("Limiting is not supported.");
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDeleteQuery() {
|
||||
return tree.isDelete();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isExistsQuery() {
|
||||
return tree.isExistsProjection();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import org.springframework.data.repository.core.EntityMetadata;
|
||||
|
||||
public interface ReactiveCosmosEntityMetadata<T> extends EntityMetadata {
|
||||
String getCollectionName();
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
|
||||
public interface ReactiveCosmosParameterAccessor extends ParameterAccessor {
|
||||
Object[] getValues();
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class ReactiveCosmosParameterParameterAccessor extends ParametersParameterAccessor
|
||||
implements ReactiveCosmosParameterAccessor {
|
||||
|
||||
private final List<Object> values;
|
||||
|
||||
public ReactiveCosmosParameterParameterAccessor(ReactiveCosmosQueryMethod method, Object[] values) {
|
||||
super(method.getParameters(), values);
|
||||
|
||||
this.values = Arrays.asList(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getValues() {
|
||||
return values.toArray();
|
||||
}
|
||||
}
|
|
@ -6,11 +6,11 @@
|
|||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.Constants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbPersistentProperty;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosPersistentProperty;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
|
||||
|
@ -23,12 +23,12 @@ import java.util.ArrayList;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class DocumentDbQueryCreator extends AbstractQueryCreator<DocumentQuery, Criteria> {
|
||||
public class ReactiveCosmosQueryCreator extends AbstractQueryCreator<DocumentQuery, Criteria> {
|
||||
|
||||
private final MappingContext<?, DocumentDbPersistentProperty> mappingContext;
|
||||
private final MappingContext<?, CosmosPersistentProperty> mappingContext;
|
||||
|
||||
public DocumentDbQueryCreator(PartTree tree, DocumentDbParameterAccessor accessor,
|
||||
MappingContext<?, DocumentDbPersistentProperty> mappingContext) {
|
||||
public ReactiveCosmosQueryCreator(PartTree tree, ReactiveCosmosParameterAccessor accessor,
|
||||
MappingContext<?, CosmosPersistentProperty> mappingContext) {
|
||||
super(tree, accessor);
|
||||
|
||||
this.mappingContext = mappingContext;
|
||||
|
@ -38,8 +38,8 @@ public class DocumentDbQueryCreator extends AbstractQueryCreator<DocumentQuery,
|
|||
String subject = mappingContext.getPersistentPropertyPath(part.getProperty()).toDotPath();
|
||||
final Class<?> domainClass = part.getProperty().getOwningType().getType();
|
||||
|
||||
@SuppressWarnings("unchecked") final DocumentDbEntityInformation information =
|
||||
new DocumentDbEntityInformation(domainClass);
|
||||
@SuppressWarnings("unchecked") final CosmosEntityInformation information =
|
||||
new CosmosEntityInformation(domainClass);
|
||||
|
||||
if (information.getIdField().getName().equals(subject)) {
|
||||
subject = Constants.ID_PROPERTY_NAME;
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
|
||||
public interface ReactiveCosmosQueryExecution {
|
||||
Object execute(DocumentQuery query, Class<?> type, String collection);
|
||||
|
||||
final class CollectionExecution implements ReactiveCosmosQueryExecution {
|
||||
|
||||
private final ReactiveCosmosOperations operations;
|
||||
|
||||
public CollectionExecution(ReactiveCosmosOperations operations) {
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(DocumentQuery query, Class<?> type, String collection) {
|
||||
return operations.getContainerName(type);
|
||||
}
|
||||
}
|
||||
|
||||
final class MultiEntityExecution implements ReactiveCosmosQueryExecution {
|
||||
|
||||
private final ReactiveCosmosOperations operations;
|
||||
|
||||
public MultiEntityExecution(ReactiveCosmosOperations operations) {
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(DocumentQuery query, Class<?> type, String collection) {
|
||||
return operations.find(query, type, collection);
|
||||
}
|
||||
}
|
||||
|
||||
final class ExistsExecution implements ReactiveCosmosQueryExecution {
|
||||
|
||||
private final ReactiveCosmosOperations operations;
|
||||
|
||||
public ExistsExecution(ReactiveCosmosOperations operations) {
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(DocumentQuery query, Class<?> type, String collection) {
|
||||
return operations.exists(query, type, collection);
|
||||
}
|
||||
}
|
||||
|
||||
final class DeleteExecution implements ReactiveCosmosQueryExecution {
|
||||
|
||||
private final ReactiveCosmosOperations operations;
|
||||
|
||||
public DeleteExecution(ReactiveCosmosOperations operations) {
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(DocumentQuery query, Class<?> type, String collection) {
|
||||
return operations.delete(query, type, collection);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.EntityMetadata;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ReactiveCosmosQueryMethod extends QueryMethod {
|
||||
|
||||
private ReactiveCosmosEntityMetadata<?> metadata;
|
||||
|
||||
public ReactiveCosmosQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
|
||||
super(method, metadata, factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public EntityMetadata<?> getEntityInformation() {
|
||||
final Class<Object> domainClass = (Class<Object>) getDomainClass();
|
||||
final CosmosEntityInformation entityInformation =
|
||||
new CosmosEntityInformation<Object, String>(domainClass);
|
||||
|
||||
this.metadata = new SimpleReactiveCosmosEntityMetadata<Object>(domainClass, entityInformation);
|
||||
return this.metadata;
|
||||
}
|
||||
}
|
|
@ -5,15 +5,15 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public class SimpleDocumentDbEntityMetadata<T> implements DocumentDbEntityMetadata<T> {
|
||||
public class SimpleCosmosEntityMetadata<T> implements CosmosEntityMetadata<T> {
|
||||
|
||||
private final Class<T> type;
|
||||
private final DocumentDbEntityInformation<T, String> entityInformation;
|
||||
private final CosmosEntityInformation<T, String> entityInformation;
|
||||
|
||||
public SimpleDocumentDbEntityMetadata(Class<T> type, DocumentDbEntityInformation<T, String> entityInformation) {
|
||||
public SimpleCosmosEntityMetadata(Class<T> type, CosmosEntityInformation<T, String> entityInformation) {
|
||||
Assert.notNull(type, "type must not be null!");
|
||||
Assert.notNull(entityInformation, "entityInformation must not be null!");
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.query;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public class SimpleReactiveCosmosEntityMetadata<T> implements ReactiveCosmosEntityMetadata<T> {
|
||||
|
||||
private final Class<T> type;
|
||||
private final CosmosEntityInformation<T, String> entityInformation;
|
||||
|
||||
public SimpleReactiveCosmosEntityMetadata(Class<T> type, CosmosEntityInformation<T,
|
||||
String> entityInformation) {
|
||||
Assert.notNull(type, "type must not be null!");
|
||||
Assert.notNull(entityInformation, "entityInformation must not be null!");
|
||||
|
||||
this.type = type;
|
||||
this.entityInformation = entityInformation;
|
||||
}
|
||||
|
||||
public Class<T> getJavaType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getCollectionName() {
|
||||
return entityInformation.getCollectionName();
|
||||
}
|
||||
}
|
|
@ -6,16 +6,17 @@
|
|||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.support;
|
||||
|
||||
import com.microsoft.azure.documentdb.ExcludedPath;
|
||||
import com.microsoft.azure.documentdb.IncludedPath;
|
||||
import com.microsoft.azure.documentdb.IndexingMode;
|
||||
import com.microsoft.azure.documentdb.IndexingPolicy;
|
||||
import com.azure.data.cosmos.ExcludedPath;
|
||||
import com.azure.data.cosmos.IncludedPath;
|
||||
import com.azure.data.cosmos.IndexingMode;
|
||||
import com.azure.data.cosmos.IndexingPolicy;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.Constants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey;
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Version;
|
||||
import org.springframework.data.repository.core.support.AbstractEntityInformation;
|
||||
|
@ -26,11 +27,10 @@ import static com.microsoft.azure.spring.data.cosmosdb.common.ExpressionResolver
|
|||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class DocumentDbEntityInformation<T, ID> extends AbstractEntityInformation<T, ID> {
|
||||
public class CosmosEntityInformation<T, ID> extends AbstractEntityInformation<T, ID> {
|
||||
|
||||
private static final String ETAG = "_etag";
|
||||
private Field id;
|
||||
|
@ -41,7 +41,7 @@ public class DocumentDbEntityInformation<T, ID> extends AbstractEntityInformatio
|
|||
private IndexingPolicy indexingPolicy;
|
||||
private boolean isVersioned;
|
||||
|
||||
public DocumentDbEntityInformation(Class<T> domainClass) {
|
||||
public CosmosEntityInformation(Class<T> domainClass) {
|
||||
super(domainClass);
|
||||
|
||||
this.id = getIdField(domainClass);
|
||||
|
@ -110,10 +110,10 @@ public class DocumentDbEntityInformation<T, ID> extends AbstractEntityInformatio
|
|||
private IndexingPolicy getIndexingPolicy(Class<?> domainClass) {
|
||||
final IndexingPolicy policy = new IndexingPolicy();
|
||||
|
||||
policy.setAutomatic(this.getIndexingPolicyAutomatic(domainClass));
|
||||
policy.setIndexingMode(this.getIndexingPolicyMode(domainClass));
|
||||
policy.automatic(this.getIndexingPolicyAutomatic(domainClass));
|
||||
policy.indexingMode(this.getIndexingPolicyMode(domainClass));
|
||||
policy.setIncludedPaths(this.getIndexingPolicyIncludePaths(domainClass));
|
||||
policy.setExcludedPaths(this.getIndexingPolicyExcludePaths(domainClass));
|
||||
policy.excludedPaths(this.getIndexingPolicyExcludePaths(domainClass));
|
||||
|
||||
return policy;
|
||||
}
|
||||
|
@ -214,8 +214,8 @@ public class DocumentDbEntityInformation<T, ID> extends AbstractEntityInformatio
|
|||
return mode;
|
||||
}
|
||||
|
||||
private Collection<IncludedPath> getIndexingPolicyIncludePaths(Class<?> domainClass) {
|
||||
final Collection<IncludedPath> pathsCollection = new ArrayList<>();
|
||||
private List<IncludedPath> getIndexingPolicyIncludePaths(Class<?> domainClass) {
|
||||
final List<IncludedPath> pathArrayList = new ArrayList<>();
|
||||
final DocumentIndexingPolicy annotation = domainClass.getAnnotation(DocumentIndexingPolicy.class);
|
||||
|
||||
if (annotation == null || annotation.includePaths() == null || annotation.includePaths().length == 0) {
|
||||
|
@ -225,27 +225,27 @@ public class DocumentDbEntityInformation<T, ID> extends AbstractEntityInformatio
|
|||
final String[] rawPaths = annotation.includePaths();
|
||||
|
||||
for (final String path : rawPaths) {
|
||||
pathsCollection.add(new IncludedPath(path));
|
||||
pathArrayList.add(new IncludedPath(path));
|
||||
}
|
||||
|
||||
return pathsCollection;
|
||||
return pathArrayList;
|
||||
}
|
||||
|
||||
private Collection<ExcludedPath> getIndexingPolicyExcludePaths(Class<?> domainClass) {
|
||||
final Collection<ExcludedPath> pathsCollection = new ArrayList<>();
|
||||
private List<ExcludedPath> getIndexingPolicyExcludePaths(Class<?> domainClass) {
|
||||
final List<ExcludedPath> pathArrayList = new ArrayList<>();
|
||||
final DocumentIndexingPolicy annotation = domainClass.getAnnotation(DocumentIndexingPolicy.class);
|
||||
|
||||
if (annotation == null || annotation.excludePaths() == null || annotation.excludePaths().length == 0) {
|
||||
if (annotation == null || annotation.excludePaths().length == 0) {
|
||||
return null; // Align the default value of IndexingPolicy
|
||||
}
|
||||
|
||||
final String[] rawPaths = annotation.excludePaths();
|
||||
|
||||
for (final String path : rawPaths) {
|
||||
pathsCollection.add(new ExcludedPath(path));
|
||||
final JSONObject obj = new JSONObject(path);
|
||||
pathArrayList.add(new ExcludedPath().path(obj.get("path").toString()));
|
||||
}
|
||||
|
||||
return pathsCollection;
|
||||
return pathArrayList;
|
||||
}
|
||||
|
||||
private boolean getIsVersioned(Class<T> domainClass) {
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.support;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.query.DocumentDbQueryMethod;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.query.PartTreeDocumentDbQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.query.CosmosQueryMethod;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.query.PartTreeCosmosQuery;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
|
@ -26,19 +26,19 @@ import java.lang.reflect.Method;
|
|||
import java.util.Optional;
|
||||
|
||||
|
||||
public class DocumentDbRepositoryFactory extends RepositoryFactorySupport {
|
||||
public class CosmosRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
private final DocumentDbOperations dbOperations;
|
||||
private final CosmosOperations cosmosOperations;
|
||||
|
||||
public DocumentDbRepositoryFactory(DocumentDbOperations dbOperations, ApplicationContext applicationContext) {
|
||||
this.dbOperations = dbOperations;
|
||||
public CosmosRepositoryFactory(CosmosOperations cosmosOperations, ApplicationContext applicationContext) {
|
||||
this.cosmosOperations = cosmosOperations;
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
|
||||
return SimpleDocumentDbRepository.class;
|
||||
return SimpleCosmosRepository.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,31 +49,31 @@ public class DocumentDbRepositoryFactory extends RepositoryFactorySupport {
|
|||
|
||||
@Override
|
||||
public <T, ID> EntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
return new DocumentDbEntityInformation<>(domainClass);
|
||||
return new CosmosEntityInformation<>(domainClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(
|
||||
QueryLookupStrategy.Key key, QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
return Optional.of(new DocumentDbQueryLookupStrategy(dbOperations, evaluationContextProvider));
|
||||
return Optional.of(new CosmosDbQueryLookupStrategy(cosmosOperations, evaluationContextProvider));
|
||||
}
|
||||
|
||||
private static class DocumentDbQueryLookupStrategy implements QueryLookupStrategy {
|
||||
private final DocumentDbOperations dbOperations;
|
||||
private static class CosmosDbQueryLookupStrategy implements QueryLookupStrategy {
|
||||
private final CosmosOperations dbOperations;
|
||||
|
||||
public DocumentDbQueryLookupStrategy(
|
||||
DocumentDbOperations operations, QueryMethodEvaluationContextProvider provider) {
|
||||
public CosmosDbQueryLookupStrategy(
|
||||
CosmosOperations operations, QueryMethodEvaluationContextProvider provider) {
|
||||
this.dbOperations = operations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata,
|
||||
ProjectionFactory factory, NamedQueries namedQueries) {
|
||||
final DocumentDbQueryMethod queryMethod = new DocumentDbQueryMethod(method, metadata, factory);
|
||||
final CosmosQueryMethod queryMethod = new CosmosQueryMethod(method, metadata, factory);
|
||||
|
||||
Assert.notNull(queryMethod, "queryMethod must not be null!");
|
||||
Assert.notNull(dbOperations, "dbOperations must not be null!");
|
||||
return new PartTreeDocumentDbQuery(queryMethod, dbOperations);
|
||||
return new PartTreeCosmosQuery(queryMethod, dbOperations);
|
||||
|
||||
}
|
||||
}
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.support;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
@ -20,21 +20,21 @@ import org.springframework.data.repository.core.support.RepositoryFactorySupport
|
|||
import java.io.Serializable;
|
||||
|
||||
|
||||
public class DocumentDbRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
|
||||
public class CosmosRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
|
||||
extends RepositoryFactoryBeanSupport<T, S, ID>
|
||||
implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
private DocumentDbOperations operations;
|
||||
private CosmosOperations operations;
|
||||
private boolean mappingContextConfigured = false;
|
||||
|
||||
|
||||
public DocumentDbRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
|
||||
public CosmosRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
|
||||
super(repositoryInterface);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setDocumentDbOperations(DocumentDbOperations operations) {
|
||||
public void setCosmosOperations(CosmosOperations operations) {
|
||||
this.operations = operations;
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ public class DocumentDbRepositoryFactoryBean<T extends Repository<S, ID>, S, ID
|
|||
}
|
||||
|
||||
protected RepositoryFactorySupport getFactoryInstance(ApplicationContext applicationContext) {
|
||||
return new DocumentDbRepositoryFactory(operations, applicationContext);
|
||||
return new CosmosRepositoryFactory(operations, applicationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,7 +66,7 @@ public class DocumentDbRepositoryFactoryBean<T extends Repository<S, ID>, S, ID
|
|||
if (operations != null) {
|
||||
setMappingContext(operations.getConverter().getMappingContext());
|
||||
} else {
|
||||
setMappingContext(new DocumentDbMappingContext());
|
||||
setMappingContext(new CosmosMappingContext());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,34 +5,47 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.support;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.query.PartTreeReactiveCosmosQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.query.ReactiveCosmosQueryMethod;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
import org.springframework.data.repository.core.RepositoryInformation;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.ReactiveRepositoryFactorySupport;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ReactiveCosmosRepositoryFactory extends ReactiveRepositoryFactorySupport {
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
private final ReactiveCosmosOperations cosmosOperations;
|
||||
|
||||
public ReactiveCosmosRepositoryFactory(ApplicationContext applicationContext) {
|
||||
public ReactiveCosmosRepositoryFactory(ReactiveCosmosOperations cosmosOperations,
|
||||
ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
this.cosmosOperations = cosmosOperations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, ID> EntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
|
||||
return new DocumentDbEntityInformation<>(domainClass);
|
||||
return new CosmosEntityInformation<>(domainClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getTargetRepository(RepositoryInformation information) {
|
||||
final EntityInformation<?, Serializable> entityInformation = getEntityInformation(information.getDomainType());
|
||||
return getTargetRepositoryViaReflection(information, entityInformation, this.applicationContext);
|
||||
final EntityInformation<?, Serializable> entityInformation =
|
||||
getEntityInformation(information.getDomainType());
|
||||
return getTargetRepositoryViaReflection(information, entityInformation,
|
||||
this.applicationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -42,8 +55,31 @@ public class ReactiveCosmosRepositoryFactory extends ReactiveRepositoryFactorySu
|
|||
|
||||
@Override
|
||||
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(
|
||||
QueryLookupStrategy.Key key, QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
return super.getQueryLookupStrategy(key, evaluationContextProvider);
|
||||
QueryLookupStrategy.Key key,
|
||||
QueryMethodEvaluationContextProvider evaluationContextProvider) {
|
||||
return Optional.of(new ReactiveCosmosQueryLookupStrategy(cosmosOperations,
|
||||
evaluationContextProvider));
|
||||
}
|
||||
|
||||
private static class ReactiveCosmosQueryLookupStrategy implements QueryLookupStrategy {
|
||||
private final ReactiveCosmosOperations cosmosOperations;
|
||||
|
||||
public ReactiveCosmosQueryLookupStrategy(
|
||||
ReactiveCosmosOperations operations, QueryMethodEvaluationContextProvider provider) {
|
||||
this.cosmosOperations = operations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata,
|
||||
ProjectionFactory factory, NamedQueries namedQueries) {
|
||||
final ReactiveCosmosQueryMethod queryMethod = new ReactiveCosmosQueryMethod(method,
|
||||
metadata, factory);
|
||||
|
||||
Assert.notNull(queryMethod, "queryMethod must not be null!");
|
||||
Assert.notNull(cosmosOperations, "dbOperations must not be null!");
|
||||
return new PartTreeReactiveCosmosQuery(queryMethod, cosmosOperations);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.support;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
|
@ -15,33 +18,55 @@ import org.springframework.data.repository.core.support.RepositoryFactorySupport
|
|||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class ReactiveCosmosRepositoryFactoryBean<T extends Repository<S, K>, S, K extends Serializable>
|
||||
extends RepositoryFactoryBeanSupport<T, S, K>
|
||||
implements ApplicationContextAware {
|
||||
public class ReactiveCosmosRepositoryFactoryBean<T extends Repository<S, K>, S,
|
||||
K extends Serializable>
|
||||
extends RepositoryFactoryBeanSupport<T, S, K>
|
||||
implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
private ReactiveCosmosOperations cosmosOperations;
|
||||
private boolean mappingContextConfigured = false;
|
||||
|
||||
public ReactiveCosmosRepositoryFactoryBean(Class<? extends T> repositoryInterface) {
|
||||
super(repositoryInterface);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void setReactiveCosmosOperations(ReactiveCosmosOperations operations) {
|
||||
this.cosmosOperations = operations;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RepositoryFactorySupport createRepositoryFactory() {
|
||||
protected final RepositoryFactorySupport createRepositoryFactory() {
|
||||
return getFactoryInstance(applicationContext);
|
||||
}
|
||||
|
||||
protected RepositoryFactorySupport getFactoryInstance(ApplicationContext applicationContext) {
|
||||
return new ReactiveCosmosRepositoryFactory(cosmosOperations, applicationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
protected RepositoryFactorySupport getFactoryInstance(ApplicationContext applicationContext) {
|
||||
return new ReactiveCosmosRepositoryFactory(applicationContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setMappingContext(MappingContext<?, ?> mappingContext) {
|
||||
super.setMappingContext(mappingContext);
|
||||
this.mappingContextConfigured = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
super.afterPropertiesSet();
|
||||
|
||||
if (!this.mappingContextConfigured) {
|
||||
if (cosmosOperations != null) {
|
||||
setMappingContext(cosmosOperations.getConverter().getMappingContext());
|
||||
} else {
|
||||
setMappingContext(new CosmosMappingContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,14 +6,13 @@
|
|||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.support;
|
||||
|
||||
|
||||
import com.microsoft.azure.documentdb.DocumentCollection;
|
||||
import com.microsoft.azure.documentdb.PartitionKey;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
|
||||
import com.azure.data.cosmos.CosmosContainerProperties;
|
||||
import com.azure.data.cosmos.PartitionKey;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
@ -27,29 +26,28 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
public class SimpleDocumentDbRepository<T, ID extends Serializable> implements DocumentDbRepository<T, ID> {
|
||||
public class SimpleCosmosRepository<T, ID extends Serializable> implements CosmosRepository<T, ID> {
|
||||
|
||||
private final DocumentDbOperations operation;
|
||||
private final DocumentDbEntityInformation<T, ID> information;
|
||||
private final DocumentCollection collection;
|
||||
private final CosmosOperations operation;
|
||||
private final CosmosEntityInformation<T, ID> information;
|
||||
|
||||
public SimpleDocumentDbRepository(DocumentDbEntityInformation<T, ID> metadata,
|
||||
ApplicationContext applicationContext) {
|
||||
this.operation = applicationContext.getBean(DocumentDbOperations.class);
|
||||
public SimpleCosmosRepository(CosmosEntityInformation<T, ID> metadata,
|
||||
ApplicationContext applicationContext) {
|
||||
this.operation = applicationContext.getBean(CosmosOperations.class);
|
||||
this.information = metadata;
|
||||
|
||||
collection = createCollectionIfNotExists();
|
||||
createCollectionIfNotExists();
|
||||
}
|
||||
|
||||
public SimpleDocumentDbRepository(DocumentDbEntityInformation<T, ID> metadata,
|
||||
DocumentDbOperations dbOperations) {
|
||||
public SimpleCosmosRepository(CosmosEntityInformation<T, ID> metadata,
|
||||
CosmosOperations dbOperations) {
|
||||
this.operation = dbOperations;
|
||||
this.information = metadata;
|
||||
|
||||
collection = createCollectionIfNotExists();
|
||||
createCollectionIfNotExists();
|
||||
}
|
||||
|
||||
private DocumentCollection createCollectionIfNotExists() {
|
||||
private CosmosContainerProperties createCollectionIfNotExists() {
|
||||
return this.operation.createCollectionIfNotExists(this.information);
|
||||
}
|
||||
|
||||
|
@ -79,7 +77,7 @@ public class SimpleDocumentDbRepository<T, ID extends Serializable> implements D
|
|||
|
||||
private PartitionKey createKey(String partitionKeyValue) {
|
||||
if (StringUtils.isEmpty(partitionKeyValue)) {
|
||||
return null;
|
||||
return PartitionKey.None;
|
||||
}
|
||||
|
||||
return new PartitionKey(partitionKeyValue);
|
||||
|
@ -141,12 +139,6 @@ public class SimpleDocumentDbRepository<T, ID extends Serializable> implements D
|
|||
return Optional.ofNullable(operation.findById(information.getCollectionName(), id, information.getJavaType()));
|
||||
}
|
||||
|
||||
/**
|
||||
* find one entity per id without partitions
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Optional<T> findById(ID id, PartitionKey partitionKey) {
|
||||
Assert.notNull(id, "id must not be null");
|
||||
|
@ -158,7 +150,6 @@ public class SimpleDocumentDbRepository<T, ID extends Serializable> implements D
|
|||
return Optional.ofNullable(operation.findById(id, information.getJavaType(), partitionKey));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* return count of documents in one collection without partitions
|
||||
*
|
|
@ -5,14 +5,15 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository.support;
|
||||
|
||||
import com.azure.data.cosmos.CosmosContainerResponse;
|
||||
import com.azure.data.cosmos.PartitionKey;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.ReactiveCosmosOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.ReactiveCosmosRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
|
@ -22,19 +23,40 @@ import reactor.core.publisher.Mono;
|
|||
|
||||
import java.io.Serializable;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class SimpleReactiveCosmosRepository<T, K extends Serializable> implements ReactiveCosmosRepository<T, K> {
|
||||
|
||||
public final DocumentDbEntityInformation<T, K> entityInformation;
|
||||
public final ReactiveCosmosOperations cosmosOperations;
|
||||
private final CosmosEntityInformation<T, K> entityInformation;
|
||||
private final ReactiveCosmosOperations cosmosOperations;
|
||||
|
||||
public SimpleReactiveCosmosRepository(CosmosEntityInformation<T, K> metadata,
|
||||
ApplicationContext applicationContext) {
|
||||
this.cosmosOperations = applicationContext.getBean(ReactiveCosmosOperations.class);
|
||||
this.entityInformation = metadata;
|
||||
|
||||
createCollectionIfNotExists();
|
||||
}
|
||||
|
||||
public SimpleReactiveCosmosRepository(CosmosEntityInformation<T, K> metadata,
|
||||
ReactiveCosmosOperations reactiveCosmosOperations) {
|
||||
this.cosmosOperations = reactiveCosmosOperations;
|
||||
this.entityInformation = metadata;
|
||||
|
||||
createCollectionIfNotExists();
|
||||
}
|
||||
|
||||
private CosmosContainerResponse createCollectionIfNotExists() {
|
||||
return this.cosmosOperations.createCollectionIfNotExists(this.entityInformation).block();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<T> findAll(Sort sort) {
|
||||
Assert.notNull(sort, "Sort must not be null!");
|
||||
|
||||
final DocumentQuery query = new DocumentQuery(Criteria.getInstance(CriteriaType.ALL)).with(sort);
|
||||
final DocumentQuery query =
|
||||
new DocumentQuery(Criteria.getInstance(CriteriaType.ALL)).with(sort);
|
||||
|
||||
return cosmosOperations.find(query, entityInformation.getJavaType(), entityInformation.getCollectionName());
|
||||
return cosmosOperations.find(query, entityInformation.getJavaType(),
|
||||
entityInformation.getCollectionName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -44,11 +66,11 @@ public class SimpleReactiveCosmosRepository<T, K extends Serializable> implement
|
|||
|
||||
if (entityInformation.isNew(entity)) {
|
||||
return cosmosOperations.insert(entityInformation.getCollectionName(),
|
||||
entity,
|
||||
createKey(entityInformation.getPartitionKeyFieldValue(entity)));
|
||||
entity,
|
||||
createKey(entityInformation.getPartitionKeyFieldValue(entity)));
|
||||
} else {
|
||||
return cosmosOperations.upsert(entityInformation.getCollectionName(),
|
||||
entity, createKey(entityInformation.getPartitionKeyFieldValue(entity)));
|
||||
entity, createKey(entityInformation.getPartitionKeyFieldValue(entity)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,7 +93,8 @@ public class SimpleReactiveCosmosRepository<T, K extends Serializable> implement
|
|||
@Override
|
||||
public Mono<T> findById(K id) {
|
||||
Assert.notNull(id, "The given id must not be null!");
|
||||
return cosmosOperations.findById(entityInformation.getCollectionName(), id, entityInformation.getJavaType());
|
||||
return cosmosOperations.findById(entityInformation.getCollectionName(), id,
|
||||
entityInformation.getJavaType());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -79,8 +102,8 @@ public class SimpleReactiveCosmosRepository<T, K extends Serializable> implement
|
|||
Assert.notNull(publisher, "The given id must not be null!");
|
||||
|
||||
return Mono.from(publisher).flatMap(
|
||||
id -> cosmosOperations.findById(entityInformation.getCollectionName(),
|
||||
id, entityInformation.getJavaType()));
|
||||
id -> cosmosOperations.findById(entityInformation.getCollectionName(),
|
||||
id, entityInformation.getJavaType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -95,20 +118,22 @@ public class SimpleReactiveCosmosRepository<T, K extends Serializable> implement
|
|||
Assert.notNull(id, "The given id must not be null!");
|
||||
|
||||
return cosmosOperations.existsById(id, entityInformation.getJavaType(),
|
||||
entityInformation.getCollectionName());
|
||||
entityInformation.getCollectionName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Boolean> existsById(Publisher<K> publisher) {
|
||||
Assert.notNull(publisher, "The given id must not be null!");
|
||||
|
||||
return Mono.from(publisher).flatMap(id -> cosmosOperations.existsById(id, entityInformation.getJavaType(),
|
||||
entityInformation.getCollectionName()));
|
||||
return Mono.from(publisher).flatMap(id -> cosmosOperations.existsById(id,
|
||||
entityInformation.getJavaType(),
|
||||
entityInformation.getCollectionName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<T> findAll() {
|
||||
return cosmosOperations.findAll(entityInformation.getCollectionName(), entityInformation.getJavaType());
|
||||
return cosmosOperations.findAll(entityInformation.getCollectionName(),
|
||||
entityInformation.getJavaType());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -140,7 +165,7 @@ public class SimpleReactiveCosmosRepository<T, K extends Serializable> implement
|
|||
Assert.notNull(publisher, "Id must not be null!");
|
||||
|
||||
return Mono.from(publisher).flatMap(id -> cosmosOperations.deleteById(entityInformation.getCollectionName(),
|
||||
id, null)).then();
|
||||
id, null)).then();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -149,8 +174,8 @@ public class SimpleReactiveCosmosRepository<T, K extends Serializable> implement
|
|||
|
||||
final Object id = entityInformation.getId(entity);
|
||||
return cosmosOperations.deleteById(entityInformation.getCollectionName(),
|
||||
id,
|
||||
createKey(entityInformation.getPartitionKeyFieldValue(entity)));
|
||||
id,
|
||||
createKey(entityInformation.getPartitionKeyFieldValue(entity)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -166,15 +191,15 @@ public class SimpleReactiveCosmosRepository<T, K extends Serializable> implement
|
|||
Assert.notNull(entityStream, "The given Publisher of entities must not be null!");
|
||||
|
||||
return Flux.from(entityStream)//
|
||||
.map(entityInformation::getRequiredId)//
|
||||
.flatMap(this::deleteById)//
|
||||
.then();
|
||||
.map(entityInformation::getRequiredId)//
|
||||
.flatMap(this::deleteById)//
|
||||
.then();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> deleteAll() {
|
||||
return cosmosOperations.deleteAll(entityInformation.getCollectionName(),
|
||||
entityInformation.getPartitionKeyFieldName());
|
||||
entityInformation.getPartitionKeyFieldName());
|
||||
}
|
||||
|
||||
private PartitionKey createKey(String partitionKeyValue) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
org.springframework.data.repository.core.support.RepositoryFactorySupport=com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbRepositoryFactory
|
||||
org.springframework.data.repository.core.support.RepositoryFactorySupport=com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosRepositoryFactory
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_FAKE_CONNECTION_STRING;
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_FAKE_HOST;
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_FAKE_KEY;
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.COSMOSDB_INVALID_FAKE_CONNECTION_STRING;
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.DB_NAME;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@PropertySource(value = {"classpath:application.properties"})
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class CosmosDbFactoryTestIT {
|
||||
|
||||
@Value("${cosmosdb.uri:}")
|
||||
private String cosmosDbUri;
|
||||
|
||||
@Value("${cosmosdb.key:}")
|
||||
private String cosmosDbKey;
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testEmptyKey() {
|
||||
final CosmosDBConfig dbConfig = CosmosDBConfig.builder(COSMOSDB_FAKE_HOST, "", DB_NAME).build();
|
||||
new CosmosDbFactory(dbConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidEndpoint() {
|
||||
final CosmosDBConfig dbConfig =
|
||||
CosmosDBConfig.builder(COSMOSDB_FAKE_HOST, COSMOSDB_FAKE_KEY, DB_NAME).build();
|
||||
final CosmosDbFactory factory = new CosmosDbFactory(dbConfig);
|
||||
|
||||
assertThat(factory).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectWithConnectionString() {
|
||||
final CosmosDBConfig dbConfig =
|
||||
CosmosDBConfig.builder(COSMOSDB_FAKE_CONNECTION_STRING, DB_NAME).build();
|
||||
final CosmosDbFactory factory = new CosmosDbFactory(dbConfig);
|
||||
|
||||
assertThat(factory).isNotNull();
|
||||
}
|
||||
|
||||
@Test(expected = CosmosDBAccessException.class)
|
||||
public void testInvalidConnectionString() {
|
||||
CosmosDBConfig.builder(COSMOSDB_INVALID_FAKE_CONNECTION_STRING, DB_NAME).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionPolicyUserAgentKept() {
|
||||
final CosmosDBConfig dbConfig =
|
||||
CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, DB_NAME).build();
|
||||
final CosmosDbFactory factory = new CosmosDbFactory(dbConfig);
|
||||
factory.getCosmosClient();
|
||||
|
||||
final String uaSuffix = factory.getConfig().getConnectionPolicy().userAgentSuffix();
|
||||
assertThat(uaSuffix).contains("spring-data");
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.DocumentDBAccessException;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class DocumentDbFactoryUnitTest {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testEmptyKey() {
|
||||
final DocumentDBConfig dbConfig = DocumentDBConfig.builder(DOCUMENTDB_FAKE_HOST, "", DB_NAME).build();
|
||||
new DocumentDbFactory(dbConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidEndpoint() {
|
||||
final DocumentDBConfig dbConfig =
|
||||
DocumentDBConfig.builder(DOCUMENTDB_FAKE_HOST, DOCUMENTDB_FAKE_KEY, DB_NAME).build();
|
||||
final DocumentDbFactory factory = new DocumentDbFactory(dbConfig);
|
||||
|
||||
assertThat(factory).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectWithConnectionString() {
|
||||
final DocumentDBConfig dbConfig =
|
||||
DocumentDBConfig.builder(DOCUMENTDB_FAKE_CONNECTION_STRING, DB_NAME).build();
|
||||
final DocumentDbFactory factory = new DocumentDbFactory(dbConfig);
|
||||
|
||||
assertThat(factory).isNotNull();
|
||||
}
|
||||
|
||||
@Test(expected = DocumentDBAccessException.class)
|
||||
public void testInvalidConnectionString() {
|
||||
final DocumentDBConfig dbConfig =
|
||||
DocumentDBConfig.builder(DOCUMENTDB_INVALID_FAKE_CONNECTION_STRING, DB_NAME).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnectionPolicyUserAgentKept() {
|
||||
final DocumentDBConfig dbConfig =
|
||||
DocumentDBConfig.builder(DOCUMENTDB_FAKE_HOST, DOCUMENTDB_FAKE_KEY, DB_NAME).build();
|
||||
final DocumentDbFactory factory = new DocumentDbFactory(dbConfig);
|
||||
|
||||
final String uaSuffix = factory.getDocumentClient().getConnectionPolicy().getUserAgentSuffix();
|
||||
assertThat(uaSuffix).contains("spring-data");
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.PropertyLoader;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.BDDMockito;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest(PropertyLoader.class)
|
||||
@PowerMockIgnore({"javax.net.ssl.*", "javax.crypto.*"})
|
||||
public class UserAgentTest {
|
||||
private static final String TEST_VERSION = "1.0.0-FOR-TEST";
|
||||
|
||||
@Test
|
||||
public void testUserAgentSuffixAppended() {
|
||||
PowerMockito.mockStatic(PropertyLoader.class);
|
||||
BDDMockito.given(PropertyLoader.getProjectVersion()).willReturn(TEST_VERSION);
|
||||
|
||||
assertThat(PropertyLoader.getProjectVersion()).isEqualTo(TEST_VERSION);
|
||||
|
||||
final DocumentDBConfig dbConfig = DocumentDBConfig.builder("https://uri", "key", TestConstants.DB_NAME).build();
|
||||
final DocumentDbFactory factory = new DocumentDbFactory(dbConfig);
|
||||
assertThat(factory.getDocumentClient().getConnectionPolicy().getUserAgentSuffix()).contains(TEST_VERSION);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See LICENSE in the project root for
|
||||
* license information.
|
||||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.PropertyLoader;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@Ignore("Cannot use fake uri and key with CosmosDbFactory as it tries the connection on new creation." +
|
||||
"At the same time, cannot use mockito with real values, because it won't prepare PropertyLoader class for mocking")
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest(PropertyLoader.class)
|
||||
@PropertySource(value = {"classpath:application.properties"})
|
||||
public class UserAgentTestIT {
|
||||
|
||||
private static final String TEST_VERSION = "1.0.0-FOR-TEST";
|
||||
|
||||
@Test
|
||||
public void testUserAgentSuffixAppended() {
|
||||
PowerMockito.mockStatic(PropertyLoader.class);
|
||||
Mockito.doReturn(TEST_VERSION).when(PropertyLoader.getProjectVersion());
|
||||
final CosmosDBConfig dbConfig = CosmosDBConfig.builder(TestConstants.COSMOSDB_FAKE_HOST,
|
||||
TestConstants.COSMOSDB_FAKE_KEY, TestConstants.DB_NAME).build();
|
||||
final CosmosDbFactory factory = new CosmosDbFactory(dbConfig);
|
||||
factory.getCosmosClient();
|
||||
assertThat(factory.getConfig().getConnectionPolicy().userAgentSuffix()).contains(TEST_VERSION);
|
||||
}
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.common;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
@ -17,21 +17,21 @@ public class PageTestUtils {
|
|||
public static void validateLastPage(Page page, int pageSize) {
|
||||
final Pageable pageable = page.getPageable();
|
||||
|
||||
assertThat(pageable).isInstanceOf(DocumentDbPageRequest.class);
|
||||
assertTrue(continuationTokenIsNull((DocumentDbPageRequest) pageable));
|
||||
assertThat(pageable).isInstanceOf(CosmosPageRequest.class);
|
||||
assertTrue(continuationTokenIsNull((CosmosPageRequest) pageable));
|
||||
assertThat(pageable.getPageSize()).isEqualTo(pageSize);
|
||||
}
|
||||
|
||||
public static void validateNonLastPage(Page page, int pageSize) {
|
||||
final Pageable pageable = page.getPageable();
|
||||
|
||||
assertThat(pageable).isInstanceOf(DocumentDbPageRequest.class);
|
||||
assertThat(((DocumentDbPageRequest) pageable).getRequestContinuation()).isNotNull();
|
||||
assertThat(((DocumentDbPageRequest) pageable).getRequestContinuation()).isNotBlank();
|
||||
assertThat(pageable).isInstanceOf(CosmosPageRequest.class);
|
||||
assertThat(((CosmosPageRequest) pageable).getRequestContinuation()).isNotNull();
|
||||
assertThat(((CosmosPageRequest) pageable).getRequestContinuation()).isNotBlank();
|
||||
assertThat(pageable.getPageSize()).isEqualTo(pageSize);
|
||||
}
|
||||
|
||||
private static boolean continuationTokenIsNull(DocumentDbPageRequest pageRequest) {
|
||||
private static boolean continuationTokenIsNull(CosmosPageRequest pageRequest) {
|
||||
final String tokenJson = pageRequest.getRequestContinuation();
|
||||
if (tokenJson == null) {
|
||||
return true;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.common;
|
||||
|
||||
import com.microsoft.azure.documentdb.IndexingMode;
|
||||
import com.azure.data.cosmos.IndexingMode;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.domain.Address;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
@ -29,7 +29,7 @@ public class TestConstants {
|
|||
public static final String DEFAULT_COLLECTION_NAME = "Person";
|
||||
public static final int DEFAULT_REQUEST_UNIT = 4000;
|
||||
public static final boolean DEFAULT_INDEXINGPOLICY_AUTOMATIC = true;
|
||||
public static final IndexingMode DEFAULT_INDEXINGPOLICY_MODE = IndexingMode.Consistent;
|
||||
public static final IndexingMode DEFAULT_INDEXINGPOLICY_MODE = IndexingMode.CONSISTENT;
|
||||
public static final String[] DEFAULT_EXCLUDEDPATHS = {};
|
||||
public static final String[] DEFAULT_INCLUDEDPATHS = {
|
||||
"{\"path\":\"/*\",\"indexes\":[" +
|
||||
|
@ -43,7 +43,7 @@ public class TestConstants {
|
|||
public static final int TIME_TO_LIVE = 5;
|
||||
public static final String REQUEST_UNIT_STRING = "1000";
|
||||
public static final boolean INDEXINGPOLICY_AUTOMATIC = false;
|
||||
public static final IndexingMode INDEXINGPOLICY_MODE = IndexingMode.Lazy;
|
||||
public static final IndexingMode INDEXINGPOLICY_MODE = IndexingMode.LAZY;
|
||||
public static final String INCLUDEDPATH_0 = "{\"path\":\"/*\",\"indexes\":[" +
|
||||
"{\"kind\":\"Range\",\"dataType\":\"Number\",\"precision\":2}," +
|
||||
"{\"kind\":\"Hash\",\"dataType\":\"String\",\"precision\":2}," +
|
||||
|
@ -130,11 +130,11 @@ public class TestConstants {
|
|||
public static final String CRITERIA_FAKE_KEY = "CriteriaFakeKey";
|
||||
public static final String CRITERIA_OBJECT = "CriteriaTestObject";
|
||||
|
||||
public static final String DOCUMENTDB_FAKE_HOST = "https://fakeuri";
|
||||
public static final String DOCUMENTDB_FAKE_KEY = "fakekey";
|
||||
public static final String DOCUMENTDB_FAKE_CONNECTION_STRING =
|
||||
public static final String COSMOSDB_FAKE_HOST = "https://fakeuri";
|
||||
public static final String COSMOSDB_FAKE_KEY = "fakekey";
|
||||
public static final String COSMOSDB_FAKE_CONNECTION_STRING =
|
||||
"AccountEndpoint=https://fakeuri/;AccountKey=fakekey;";
|
||||
public static final String DOCUMENTDB_INVALID_FAKE_CONNECTION_STRING = "invalid connection string";
|
||||
public static final String COSMOSDB_INVALID_FAKE_CONNECTION_STRING = "invalid connection string";
|
||||
|
||||
public static final String PROPERTY_ID = "id";
|
||||
public static final String PROPERTY_FIRST_NAME = "firstName";
|
||||
|
|
|
@ -5,11 +5,9 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.common;
|
||||
|
||||
import com.microsoft.azure.documentdb.JsonSerializable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -23,8 +21,8 @@ public class TestUtils {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static <T extends JsonSerializable> void testIndexingPolicyPathsEquals(Collection<T> policyPaths,
|
||||
String [] pathsExpected) {
|
||||
public static <T> void testIndexingPolicyPathsEquals(List<T> policyPaths,
|
||||
String [] pathsExpected) {
|
||||
if (policyPaths == null) {
|
||||
throw new IllegalStateException("policyPaths should not be null");
|
||||
} else if (pathsExpected == null) {
|
||||
|
@ -38,7 +36,6 @@ public class TestUtils {
|
|||
for (final String path: pathsExpected) {
|
||||
Assert.isTrue(pathIterator.hasNext(), "policy path iterator should have next");
|
||||
final T includedPath = pathIterator.next();
|
||||
|
||||
Assert.isTrue(includedPath.toString().equals(path), "unmatched policy path");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.config;
|
||||
|
||||
import com.azure.data.cosmos.ConsistencyLevel;
|
||||
import com.azure.data.cosmos.CosmosClient;
|
||||
import com.azure.data.cosmos.internal.RequestOptions;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.microsoft.azure.documentdb.ConsistencyLevel;
|
||||
import com.microsoft.azure.documentdb.DocumentClient;
|
||||
import com.microsoft.azure.documentdb.RequestOptions;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.Constants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.DocumentDbFactory;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.ExpressionResolver;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
|
||||
import org.assertj.core.api.Assertions;
|
||||
|
@ -30,7 +30,7 @@ import org.springframework.context.support.AbstractApplicationContext;
|
|||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class AbstractDocumentDbConfigurationIT {
|
||||
public class AbstractCosmosConfigurationIT {
|
||||
private static final String OBJECTMAPPER_BEAN_NAME = Constants.OBJECTMAPPER_BEAN_NAME;
|
||||
|
||||
@Rule
|
||||
|
@ -39,23 +39,23 @@ public class AbstractDocumentDbConfigurationIT {
|
|||
@Test
|
||||
public void containsExpressionResolver() {
|
||||
final AbstractApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
TestDocumentDbConfiguration.class);
|
||||
TestCosmosConfiguration.class);
|
||||
|
||||
assertNotNull(context.getBean(ExpressionResolver.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void containsDocumentDbFactory() {
|
||||
public void containsCosmosDbFactory() {
|
||||
final AbstractApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
TestDocumentDbConfiguration.class);
|
||||
TestCosmosConfiguration.class);
|
||||
|
||||
Assertions.assertThat(context.getBean(DocumentDbFactory.class)).isNotNull();
|
||||
Assertions.assertThat(context.getBean(CosmosDbFactory.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test(expected = NoSuchBeanDefinitionException.class)
|
||||
public void defaultObjectMapperBeanNotExists() {
|
||||
final AbstractApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
TestDocumentDbConfiguration.class);
|
||||
TestCosmosConfiguration.class);
|
||||
|
||||
context.getBean(ObjectMapper.class);
|
||||
}
|
||||
|
@ -73,44 +73,43 @@ public class AbstractDocumentDbConfigurationIT {
|
|||
public void testRequestOptionsConfigurable() {
|
||||
final AbstractApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
RequestOptionsConfiguration.class);
|
||||
final DocumentDbFactory factory = context.getBean(DocumentDbFactory.class);
|
||||
final CosmosDbFactory factory = context.getBean(CosmosDbFactory.class);
|
||||
|
||||
Assertions.assertThat(factory).isNotNull();
|
||||
|
||||
final RequestOptions options = factory.getConfig().getRequestOptions();
|
||||
|
||||
Assertions.assertThat(options).isNotNull();
|
||||
Assertions.assertThat(options.getConsistencyLevel()).isEqualTo(ConsistencyLevel.ConsistentPrefix);
|
||||
Assertions.assertThat(options.getDisableRUPerMinuteUsage()).isTrue();
|
||||
Assertions.assertThat(options.getConsistencyLevel()).isEqualTo(ConsistencyLevel.CONSISTENT_PREFIX);
|
||||
Assertions.assertThat(options.isScriptLoggingEnabled()).isTrue();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@PropertySource(value = {"classpath:application.properties"})
|
||||
static class TestDocumentDbConfiguration extends AbstractDocumentDbConfiguration {
|
||||
static class TestCosmosConfiguration extends AbstractCosmosConfiguration {
|
||||
|
||||
@Value("${cosmosdb.uri:}")
|
||||
private String documentDbUri;
|
||||
private String cosmosDbUri;
|
||||
|
||||
@Value("${cosmosdb.key:}")
|
||||
private String documentDbKey;
|
||||
private String cosmosDbKey;
|
||||
|
||||
@Mock
|
||||
private DocumentClient mockClient;
|
||||
private CosmosClient mockClient;
|
||||
|
||||
@Bean
|
||||
public DocumentDBConfig getConfig() {
|
||||
return DocumentDBConfig.builder(documentDbUri, documentDbKey, TestConstants.DB_NAME).build();
|
||||
public CosmosDBConfig getConfig() {
|
||||
return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, TestConstants.DB_NAME).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocumentClient documentClient(DocumentDBConfig config) {
|
||||
public CosmosClient cosmosClient(CosmosDBConfig config) {
|
||||
return mockClient;
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class ObjectMapperConfiguration extends TestDocumentDbConfiguration {
|
||||
static class ObjectMapperConfiguration extends TestCosmosConfiguration {
|
||||
@Bean(name = OBJECTMAPPER_BEAN_NAME)
|
||||
public ObjectMapper objectMapper() {
|
||||
return new ObjectMapper();
|
||||
|
@ -119,28 +118,27 @@ public class AbstractDocumentDbConfigurationIT {
|
|||
|
||||
@Configuration
|
||||
@PropertySource(value = {"classpath:application.properties"})
|
||||
static class RequestOptionsConfiguration extends AbstractDocumentDbConfiguration {
|
||||
static class RequestOptionsConfiguration extends AbstractCosmosConfiguration {
|
||||
|
||||
@Value("${cosmosdb.uri:}")
|
||||
private String documentDbUri;
|
||||
private String cosmosDbUri;
|
||||
|
||||
@Value("${cosmosdb.key:}")
|
||||
private String documentDbKey;
|
||||
private String cosmosDbKey;
|
||||
|
||||
private RequestOptions getRequestOptions() {
|
||||
final RequestOptions options = new RequestOptions();
|
||||
|
||||
options.setConsistencyLevel(ConsistencyLevel.ConsistentPrefix);
|
||||
options.setDisableRUPerMinuteUsage(true);
|
||||
options.setConsistencyLevel(ConsistencyLevel.CONSISTENT_PREFIX);
|
||||
options.setScriptLoggingEnabled(true);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DocumentDBConfig getConfig() {
|
||||
public CosmosDBConfig getConfig() {
|
||||
final RequestOptions options = getRequestOptions();
|
||||
return DocumentDBConfig.builder(documentDbUri, documentDbKey, TestConstants.DB_NAME)
|
||||
return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, TestConstants.DB_NAME)
|
||||
.requestOptions(options)
|
||||
.build();
|
||||
}
|
|
@ -7,18 +7,18 @@
|
|||
package com.microsoft.azure.spring.data.cosmosdb.core;
|
||||
|
||||
import com.azure.data.cosmos.CosmosClientException;
|
||||
import com.microsoft.azure.documentdb.PartitionKey;
|
||||
import com.azure.data.cosmos.PartitionKey;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.domain.Person;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.DocumentDBAccessException;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
@ -63,7 +63,7 @@ import java.util.UUID;
|
|||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@PropertySource(value = { "classpath:application.properties" })
|
||||
public class DocumentDbTemplateIT {
|
||||
public class CosmosTemplateIT {
|
||||
private static final Person TEST_PERSON = new Person(ID_1, FIRST_NAME, LAST_NAME, HOBBIES,
|
||||
ADDRESSES);
|
||||
|
||||
|
@ -80,14 +80,13 @@ public class DocumentDbTemplateIT {
|
|||
private static final String WRONG_ETAG = "WRONG_ETAG";
|
||||
|
||||
@Value("${cosmosdb.uri}")
|
||||
private String documentDbUri;
|
||||
private String cosmosDbUri;
|
||||
@Value("${cosmosdb.key}")
|
||||
private String documentDbKey;
|
||||
private String cosmosDbKey;
|
||||
|
||||
private static DocumentDbTemplate dbTemplate;
|
||||
private static DocumentDbEntityInformation<Person, String> personInfo;
|
||||
private static CosmosTemplate cosmosTemplate;
|
||||
private static CosmosEntityInformation<Person, String> personInfo;
|
||||
private static String collectionName;
|
||||
|
||||
private static boolean initialized;
|
||||
|
||||
private Person insertedPerson;
|
||||
|
@ -98,64 +97,64 @@ public class DocumentDbTemplateIT {
|
|||
@Before
|
||||
public void setup() throws ClassNotFoundException {
|
||||
if (!initialized) {
|
||||
final DocumentDBConfig dbConfig = DocumentDBConfig.builder(documentDbUri,
|
||||
documentDbKey, DB_NAME).build();
|
||||
final CosmosDBConfig dbConfig = CosmosDBConfig.builder(cosmosDbUri,
|
||||
cosmosDbKey, DB_NAME).build();
|
||||
final CosmosDbFactory cosmosDbFactory = new CosmosDbFactory(dbConfig);
|
||||
|
||||
final DocumentDbMappingContext mappingContext = new DocumentDbMappingContext();
|
||||
personInfo = new DocumentDbEntityInformation<>(Person.class);
|
||||
final CosmosMappingContext mappingContext = new CosmosMappingContext();
|
||||
personInfo = new CosmosEntityInformation<>(Person.class);
|
||||
collectionName = personInfo.getCollectionName();
|
||||
|
||||
mappingContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class));
|
||||
|
||||
final MappingDocumentDbConverter dbConverter =
|
||||
new MappingDocumentDbConverter(mappingContext, null);
|
||||
dbTemplate = new DocumentDbTemplate(cosmosDbFactory, dbConverter, DB_NAME);
|
||||
dbTemplate.createCollectionIfNotExists(personInfo);
|
||||
final MappingCosmosConverter cosmosConverter = new MappingCosmosConverter(mappingContext,
|
||||
null);
|
||||
cosmosTemplate = new CosmosTemplate(cosmosDbFactory, cosmosConverter, DB_NAME);
|
||||
cosmosTemplate.createCollectionIfNotExists(personInfo);
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
insertedPerson = dbTemplate.insert(Person.class.getSimpleName(), TEST_PERSON, null);
|
||||
insertedPerson = cosmosTemplate.insert(Person.class.getSimpleName(), TEST_PERSON, null);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
dbTemplate.deleteAll(Person.class.getSimpleName(), Person.class);
|
||||
cosmosTemplate.deleteAll(Person.class.getSimpleName(), Person.class);
|
||||
}
|
||||
|
||||
@Test(expected = DocumentDBAccessException.class)
|
||||
@Test(expected = CosmosDBAccessException.class)
|
||||
public void testInsertDuplicateId() {
|
||||
dbTemplate.insert(Person.class.getSimpleName(), TEST_PERSON,
|
||||
cosmosTemplate.insert(Person.class.getSimpleName(), TEST_PERSON,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAll() {
|
||||
final List<Person> result = dbTemplate.findAll(Person.class.getSimpleName(), Person.class);
|
||||
final List<Person> result = cosmosTemplate.findAll(Person.class.getSimpleName(), Person.class);
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertThat(result.get(0)).isEqualTo(TEST_PERSON);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindById() {
|
||||
final Person result = dbTemplate.findById(Person.class.getSimpleName(),
|
||||
final Person result = cosmosTemplate.findById(Person.class.getSimpleName(),
|
||||
TEST_PERSON.getId(), Person.class);
|
||||
assertEquals(result, TEST_PERSON);
|
||||
|
||||
final Person nullResult = dbTemplate.findById(Person.class.getSimpleName(),
|
||||
final Person nullResult = cosmosTemplate.findById(Person.class.getSimpleName(),
|
||||
NOT_EXIST_ID, Person.class);
|
||||
assertThat(nullResult).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindByMultiIds() {
|
||||
dbTemplate.insert(TEST_PERSON_2,
|
||||
cosmosTemplate.insert(TEST_PERSON_2,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)));
|
||||
dbTemplate.insert(TEST_PERSON_3,
|
||||
cosmosTemplate.insert(TEST_PERSON_3,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_3)));
|
||||
|
||||
final List<Object> ids = Lists.newArrayList(ID_1, ID_2, ID_3);
|
||||
final List<Person> result = dbTemplate.findByIds(ids, Person.class, collectionName);
|
||||
final List<Person> result = cosmosTemplate.findByIds(ids, Person.class, collectionName);
|
||||
|
||||
final List<Person> expected = Lists.newArrayList(TEST_PERSON, TEST_PERSON_2, TEST_PERSON_3);
|
||||
assertThat(result.size()).isEqualTo(expected.size());
|
||||
|
@ -165,17 +164,17 @@ public class DocumentDbTemplateIT {
|
|||
@Test
|
||||
public void testUpsertNewDocument() {
|
||||
// Delete first as was inserted in setup
|
||||
dbTemplate.deleteById(Person.class.getSimpleName(), TEST_PERSON.getId(),
|
||||
cosmosTemplate.deleteById(Person.class.getSimpleName(), TEST_PERSON.getId(),
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON)));
|
||||
|
||||
final String firstName = NEW_FIRST_NAME + "_" + UUID.randomUUID().toString();
|
||||
final Person newPerson = new Person(TEST_PERSON.getId(), firstName,
|
||||
NEW_FIRST_NAME, null, null);
|
||||
|
||||
dbTemplate.upsert(Person.class.getSimpleName(), newPerson,
|
||||
cosmosTemplate.upsert(Person.class.getSimpleName(), newPerson,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(newPerson)));
|
||||
|
||||
final List<Person> result = dbTemplate.findAll(Person.class);
|
||||
final List<Person> result = cosmosTemplate.findAll(Person.class);
|
||||
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertEquals(result.get(0).getFirstName(), firstName);
|
||||
|
@ -187,9 +186,9 @@ public class DocumentDbTemplateIT {
|
|||
TEST_PERSON.getLastName(), TEST_PERSON.getHobbies(), TEST_PERSON.getShippingAddresses());
|
||||
updated.set_etag(insertedPerson.get_etag());
|
||||
|
||||
dbTemplate.upsert(Person.class.getSimpleName(), updated, null);
|
||||
cosmosTemplate.upsert(Person.class.getSimpleName(), updated, null);
|
||||
|
||||
final Person result = dbTemplate.findById(Person.class.getSimpleName(),
|
||||
final Person result = cosmosTemplate.findById(Person.class.getSimpleName(),
|
||||
updated.getId(), Person.class);
|
||||
|
||||
assertEquals(result, updated);
|
||||
|
@ -202,14 +201,14 @@ public class DocumentDbTemplateIT {
|
|||
updated.set_etag(WRONG_ETAG);
|
||||
|
||||
try {
|
||||
dbTemplate.upsert(Person.class.getSimpleName(), updated, null);
|
||||
} catch (DocumentDBAccessException e) {
|
||||
cosmosTemplate.upsert(Person.class.getSimpleName(), updated, null);
|
||||
} catch (CosmosDBAccessException e) {
|
||||
assertThat(e.getCause()).isNotNull();
|
||||
final Throwable cosmosClientException = e.getCause().getCause();
|
||||
assertThat(cosmosClientException).isInstanceOf(CosmosClientException.class);
|
||||
assertThat(cosmosClientException.getMessage()).contains(PRECONDITION_IS_NOT_MET);
|
||||
|
||||
final Person unmodifiedPerson = dbTemplate.findById(Person.class.getSimpleName(),
|
||||
final Person unmodifiedPerson = cosmosTemplate.findById(Person.class.getSimpleName(),
|
||||
TEST_PERSON.getId(), Person.class);
|
||||
assertThat(unmodifiedPerson.getFirstName()).isEqualTo(insertedPerson.getFirstName());
|
||||
return;
|
||||
|
@ -220,54 +219,54 @@ public class DocumentDbTemplateIT {
|
|||
|
||||
@Test
|
||||
public void testDeleteById() {
|
||||
dbTemplate.insert(TEST_PERSON_2, null);
|
||||
assertThat(dbTemplate.findAll(Person.class).size()).isEqualTo(2);
|
||||
cosmosTemplate.insert(TEST_PERSON_2, null);
|
||||
assertThat(cosmosTemplate.findAll(Person.class).size()).isEqualTo(2);
|
||||
|
||||
dbTemplate.deleteById(Person.class.getSimpleName(), TEST_PERSON.getId(),
|
||||
cosmosTemplate.deleteById(Person.class.getSimpleName(), TEST_PERSON.getId(),
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON)));
|
||||
|
||||
final List<Person> result = dbTemplate.findAll(Person.class);
|
||||
final List<Person> result = cosmosTemplate.findAll(Person.class);
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertEquals(result.get(0), TEST_PERSON_2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountByCollection() {
|
||||
final long prevCount = dbTemplate.count(collectionName);
|
||||
final long prevCount = cosmosTemplate.count(collectionName);
|
||||
assertThat(prevCount).isEqualTo(1);
|
||||
|
||||
dbTemplate.insert(TEST_PERSON_2,
|
||||
cosmosTemplate.insert(TEST_PERSON_2,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)));
|
||||
|
||||
final long newCount = dbTemplate.count(collectionName);
|
||||
final long newCount = cosmosTemplate.count(collectionName);
|
||||
assertThat(newCount).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountByQuery() {
|
||||
dbTemplate.insert(TEST_PERSON_2,
|
||||
cosmosTemplate.insert(TEST_PERSON_2,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)));
|
||||
|
||||
final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName",
|
||||
Collections.singletonList(TEST_PERSON_2.getFirstName()));
|
||||
final DocumentQuery query = new DocumentQuery(criteria);
|
||||
|
||||
final long count = dbTemplate.count(query, Person.class, collectionName);
|
||||
final long count = cosmosTemplate.count(query, Person.class, collectionName);
|
||||
assertThat(count).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAllPageableMultiPages() {
|
||||
dbTemplate.insert(TEST_PERSON_2,
|
||||
cosmosTemplate.insert(TEST_PERSON_2,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)));
|
||||
|
||||
final DocumentDbPageRequest pageRequest = new DocumentDbPageRequest(0, PAGE_SIZE_1, null);
|
||||
final Page<Person> page1 = dbTemplate.findAll(pageRequest, Person.class, collectionName);
|
||||
final CosmosPageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_1, null);
|
||||
final Page<Person> page1 = cosmosTemplate.findAll(pageRequest, Person.class, collectionName);
|
||||
|
||||
assertThat(page1.getContent().size()).isEqualTo(PAGE_SIZE_1);
|
||||
validateNonLastPage(page1, PAGE_SIZE_1);
|
||||
|
||||
final Page<Person> page2 = dbTemplate.findAll(page1.getPageable(), Person.class,
|
||||
final Page<Person> page2 = cosmosTemplate.findAll(page1.getPageable(), Person.class,
|
||||
collectionName);
|
||||
assertThat(page2.getContent().size()).isEqualTo(1);
|
||||
validateLastPage(page2, PAGE_SIZE_1);
|
||||
|
@ -275,30 +274,30 @@ public class DocumentDbTemplateIT {
|
|||
|
||||
@Test
|
||||
public void testPaginationQuery() {
|
||||
dbTemplate.insert(TEST_PERSON_2,
|
||||
cosmosTemplate.insert(TEST_PERSON_2,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)));
|
||||
|
||||
final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName",
|
||||
Collections.singletonList(FIRST_NAME));
|
||||
final PageRequest pageRequest = new DocumentDbPageRequest(0, PAGE_SIZE_2, null);
|
||||
final PageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_2, null);
|
||||
final DocumentQuery query = new DocumentQuery(criteria).with(pageRequest);
|
||||
|
||||
final Page<Person> page = dbTemplate.paginationQuery(query, Person.class, collectionName);
|
||||
final Page<Person> page = cosmosTemplate.paginationQuery(query, Person.class, collectionName);
|
||||
assertThat(page.getContent().size()).isEqualTo(1);
|
||||
validateLastPage(page, PAGE_SIZE_2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindAllWithPageableAndSort() {
|
||||
dbTemplate.insert(TEST_PERSON_2,
|
||||
cosmosTemplate.insert(TEST_PERSON_2,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)));
|
||||
dbTemplate.insert(TEST_PERSON_3,
|
||||
cosmosTemplate.insert(TEST_PERSON_3,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_3)));
|
||||
|
||||
final Sort sort = new Sort(Sort.Direction.DESC, "firstName");
|
||||
final PageRequest pageRequest = DocumentDbPageRequest.of(0, PAGE_SIZE_3, null, sort);
|
||||
final Sort sort = Sort.by(Sort.Direction.DESC, "firstName");
|
||||
final PageRequest pageRequest = CosmosPageRequest.of(0, PAGE_SIZE_3, null, sort);
|
||||
|
||||
final Page<Person> page = dbTemplate.findAll(pageRequest, Person.class, collectionName);
|
||||
final Page<Person> page = cosmosTemplate.findAll(pageRequest, Person.class, collectionName);
|
||||
assertThat(page.getContent().size()).isEqualTo(3);
|
||||
validateLastPage(page, PAGE_SIZE_3);
|
||||
|
||||
|
@ -314,19 +313,19 @@ public class DocumentDbTemplateIT {
|
|||
final Person testPerson4 = new Person("id_4", "barney", NEW_LAST_NAME, HOBBIES, ADDRESSES);
|
||||
final Person testPerson5 = new Person("id_5", "fred", NEW_LAST_NAME, HOBBIES, ADDRESSES);
|
||||
|
||||
dbTemplate.insert(TEST_PERSON_2,
|
||||
cosmosTemplate.insert(TEST_PERSON_2,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_2)));
|
||||
dbTemplate.insert(TEST_PERSON_3,
|
||||
cosmosTemplate.insert(TEST_PERSON_3,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_3)));
|
||||
dbTemplate.insert(testPerson4,
|
||||
cosmosTemplate.insert(testPerson4,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(testPerson4)));
|
||||
dbTemplate.insert(testPerson5,
|
||||
cosmosTemplate.insert(testPerson5,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(testPerson5)));
|
||||
|
||||
final Sort sort = new Sort(Sort.Direction.ASC, "firstName");
|
||||
final PageRequest pageRequest = DocumentDbPageRequest.of(0, PAGE_SIZE_3, null, sort);
|
||||
final Sort sort = Sort.by(Sort.Direction.ASC, "firstName");
|
||||
final PageRequest pageRequest = CosmosPageRequest.of(0, PAGE_SIZE_3, null, sort);
|
||||
|
||||
final Page<Person> firstPage = dbTemplate.findAll(pageRequest, Person.class,
|
||||
final Page<Person> firstPage = cosmosTemplate.findAll(pageRequest, Person.class,
|
||||
collectionName);
|
||||
|
||||
assertThat(firstPage.getContent().size()).isEqualTo(3);
|
||||
|
@ -337,7 +336,7 @@ public class DocumentDbTemplateIT {
|
|||
assertThat(firstPageResults.get(1).getFirstName()).isEqualTo(FIRST_NAME);
|
||||
assertThat(firstPageResults.get(2).getFirstName()).isEqualTo(testPerson5.getFirstName());
|
||||
|
||||
final Page<Person> secondPage = dbTemplate.findAll(firstPage.getPageable(), Person.class,
|
||||
final Page<Person> secondPage = cosmosTemplate.findAll(firstPage.getPageable(), Person.class,
|
||||
collectionName);
|
||||
|
||||
assertThat(secondPage.getContent().size()).isEqualTo(2);
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.core;
|
||||
|
||||
import com.microsoft.azure.documentdb.PartitionKey;
|
||||
import com.azure.data.cosmos.PartitionKey;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.domain.Person;
|
||||
|
@ -16,7 +16,6 @@ import org.junit.runner.RunWith;
|
|||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType.IS_EQUAL;
|
||||
|
@ -26,7 +25,7 @@ import java.lang.reflect.Method;
|
|||
import java.util.Arrays;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DocumentDbTemplateIllegalTest {
|
||||
public class CosmosTemplateIllegalTest {
|
||||
private static final String NULL_STR = null;
|
||||
private static final String DUMMY_COLL = "dummy";
|
||||
private static final String DUMMY_ID = "ID_1";
|
||||
|
@ -36,7 +35,7 @@ public class DocumentDbTemplateIllegalTest {
|
|||
private static final String CHECK_FAILURE_MSG = "Illegal argument is not checked";
|
||||
|
||||
@Mock(answer = Answers.CALLS_REAL_METHODS)
|
||||
private DocumentDbTemplate dbTemplate;
|
||||
private CosmosTemplate dbTemplate;
|
||||
private Class dbTemplateClass;
|
||||
|
||||
@Before
|
|
@ -6,17 +6,17 @@
|
|||
|
||||
package com.microsoft.azure.spring.data.cosmosdb.core;
|
||||
|
||||
import com.microsoft.azure.documentdb.PartitionKey;
|
||||
import com.azure.data.cosmos.PartitionKey;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.domain.PartitionPerson;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -45,7 +45,7 @@ import static org.junit.Assert.assertTrue;
|
|||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@PropertySource(value = {"classpath:application.properties"})
|
||||
public class DocumentDbTemplatePartitionIT {
|
||||
public class CosmosTemplatePartitionIT {
|
||||
private static final PartitionPerson TEST_PERSON = new PartitionPerson(ID_1, FIRST_NAME, LAST_NAME,
|
||||
HOBBIES, ADDRESSES);
|
||||
|
||||
|
@ -53,13 +53,13 @@ public class DocumentDbTemplatePartitionIT {
|
|||
TEST_PERSON.getLastName(), HOBBIES, ADDRESSES);
|
||||
|
||||
@Value("${cosmosdb.uri}")
|
||||
private String documentDbUri;
|
||||
private String cosmosDbUri;
|
||||
@Value("${cosmosdb.key}")
|
||||
private String documentDbKey;
|
||||
private String cosmosDbKey;
|
||||
|
||||
private static DocumentDbTemplate dbTemplate;
|
||||
private static CosmosTemplate cosmosTemplate;
|
||||
private static String collectionName;
|
||||
private static DocumentDbEntityInformation<PartitionPerson, String> personInfo;
|
||||
private static CosmosEntityInformation<PartitionPerson, String> personInfo;
|
||||
private static boolean initialized;
|
||||
|
||||
@Autowired
|
||||
|
@ -68,36 +68,36 @@ public class DocumentDbTemplatePartitionIT {
|
|||
@Before
|
||||
public void setup() throws ClassNotFoundException {
|
||||
if (!initialized) {
|
||||
final DocumentDBConfig dbConfig = DocumentDBConfig.builder(documentDbUri, documentDbKey, DB_NAME).build();
|
||||
final CosmosDBConfig dbConfig = CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, DB_NAME).build();
|
||||
final CosmosDbFactory cosmosDbFactory = new CosmosDbFactory(dbConfig);
|
||||
final DocumentDbMappingContext mappingContext = new DocumentDbMappingContext();
|
||||
final CosmosMappingContext mappingContext = new CosmosMappingContext();
|
||||
|
||||
personInfo = new DocumentDbEntityInformation<>(PartitionPerson.class);
|
||||
personInfo = new CosmosEntityInformation<>(PartitionPerson.class);
|
||||
mappingContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class));
|
||||
|
||||
final MappingDocumentDbConverter dbConverter = new MappingDocumentDbConverter(mappingContext, null);
|
||||
final MappingCosmosConverter dbConverter = new MappingCosmosConverter(mappingContext, null);
|
||||
|
||||
dbTemplate = new DocumentDbTemplate(cosmosDbFactory, dbConverter, DB_NAME);
|
||||
cosmosTemplate = new CosmosTemplate(cosmosDbFactory, dbConverter, DB_NAME);
|
||||
collectionName = personInfo.getCollectionName();
|
||||
|
||||
dbTemplate.createCollectionIfNotExists(personInfo);
|
||||
cosmosTemplate.createCollectionIfNotExists(personInfo);
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
dbTemplate.insert(PartitionPerson.class.getSimpleName(), TEST_PERSON,
|
||||
cosmosTemplate.insert(PartitionPerson.class.getSimpleName(), TEST_PERSON,
|
||||
new PartitionKey(TEST_PERSON.getLastName()));
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanup() {
|
||||
dbTemplate.deleteAll(personInfo.getCollectionName(), PartitionPerson.class);
|
||||
cosmosTemplate.deleteAll(personInfo.getCollectionName(), PartitionPerson.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindWithPartition() {
|
||||
Criteria criteria = Criteria.getInstance(IS_EQUAL, PROPERTY_LAST_NAME, Arrays.asList(LAST_NAME));
|
||||
DocumentQuery query = new DocumentQuery(criteria);
|
||||
List<PartitionPerson> result = dbTemplate.find(query, PartitionPerson.class,
|
||||
List<PartitionPerson> result = cosmosTemplate.find(query, PartitionPerson.class,
|
||||
PartitionPerson.class.getSimpleName());
|
||||
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
|
@ -105,15 +105,16 @@ public class DocumentDbTemplatePartitionIT {
|
|||
|
||||
criteria = Criteria.getInstance(IS_EQUAL, PROPERTY_ID, Arrays.asList(ID_1));
|
||||
query = new DocumentQuery(criteria);
|
||||
result = dbTemplate.find(query, PartitionPerson.class, PartitionPerson.class.getSimpleName());
|
||||
result = cosmosTemplate.find(query, PartitionPerson.class, PartitionPerson.class.getSimpleName());
|
||||
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertEquals(TEST_PERSON, result.get(0));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testFindByIdWithPartition() {
|
||||
final PartitionPerson partitionPersonById = dbTemplate.findById(TEST_PERSON.getId(),
|
||||
final PartitionPerson partitionPersonById = cosmosTemplate.findById(TEST_PERSON.getId(),
|
||||
PartitionPerson.class,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON)));
|
||||
|
||||
|
@ -125,7 +126,7 @@ public class DocumentDbTemplatePartitionIT {
|
|||
final Criteria criteria = Criteria.getInstance(IS_EQUAL, PROPERTY_ID, Arrays.asList(NOT_EXIST_ID));
|
||||
final DocumentQuery query = new DocumentQuery(criteria);
|
||||
|
||||
final List<PartitionPerson> result = dbTemplate.find(query, PartitionPerson.class,
|
||||
final List<PartitionPerson> result = cosmosTemplate.find(query, PartitionPerson.class,
|
||||
PartitionPerson.class.getSimpleName());
|
||||
assertThat(result.size()).isEqualTo(0);
|
||||
}
|
||||
|
@ -138,9 +139,9 @@ public class DocumentDbTemplatePartitionIT {
|
|||
null, null);
|
||||
|
||||
final String partitionKeyValue = newPerson.getLastName();
|
||||
dbTemplate.upsert(PartitionPerson.class.getSimpleName(), newPerson, new PartitionKey(partitionKeyValue));
|
||||
cosmosTemplate.upsert(PartitionPerson.class.getSimpleName(), newPerson, new PartitionKey(partitionKeyValue));
|
||||
|
||||
final List<PartitionPerson> result = dbTemplate.findAll(PartitionPerson.class);
|
||||
final List<PartitionPerson> result = cosmosTemplate.findAll(PartitionPerson.class);
|
||||
|
||||
assertThat(result.size()).isEqualTo(2);
|
||||
|
||||
|
@ -153,9 +154,9 @@ public class DocumentDbTemplatePartitionIT {
|
|||
public void testUpdatePartition() {
|
||||
final PartitionPerson updated = new PartitionPerson(TEST_PERSON.getId(), UPDATED_FIRST_NAME,
|
||||
TEST_PERSON.getLastName(), TEST_PERSON.getHobbies(), TEST_PERSON.getShippingAddresses());
|
||||
dbTemplate.upsert(PartitionPerson.class.getSimpleName(), updated, new PartitionKey(updated.getLastName()));
|
||||
cosmosTemplate.upsert(PartitionPerson.class.getSimpleName(), updated, new PartitionKey(updated.getLastName()));
|
||||
|
||||
final List<PartitionPerson> result = dbTemplate.findAll(PartitionPerson.class);
|
||||
final List<PartitionPerson> result = cosmosTemplate.findAll(PartitionPerson.class);
|
||||
final PartitionPerson person = result.stream().filter(
|
||||
p -> TEST_PERSON.getId().equals(p.getId())).findFirst().get();
|
||||
|
||||
|
@ -165,41 +166,41 @@ public class DocumentDbTemplatePartitionIT {
|
|||
@Test
|
||||
public void testDeleteByIdPartition() {
|
||||
// insert new document with same partition key
|
||||
dbTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
|
||||
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
|
||||
|
||||
final List<PartitionPerson> inserted = dbTemplate.findAll(PartitionPerson.class);
|
||||
final List<PartitionPerson> inserted = cosmosTemplate.findAll(PartitionPerson.class);
|
||||
assertThat(inserted.size()).isEqualTo(2);
|
||||
assertThat(inserted.get(0).getLastName()).isEqualTo(TEST_PERSON.getLastName());
|
||||
assertThat(inserted.get(1).getLastName()).isEqualTo(TEST_PERSON.getLastName());
|
||||
|
||||
dbTemplate.deleteById(PartitionPerson.class.getSimpleName(),
|
||||
cosmosTemplate.deleteById(PartitionPerson.class.getSimpleName(),
|
||||
TEST_PERSON.getId(), new PartitionKey(TEST_PERSON.getLastName()));
|
||||
|
||||
final List<PartitionPerson> result = dbTemplate.findAll(PartitionPerson.class);
|
||||
final List<PartitionPerson> result = cosmosTemplate.findAll(PartitionPerson.class);
|
||||
assertThat(result.size()).isEqualTo(1);
|
||||
assertTrue(result.get(0).equals(TEST_PERSON_2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountForPartitionedCollection() {
|
||||
final long prevCount = dbTemplate.count(collectionName);
|
||||
final long prevCount = cosmosTemplate.count(collectionName);
|
||||
assertThat(prevCount).isEqualTo(1);
|
||||
|
||||
dbTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
|
||||
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
|
||||
|
||||
final long newCount = dbTemplate.count(collectionName);
|
||||
final long newCount = cosmosTemplate.count(collectionName);
|
||||
assertThat(newCount).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountForPartitionedCollectionByQuery() {
|
||||
dbTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
|
||||
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
|
||||
|
||||
final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName",
|
||||
Arrays.asList(TEST_PERSON_2.getFirstName()));
|
||||
final DocumentQuery query = new DocumentQuery(criteria);
|
||||
|
||||
final long count = dbTemplate.count(query, PartitionPerson.class, collectionName);
|
||||
final long count = cosmosTemplate.count(query, PartitionPerson.class, collectionName);
|
||||
assertThat(count).isEqualTo(1);
|
||||
}
|
||||
|
||||
|
@ -209,21 +210,21 @@ public class DocumentDbTemplatePartitionIT {
|
|||
Arrays.asList("non-exist-first-name"));
|
||||
final DocumentQuery query = new DocumentQuery(criteria);
|
||||
|
||||
final long count = dbTemplate.count(query, PartitionPerson.class, collectionName);
|
||||
final long count = cosmosTemplate.count(query, PartitionPerson.class, collectionName);
|
||||
assertThat(count).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPartitionedFindAllPageableMultiPages() {
|
||||
dbTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
|
||||
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
|
||||
|
||||
final DocumentDbPageRequest pageRequest = new DocumentDbPageRequest(0, PAGE_SIZE_1, null);
|
||||
final Page<PartitionPerson> page1 = dbTemplate.findAll(pageRequest, PartitionPerson.class, collectionName);
|
||||
final CosmosPageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_1, null);
|
||||
final Page<PartitionPerson> page1 = cosmosTemplate.findAll(pageRequest, PartitionPerson.class, collectionName);
|
||||
|
||||
assertThat(page1.getContent().size()).isEqualTo(PAGE_SIZE_1);
|
||||
validateNonLastPage(page1, PAGE_SIZE_1);
|
||||
|
||||
final Page<PartitionPerson> page2 = dbTemplate.findAll(page1.getPageable(),
|
||||
final Page<PartitionPerson> page2 = cosmosTemplate.findAll(page1.getPageable(),
|
||||
PartitionPerson.class, collectionName);
|
||||
assertThat(page2.getContent().size()).isEqualTo(1);
|
||||
validateLastPage(page2, PAGE_SIZE_1);
|
||||
|
@ -231,14 +232,14 @@ public class DocumentDbTemplatePartitionIT {
|
|||
|
||||
@Test
|
||||
public void testPartitionedPaginationQuery() {
|
||||
dbTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
|
||||
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName()));
|
||||
|
||||
final Criteria criteria = Criteria.getInstance(CriteriaType.IS_EQUAL, "firstName",
|
||||
Arrays.asList(FIRST_NAME));
|
||||
final PageRequest pageRequest = new DocumentDbPageRequest(0, PAGE_SIZE_2, null);
|
||||
final PageRequest pageRequest = new CosmosPageRequest(0, PAGE_SIZE_2, null);
|
||||
final DocumentQuery query = new DocumentQuery(criteria).with(pageRequest);
|
||||
|
||||
final Page<PartitionPerson> page = dbTemplate.paginationQuery(query, PartitionPerson.class, collectionName);
|
||||
final Page<PartitionPerson> page = cosmosTemplate.paginationQuery(query, PartitionPerson.class, collectionName);
|
||||
assertThat(page.getContent().size()).isEqualTo(1);
|
||||
validateLastPage(page, PAGE_SIZE_2);
|
||||
}
|
|
@ -8,19 +8,19 @@ package com.microsoft.azure.spring.data.cosmosdb.core;
|
|||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DocumentDbTemplateUnitTest {
|
||||
public class CosmosTemplateUnitTest {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectNullDbFactory() {
|
||||
final DocumentDBConfig dbConfig = DocumentDBConfig.builder("", "", TestConstants.DB_NAME).build();
|
||||
final CosmosDBConfig dbConfig = CosmosDBConfig.builder("", "", TestConstants.DB_NAME).build();
|
||||
final CosmosDbFactory cosmosDbFactory = new CosmosDbFactory(dbConfig);
|
||||
|
||||
new DocumentDbTemplate(cosmosDbFactory, null, TestConstants.DB_NAME);
|
||||
new CosmosTemplate(cosmosDbFactory, null, TestConstants.DB_NAME);
|
||||
}
|
||||
}
|
|
@ -10,14 +10,15 @@ import com.azure.data.cosmos.CosmosKeyCredential;
|
|||
import com.azure.data.cosmos.PartitionKey;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CriteriaType;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.domain.Person;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.exception.CosmosDBAccessException;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import io.reactivex.subscribers.TestSubscriber;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
|
@ -64,15 +65,15 @@ public class ReactiveCosmosTemplateIT {
|
|||
TestConstants.NEW_LAST_NAME, TestConstants.HOBBIES, TestConstants.ADDRESSES);
|
||||
|
||||
@Value("${cosmosdb.uri}")
|
||||
private String documentDbUri;
|
||||
private String cosmosDbUri;
|
||||
@Value("${cosmosdb.key}")
|
||||
private String documentDbKey;
|
||||
private String cosmosDbKey;
|
||||
@Value("${cosmosdb.secondaryKey}")
|
||||
private String documentDbSecondaryKey;
|
||||
private String cosmosDbSecondaryKey;
|
||||
|
||||
private static ReactiveCosmosTemplate cosmosTemplate;
|
||||
private static String containerName;
|
||||
private static DocumentDbEntityInformation<Person, String> personInfo;
|
||||
private static CosmosEntityInformation<Person, String> personInfo;
|
||||
private static CosmosKeyCredential cosmosKeyCredential;
|
||||
|
||||
private static boolean initialized;
|
||||
|
@ -83,19 +84,19 @@ public class ReactiveCosmosTemplateIT {
|
|||
@Before
|
||||
public void setUp() throws ClassNotFoundException {
|
||||
if (!initialized) {
|
||||
cosmosKeyCredential = new CosmosKeyCredential(documentDbKey);
|
||||
final DocumentDBConfig dbConfig = DocumentDBConfig.builder(documentDbUri,
|
||||
cosmosKeyCredential = new CosmosKeyCredential(cosmosDbKey);
|
||||
final CosmosDBConfig dbConfig = CosmosDBConfig.builder(cosmosDbUri,
|
||||
cosmosKeyCredential, DB_NAME).build();
|
||||
final CosmosDbFactory dbFactory = new CosmosDbFactory(dbConfig);
|
||||
|
||||
final DocumentDbMappingContext mappingContext = new DocumentDbMappingContext();
|
||||
personInfo = new DocumentDbEntityInformation<>(Person.class);
|
||||
final CosmosMappingContext mappingContext = new CosmosMappingContext();
|
||||
personInfo = new CosmosEntityInformation<>(Person.class);
|
||||
containerName = personInfo.getCollectionName();
|
||||
|
||||
mappingContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class));
|
||||
|
||||
final MappingDocumentDbConverter dbConverter =
|
||||
new MappingDocumentDbConverter(mappingContext, null);
|
||||
final MappingCosmosConverter dbConverter =
|
||||
new MappingCosmosConverter(mappingContext, null);
|
||||
cosmosTemplate = new ReactiveCosmosTemplate(dbFactory, dbConverter, DB_NAME);
|
||||
cosmosTemplate.createCollectionIfNotExists(personInfo).block().container();
|
||||
initialized = true;
|
||||
|
@ -107,7 +108,7 @@ public class ReactiveCosmosTemplateIT {
|
|||
@After
|
||||
public void cleanup() {
|
||||
// Reset master key
|
||||
cosmosKeyCredential.key(documentDbKey);
|
||||
cosmosKeyCredential.key(cosmosDbKey);
|
||||
cosmosTemplate.deleteAll(Person.class.getSimpleName(),
|
||||
personInfo.getPartitionKeyFieldName()).block();
|
||||
}
|
||||
|
@ -122,7 +123,8 @@ public class ReactiveCosmosTemplateIT {
|
|||
testSubscriber.assertNotComplete();
|
||||
testSubscriber.assertTerminated();
|
||||
assertThat(testSubscriber.errors()).hasSize(1);
|
||||
assertThat(((List) testSubscriber.getEvents().get(1)).get(0)).isInstanceOf(CosmosClientException.class);
|
||||
assertThat(((List) testSubscriber.getEvents().get(1)).get(0))
|
||||
.isInstanceOf(CosmosDBAccessException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -137,7 +139,7 @@ public class ReactiveCosmosTemplateIT {
|
|||
|
||||
@Test
|
||||
public void testFindByIDBySecondaryKey() {
|
||||
cosmosKeyCredential.key(documentDbSecondaryKey);
|
||||
cosmosKeyCredential.key(cosmosDbSecondaryKey);
|
||||
final Mono<Person> findById = cosmosTemplate.findById(Person.class.getSimpleName(),
|
||||
TEST_PERSON.getId(),
|
||||
Person.class);
|
||||
|
@ -171,7 +173,7 @@ public class ReactiveCosmosTemplateIT {
|
|||
|
||||
@Test
|
||||
public void testInsertBySecondaryKey() {
|
||||
cosmosKeyCredential.key(documentDbSecondaryKey);
|
||||
cosmosKeyCredential.key(cosmosDbSecondaryKey);
|
||||
StepVerifier.create(cosmosTemplate.insert(TEST_PERSON_3,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_3))))
|
||||
.expectNext(TEST_PERSON_3).verifyComplete();
|
||||
|
@ -197,7 +199,7 @@ public class ReactiveCosmosTemplateIT {
|
|||
|
||||
@Test
|
||||
public void testUpsertBySecondaryKey() {
|
||||
cosmosKeyCredential.key(documentDbSecondaryKey);
|
||||
cosmosKeyCredential.key(cosmosDbSecondaryKey);
|
||||
final Person p = TEST_PERSON_2;
|
||||
final ArrayList<String> hobbies = new ArrayList<>(p.getHobbies());
|
||||
hobbies.add("more code");
|
||||
|
@ -234,7 +236,7 @@ public class ReactiveCosmosTemplateIT {
|
|||
|
||||
@Test
|
||||
public void testDeleteByIdBySecondaryKey() {
|
||||
cosmosKeyCredential.key(documentDbSecondaryKey);
|
||||
cosmosKeyCredential.key(cosmosDbSecondaryKey);
|
||||
cosmosTemplate.insert(TEST_PERSON_4,
|
||||
new PartitionKey(personInfo.getPartitionKeyFieldValue(TEST_PERSON_4))).block();
|
||||
Flux<Person> flux = cosmosTemplate.findAll(Person.class.getSimpleName(), Person.class);
|
||||
|
@ -274,7 +276,7 @@ public class ReactiveCosmosTemplateIT {
|
|||
|
||||
@Test
|
||||
public void testCountBySecondaryKey() {
|
||||
cosmosKeyCredential.key(documentDbSecondaryKey);
|
||||
cosmosKeyCredential.key(cosmosDbSecondaryKey);
|
||||
final Mono<Long> count = cosmosTemplate.count(containerName);
|
||||
StepVerifier.create(count).expectNext((long) 1).verifyComplete();
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ package com.microsoft.azure.spring.data.cosmosdb.core;
|
|||
|
||||
import com.azure.data.cosmos.PartitionKey;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.CosmosDbFactory;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.Criteria;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentQuery;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.domain.PartitionPerson;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
|
@ -59,13 +59,13 @@ public class ReactiveCosmosTemplatePartitionIT {
|
|||
TEST_PERSON.getLastName(), HOBBIES, ADDRESSES);
|
||||
|
||||
@Value("${cosmosdb.uri}")
|
||||
private String documentDbUri;
|
||||
private String cosmosDbUri;
|
||||
@Value("${cosmosdb.key}")
|
||||
private String documentDbKey;
|
||||
private String cosmosDbKey;
|
||||
|
||||
private static ReactiveCosmosTemplate cosmosTemplate;
|
||||
private static String containerName;
|
||||
private static DocumentDbEntityInformation<PartitionPerson, String> personInfo;
|
||||
private static CosmosEntityInformation<PartitionPerson, String> personInfo;
|
||||
|
||||
private static boolean initialized;
|
||||
|
||||
|
@ -75,17 +75,19 @@ public class ReactiveCosmosTemplatePartitionIT {
|
|||
@Before
|
||||
public void setUp() throws ClassNotFoundException {
|
||||
if (!initialized) {
|
||||
final DocumentDBConfig dbConfig = DocumentDBConfig.builder(documentDbUri, documentDbKey, DB_NAME).build();
|
||||
final CosmosDBConfig dbConfig = CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey,
|
||||
DB_NAME).build();
|
||||
final CosmosDbFactory dbFactory = new CosmosDbFactory(dbConfig);
|
||||
|
||||
final DocumentDbMappingContext mappingContext = new DocumentDbMappingContext();
|
||||
|
||||
personInfo = new DocumentDbEntityInformation<>(PartitionPerson.class);
|
||||
final CosmosMappingContext mappingContext = new CosmosMappingContext();
|
||||
personInfo =
|
||||
new CosmosEntityInformation<>(PartitionPerson.class);
|
||||
containerName = personInfo.getCollectionName();
|
||||
|
||||
mappingContext.setInitialEntitySet(new EntityScanner(this.applicationContext).scan(Persistent.class));
|
||||
|
||||
final MappingDocumentDbConverter dbConverter = new MappingDocumentDbConverter(mappingContext, null);
|
||||
final MappingCosmosConverter dbConverter = new MappingCosmosConverter(mappingContext,
|
||||
null);
|
||||
cosmosTemplate = new ReactiveCosmosTemplate(dbFactory, dbConverter, DB_NAME);
|
||||
cosmosTemplate.createCollectionIfNotExists(personInfo).block();
|
||||
|
||||
|
@ -96,21 +98,25 @@ public class ReactiveCosmosTemplatePartitionIT {
|
|||
|
||||
@After
|
||||
public void cleanup() {
|
||||
cosmosTemplate.deleteAll(PartitionPerson.class.getSimpleName(), personInfo.getPartitionKeyFieldName()).block();
|
||||
cosmosTemplate.deleteAll(PartitionPerson.class.getSimpleName(),
|
||||
personInfo.getPartitionKeyFieldName()).block();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindWithPartition() {
|
||||
final Criteria criteria = Criteria.getInstance(IS_EQUAL, PROPERTY_LAST_NAME, Arrays.asList(LAST_NAME));
|
||||
final Criteria criteria = Criteria.getInstance(IS_EQUAL, PROPERTY_LAST_NAME,
|
||||
Arrays.asList(LAST_NAME));
|
||||
final DocumentQuery query = new DocumentQuery(criteria);
|
||||
final Flux<PartitionPerson> partitionPersonFlux = cosmosTemplate.find(query, PartitionPerson.class,
|
||||
PartitionPerson.class.getSimpleName());
|
||||
final Flux<PartitionPerson> partitionPersonFlux = cosmosTemplate.find(query,
|
||||
PartitionPerson.class,
|
||||
PartitionPerson.class.getSimpleName());
|
||||
StepVerifier.create(partitionPersonFlux).consumeNextWith(actual -> {
|
||||
Assert.assertThat(actual.getFirstName(), is(equalTo(TEST_PERSON.getFirstName())));
|
||||
Assert.assertThat(actual.getLastName(), is(equalTo(TEST_PERSON.getLastName())));
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testFindByIdWithPartition() {
|
||||
final Mono<PartitionPerson> partitionPersonMono = cosmosTemplate.findById(TEST_PERSON.getId(),
|
||||
|
@ -122,25 +128,28 @@ public class ReactiveCosmosTemplatePartitionIT {
|
|||
}).verifyComplete();
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void testFindByNonExistIdWithPartition() {
|
||||
//
|
||||
// }
|
||||
// @Test
|
||||
// public void testFindByNonExistIdWithPartition() {
|
||||
//
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testUpsertNewDocumentPartition() {
|
||||
final String firstName = NEW_FIRST_NAME + "_" + UUID.randomUUID().toString();
|
||||
final PartitionPerson newPerson = new PartitionPerson(UUID.randomUUID().toString(), firstName, NEW_LAST_NAME,
|
||||
null, null);
|
||||
final PartitionPerson newPerson = new PartitionPerson(UUID.randomUUID().toString(),
|
||||
firstName, NEW_LAST_NAME,
|
||||
null, null);
|
||||
final String partitionKeyValue = newPerson.getLastName();
|
||||
final Mono<PartitionPerson> upsert = cosmosTemplate.upsert(newPerson, new PartitionKey(partitionKeyValue));
|
||||
final Mono<PartitionPerson> upsert = cosmosTemplate.upsert(newPerson,
|
||||
new PartitionKey(partitionKeyValue));
|
||||
StepVerifier.create(upsert).expectNextCount(1).verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateWithPartition() {
|
||||
final PartitionPerson updated = new PartitionPerson(TEST_PERSON.getId(), UPDATED_FIRST_NAME,
|
||||
TEST_PERSON.getLastName(), TEST_PERSON.getHobbies(), TEST_PERSON.getShippingAddresses());
|
||||
TEST_PERSON.getLastName(), TEST_PERSON.getHobbies(),
|
||||
TEST_PERSON.getShippingAddresses());
|
||||
cosmosTemplate.upsert(updated, new PartitionKey(updated.getLastName())).block();
|
||||
|
||||
final PartitionPerson person = cosmosTemplate
|
||||
|
@ -158,26 +167,41 @@ public class ReactiveCosmosTemplatePartitionIT {
|
|||
StepVerifier.create(cosmosTemplate.findAll(PartitionPerson.class)).expectNextCount(2).verifyComplete();
|
||||
|
||||
cosmosTemplate.deleteById(PartitionPerson.class.getSimpleName(),
|
||||
TEST_PERSON.getId(), new PartitionKey(TEST_PERSON.getLastName())).block();
|
||||
TEST_PERSON.getId(), new PartitionKey(TEST_PERSON.getLastName())).block();
|
||||
StepVerifier.create(cosmosTemplate.findAll(PartitionPerson.class))
|
||||
.expectNext(TEST_PERSON_2)
|
||||
.verifyComplete();
|
||||
.expectNext(TEST_PERSON_2)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteAll() {
|
||||
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName())).block();
|
||||
StepVerifier.create(cosmosTemplate.findAll(PartitionPerson.class)).expectNextCount(2).verifyComplete();
|
||||
final CosmosEntityInformation<PartitionPerson, String> personInfo =
|
||||
new CosmosEntityInformation<>(PartitionPerson.class);
|
||||
cosmosTemplate.deleteAll(containerName, personInfo.getPartitionKeyFieldName()).block();
|
||||
StepVerifier.create(cosmosTemplate.findAll(PartitionPerson.class))
|
||||
.expectNextCount(0)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountForPartitionedCollection() {
|
||||
StepVerifier.create(cosmosTemplate.count(containerName)).expectNext((long) 1).verifyComplete();
|
||||
StepVerifier.create(cosmosTemplate.count(containerName))
|
||||
.expectNext((long) 1).verifyComplete();
|
||||
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName())).block();
|
||||
StepVerifier.create(cosmosTemplate.count(containerName)).expectNext((long) 2).verifyComplete();
|
||||
StepVerifier.create(cosmosTemplate.count(containerName))
|
||||
.expectNext((long) 2).verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountForPartitionedCollectionByQuery() {
|
||||
cosmosTemplate.insert(TEST_PERSON_2, new PartitionKey(TEST_PERSON_2.getLastName())).block();
|
||||
final Criteria criteria = Criteria.getInstance(IS_EQUAL, "firstName",
|
||||
Arrays.asList(TEST_PERSON_2.getFirstName()));
|
||||
Arrays.asList(TEST_PERSON_2.getFirstName()));
|
||||
final DocumentQuery query = new DocumentQuery(criteria);
|
||||
StepVerifier.create(cosmosTemplate.count(query, containerName)).expectNext((long) 1).verifyComplete();
|
||||
StepVerifier.create(cosmosTemplate.count(query, containerName))
|
||||
.expectNext((long) 1).verifyComplete();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ package com.microsoft.azure.spring.data.cosmosdb.core.converter;
|
|||
import com.azure.data.cosmos.CosmosItemProperties;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingDocumentDbConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentDbMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.convert.MappingCosmosConverter;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.CosmosMappingContext;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.domain.Address;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.domain.Memo;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.domain.Importance;
|
||||
|
@ -18,7 +18,7 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
@ -28,33 +28,31 @@ import java.util.Date;
|
|||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MappingDocumentDbConverterUnitTest {
|
||||
public class MappingCosmosConverterUnitTest {
|
||||
private static final SimpleDateFormat DATE = new SimpleDateFormat(TestConstants.DATE_FORMAT);
|
||||
private static final SimpleDateFormat TIMEZONE_DATE = new SimpleDateFormat(TestConstants.DATE_TIMEZONE_FORMAT);
|
||||
|
||||
MappingDocumentDbConverter dbConverter;
|
||||
DocumentDbMappingContext mappingContext;
|
||||
ObjectMapper objectMapper;
|
||||
private MappingCosmosConverter mappingCosmosConverter;
|
||||
|
||||
@Mock
|
||||
ApplicationContext applicationContext;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mappingContext = new DocumentDbMappingContext();
|
||||
objectMapper = new ObjectMapper();
|
||||
final CosmosMappingContext mappingContext = new CosmosMappingContext();
|
||||
final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
mappingContext.setApplicationContext(applicationContext);
|
||||
mappingContext.afterPropertiesSet();
|
||||
mappingContext.getPersistentEntity(Address.class);
|
||||
|
||||
dbConverter = new MappingDocumentDbConverter(mappingContext, objectMapper);
|
||||
mappingCosmosConverter = new MappingCosmosConverter(mappingContext, objectMapper);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void covertAddressToDocumentCorrectly() {
|
||||
final Address testAddress = new Address(TestConstants.POSTAL_CODE, TestConstants.CITY, TestConstants.STREET);
|
||||
final CosmosItemProperties cosmosItemProperties = dbConverter.writeCosmosItemProperties(testAddress);
|
||||
final CosmosItemProperties cosmosItemProperties = mappingCosmosConverter.writeCosmosItemProperties(testAddress);
|
||||
|
||||
assertThat(cosmosItemProperties.id()).isEqualTo(testAddress.getPostalCode());
|
||||
assertThat(cosmosItemProperties.getString(TestConstants.PROPERTY_CITY)).isEqualTo(testAddress.getCity());
|
||||
|
@ -70,7 +68,7 @@ public class MappingDocumentDbConverterUnitTest {
|
|||
final CosmosItemProperties cosmosItemProperties = new CosmosItemProperties(jsonObject.toString());
|
||||
cosmosItemProperties.id(TestConstants.POSTAL_CODE);
|
||||
|
||||
final Address address = dbConverter.read(Address.class, cosmosItemProperties);
|
||||
final Address address = mappingCosmosConverter.read(Address.class, cosmosItemProperties);
|
||||
|
||||
assertThat(address.getPostalCode()).isEqualTo(TestConstants.POSTAL_CODE);
|
||||
assertThat(address.getCity()).isEqualTo(TestConstants.CITY);
|
||||
|
@ -81,7 +79,7 @@ public class MappingDocumentDbConverterUnitTest {
|
|||
public void canWritePojoWithDateToDocument() throws ParseException {
|
||||
final Memo memo = new Memo(TestConstants.ID_1, TestConstants.MESSAGE, DATE.parse(TestConstants.DATE_STRING),
|
||||
Importance.NORMAL);
|
||||
final CosmosItemProperties cosmosItemProperties = dbConverter.writeCosmosItemProperties(memo);
|
||||
final CosmosItemProperties cosmosItemProperties = mappingCosmosConverter.writeCosmosItemProperties(memo);
|
||||
|
||||
assertThat(cosmosItemProperties.id()).isEqualTo(memo.getId());
|
||||
assertThat(cosmosItemProperties.getString(TestConstants.PROPERTY_MESSAGE)).isEqualTo(memo.getMessage());
|
||||
|
@ -99,7 +97,7 @@ public class MappingDocumentDbConverterUnitTest {
|
|||
final CosmosItemProperties cosmosItemProperties = new CosmosItemProperties(jsonObject.toString());
|
||||
cosmosItemProperties.id(TestConstants.ID_1);
|
||||
|
||||
final Memo memo = dbConverter.read(Memo.class, cosmosItemProperties);
|
||||
final Memo memo = mappingCosmosConverter.read(Memo.class, cosmosItemProperties);
|
||||
assertThat(cosmosItemProperties.id()).isEqualTo(memo.getId());
|
||||
assertThat(cosmosItemProperties.getString(TestConstants.PROPERTY_MESSAGE)).isEqualTo(TestConstants.MESSAGE);
|
||||
assertThat(cosmosItemProperties.getLong(TestConstants.PROPERTY_DATE)).isEqualTo(date);
|
||||
|
@ -108,7 +106,7 @@ public class MappingDocumentDbConverterUnitTest {
|
|||
@Test
|
||||
public void convertDateValueToMilliSeconds() throws ParseException {
|
||||
final Date date = TIMEZONE_DATE.parse(TestConstants.DATE_TIMEZONE_STRING);
|
||||
final long time = (Long) MappingDocumentDbConverter.toDocumentDBValue(date);
|
||||
final long time = (Long) MappingCosmosConverter.toCosmosDbValue(date);
|
||||
|
||||
assertThat(time).isEqualTo(TestConstants.MILLI_SECONDS);
|
||||
}
|
|
@ -12,18 +12,18 @@ import org.springframework.data.util.ClassTypeInformation;
|
|||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class BasicDocumentDbPersistentEntityUnitTest {
|
||||
public class BasicCosmosPersistentEntityUnitTest {
|
||||
|
||||
@Test
|
||||
public void testGetCollection() {
|
||||
final BasicDocumentDbPersistentEntity entity = new BasicDocumentDbPersistentEntity<Person>(
|
||||
final BasicCosmosPersistentEntity entity = new BasicCosmosPersistentEntity<Person>(
|
||||
ClassTypeInformation.from(Person.class));
|
||||
assertThat(entity.getCollection()).isEqualTo("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLanguage() {
|
||||
final BasicDocumentDbPersistentEntity entity = new BasicDocumentDbPersistentEntity<Person>(
|
||||
final BasicCosmosPersistentEntity entity = new BasicCosmosPersistentEntity<Person>(
|
||||
ClassTypeInformation.from(Person.class));
|
||||
assertThat(entity.getLanguage()).isEqualTo("");
|
||||
}
|
|
@ -12,15 +12,15 @@ import org.springframework.context.ApplicationContext;
|
|||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class DocumentDbMappingContextUnitTest {
|
||||
public class CosmosMappingContextUnitTest {
|
||||
|
||||
@Mock
|
||||
ApplicationContext context;
|
||||
|
||||
@Test
|
||||
public void mappingContextWithImplicitIdProperty() {
|
||||
final DocumentDbMappingContext context = new DocumentDbMappingContext();
|
||||
final BasicDocumentDbPersistentEntity<?> entity = context.getPersistentEntity(ClassWithId.class);
|
||||
final CosmosMappingContext context = new CosmosMappingContext();
|
||||
final BasicCosmosPersistentEntity<?> entity = context.getPersistentEntity(ClassWithId.class);
|
||||
|
||||
assertThat(entity).isNotNull();
|
||||
}
|
|
@ -55,7 +55,7 @@ public class CriteriaUnitTest {
|
|||
final Criteria criteria = Criteria.getInstance(CriteriaType.IN, CRITERIA_KEY, values);
|
||||
final DocumentQuery query = new DocumentQuery(criteria);
|
||||
|
||||
new FindQuerySpecGenerator().generate(query);
|
||||
new FindQuerySpecGenerator().generateCosmos(query);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalQueryException.class)
|
||||
|
@ -64,6 +64,6 @@ public class CriteriaUnitTest {
|
|||
final Criteria criteria = Criteria.getInstance(CriteriaType.IN, CRITERIA_KEY, values);
|
||||
final DocumentQuery query = new DocumentQuery(criteria);
|
||||
|
||||
new FindQuerySpecGenerator().generate(query);
|
||||
new FindQuerySpecGenerator().generateCosmos(query);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.domain;
|
||||
|
||||
import com.microsoft.azure.documentdb.IndexingMode;
|
||||
import com.azure.data.cosmos.IndexingMode;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.PartitionKey;
|
||||
|
@ -18,7 +18,7 @@ import java.util.UUID;
|
|||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Document
|
||||
@DocumentIndexingPolicy(mode = IndexingMode.Lazy)
|
||||
@DocumentIndexingPolicy(mode = IndexingMode.LAZY)
|
||||
public class Question {
|
||||
|
||||
@Id
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.domain;
|
||||
|
||||
import com.microsoft.azure.documentdb.IndexingMode;
|
||||
import com.azure.data.cosmos.IndexingMode;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPolicy;
|
||||
|
@ -17,7 +17,7 @@ import org.springframework.data.annotation.Id;
|
|||
@Data
|
||||
@AllArgsConstructor
|
||||
@DocumentIndexingPolicy(
|
||||
mode = IndexingMode.Lazy,
|
||||
mode = IndexingMode.LAZY,
|
||||
automatic = TestConstants.INDEXINGPOLICY_AUTOMATIC,
|
||||
includePaths = {
|
||||
TestConstants.INCLUDEDPATH_0,
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.performance;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.AbstractDocumentDbConfiguration;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.DocumentDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.AbstractCosmosConfiguration;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.config.CosmosDBConfig;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.performance.utils.Constants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.config.EnableDocumentDbRepositories;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.config.EnableCosmosRepositories;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
@ -16,16 +16,16 @@ import org.springframework.context.annotation.PropertySource;
|
|||
|
||||
@Configuration
|
||||
@PropertySource(value = {"classpath:application.properties"})
|
||||
@EnableDocumentDbRepositories
|
||||
public class PerfConfiguration extends AbstractDocumentDbConfiguration {
|
||||
@EnableCosmosRepositories
|
||||
public class PerfConfiguration extends AbstractCosmosConfiguration {
|
||||
@Value("${cosmosdb.uri:}")
|
||||
private String documentDbUri;
|
||||
private String cosmosDbUri;
|
||||
|
||||
@Value("${cosmosdb.key:}")
|
||||
private String documentDbKey;
|
||||
private String cosmosDbKey;
|
||||
|
||||
@Bean
|
||||
public DocumentDBConfig getConfig() {
|
||||
return DocumentDBConfig.builder(documentDbUri, documentDbKey, Constants.PERF_DATABASE_NAME).build();
|
||||
public CosmosDBConfig getConfig() {
|
||||
return CosmosDBConfig.builder(cosmosDbUri, cosmosDbKey, Constants.PERF_DATABASE_NAME).build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.performance;
|
||||
|
||||
import com.microsoft.azure.documentdb.DocumentClient;
|
||||
import com.microsoft.azure.documentdb.DocumentClientException;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.DocumentDbPageRequest;
|
||||
import com.azure.data.cosmos.CosmosClient;
|
||||
import com.azure.data.cosmos.CosmosClientException;
|
||||
import com.azure.data.cosmos.sync.CosmosSyncClient;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.query.CosmosPageRequest;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.performance.domain.PerfPerson;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.performance.repository.PerfPersonRepository;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.performance.service.SdkService;
|
||||
|
@ -32,7 +33,11 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.FunctionUtils.*;
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.FunctionUtils.acceptInputListFunc;
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.FunctionUtils.applyInputListFunc;
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.FunctionUtils.getSupplier;
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.FunctionUtils.runConsumerForTimes;
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.FunctionUtils.runFunctionForTimes;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@Slf4j
|
||||
|
@ -51,7 +56,10 @@ public class PerformanceCompare {
|
|||
private float acceptanceDiff;
|
||||
|
||||
@Autowired
|
||||
private DocumentClient documentClient;
|
||||
private CosmosSyncClient cosmosSyncClient;
|
||||
|
||||
@Autowired
|
||||
private CosmosClient asyncClient;
|
||||
|
||||
@Autowired
|
||||
private PerfPersonRepository repository;
|
||||
|
@ -61,14 +69,16 @@ public class PerformanceCompare {
|
|||
private static PerformanceReport report = new PerformanceReport();
|
||||
|
||||
@Before
|
||||
public void setup() throws DocumentClientException {
|
||||
public void setup() throws CosmosClientException {
|
||||
if (!hasInit) {
|
||||
DatabaseUtils.createDatabase(documentClient, Constants.PERF_DATABASE_NAME);
|
||||
DatabaseUtils.createCollection(documentClient, Constants.PERF_DATABASE_NAME,
|
||||
DatabaseUtils.createDatabase(cosmosSyncClient, Constants.PERF_DATABASE_NAME);
|
||||
DatabaseUtils.createCollection(cosmosSyncClient, Constants.PERF_DATABASE_NAME,
|
||||
Constants.SPRING_COLLECTION_NAME);
|
||||
DatabaseUtils.createCollection(documentClient, Constants.PERF_DATABASE_NAME, Constants.SDK_COLLECTION_NAME);
|
||||
DatabaseUtils.createCollection(cosmosSyncClient,
|
||||
Constants.PERF_DATABASE_NAME, Constants.SDK_COLLECTION_NAME);
|
||||
|
||||
sdkService = new SdkService(documentClient, Constants.PERF_DATABASE_NAME, Constants.SDK_COLLECTION_NAME);
|
||||
sdkService = new SdkService(cosmosSyncClient, Constants.PERF_DATABASE_NAME,
|
||||
Constants.SDK_COLLECTION_NAME, asyncClient);
|
||||
hasInit = true;
|
||||
}
|
||||
|
||||
|
@ -171,7 +181,7 @@ public class PerformanceCompare {
|
|||
public void findBySortingTest() {
|
||||
prepareListData(recurTimes);
|
||||
|
||||
final Sort sort = new Sort(Sort.Direction.ASC, "name");
|
||||
final Sort sort = Sort.by(Sort.Direction.ASC, "name");
|
||||
final List<Sort> sortList = buildSortList(sort, recurTimes);
|
||||
|
||||
final long springCost = applyInputListFunc(sortList, repository::findAll);
|
||||
|
@ -248,7 +258,7 @@ public class PerformanceCompare {
|
|||
}
|
||||
|
||||
private void queryTwoPages(int pageSize) {
|
||||
final Pageable pageable = new DocumentDbPageRequest(0, pageSize, null);
|
||||
final Pageable pageable = new CosmosPageRequest(0, pageSize, null);
|
||||
final Page<PerfPerson> page = this.repository.findAll(pageable);
|
||||
this.repository.findAll(page.getPageable());
|
||||
}
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
package com.microsoft.azure.spring.data.cosmosdb.performance.repository;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.performance.domain.PerfPerson;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.DocumentDbRepository;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.CosmosRepository;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface PerfPersonRepository extends DocumentDbRepository<PerfPerson, String> {
|
||||
public interface PerfPersonRepository extends CosmosRepository<PerfPerson, String> {
|
||||
List<PerfPerson> findAll(Sort sort);
|
||||
|
||||
List<PerfPerson> findByName(String name);
|
||||
|
|
|
@ -5,8 +5,15 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.performance.service;
|
||||
|
||||
import com.azure.data.cosmos.CosmosClient;
|
||||
import com.azure.data.cosmos.CosmosClientException;
|
||||
import com.azure.data.cosmos.CosmosItemProperties;
|
||||
import com.azure.data.cosmos.CosmosItemRequestOptions;
|
||||
import com.azure.data.cosmos.FeedOptions;
|
||||
import com.azure.data.cosmos.FeedResponse;
|
||||
import com.azure.data.cosmos.PartitionKey;
|
||||
import com.azure.data.cosmos.sync.CosmosSyncClient;
|
||||
import com.google.gson.Gson;
|
||||
import com.microsoft.azure.documentdb.*;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.performance.domain.PerfPerson;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.performance.utils.DatabaseUtils;
|
||||
import org.assertj.core.util.Lists;
|
||||
|
@ -18,34 +25,31 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.Constants.PERF_DATABASE_NAME;
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.performance.utils.Constants.SDK_COLLECTION_NAME;
|
||||
|
||||
public class SdkService {
|
||||
private static Gson gson = new Gson();
|
||||
|
||||
private final DocumentClient documentClient;
|
||||
private final CosmosSyncClient cosmosSyncClient;
|
||||
private final String dbName;
|
||||
private final String collectionName;
|
||||
private final String collectionLink;
|
||||
|
||||
public SdkService(DocumentClient client, String dbName, String collectionName) {
|
||||
this.documentClient = client;
|
||||
public SdkService(CosmosSyncClient client, String dbName, String collectionName, CosmosClient asyncClient) {
|
||||
this.cosmosSyncClient = client;
|
||||
this.dbName = dbName;
|
||||
this.collectionName = collectionName;
|
||||
this.collectionLink = "dbs/" + PERF_DATABASE_NAME + "/colls/" + SDK_COLLECTION_NAME;
|
||||
}
|
||||
|
||||
public PerfPerson save(PerfPerson person) {
|
||||
try {
|
||||
final String personJson = gson.toJson(person);
|
||||
final Document personDoc = new Document(personJson);
|
||||
final CosmosItemProperties personDoc = new CosmosItemProperties(personJson);
|
||||
|
||||
final Document doc = documentClient.createDocument(collectionLink, personDoc,
|
||||
null, false).getResource();
|
||||
final CosmosItemProperties doc = cosmosSyncClient.getDatabase(dbName)
|
||||
.getContainer(collectionName)
|
||||
.createItem(personDoc)
|
||||
.properties();
|
||||
|
||||
return gson.fromJson(doc.toJson(), PerfPerson.class);
|
||||
} catch (DocumentClientException e) {
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e); // Runtime exception to fail directly
|
||||
}
|
||||
}
|
||||
|
@ -60,9 +64,13 @@ public class SdkService {
|
|||
public void delete(PerfPerson person) {
|
||||
try {
|
||||
final String docLink = DatabaseUtils.getDocumentLink(dbName, collectionName, person.getId());
|
||||
cosmosSyncClient.getDatabase(dbName)
|
||||
.getContainer(collectionName)
|
||||
.getItem(person.getId(),
|
||||
PartitionKey.None)
|
||||
.delete(new CosmosItemRequestOptions());
|
||||
|
||||
documentClient.deleteDocument(docLink, null);
|
||||
} catch (DocumentClientException e) {
|
||||
} catch (CosmosClientException e) {
|
||||
throw new IllegalStateException(e); // Runtime exception to fail directly
|
||||
}
|
||||
}
|
||||
|
@ -71,9 +79,21 @@ public class SdkService {
|
|||
personIterable.forEach(person -> delete(person));
|
||||
}
|
||||
|
||||
public Document findById(String id) {
|
||||
return documentClient.queryDocuments(collectionLink, "SELECT * FROM " + collectionName + " WHERE " +
|
||||
collectionName + ".id='" + id + "'", new FeedOptions()).getQueryIterator().next();
|
||||
public CosmosItemProperties findById(String id) {
|
||||
final Iterator<FeedResponse<CosmosItemProperties>> feedResponseIterator =
|
||||
cosmosSyncClient.getDatabase(dbName)
|
||||
.getContainer(collectionName)
|
||||
.queryItems("SELECT * FROM " + collectionName + " WHERE " +
|
||||
collectionName + ".id='" + id + "'", new FeedOptions());
|
||||
CosmosItemProperties itemProperties = null;
|
||||
if (feedResponseIterator.hasNext()) {
|
||||
final List<CosmosItemProperties> results = feedResponseIterator.next().results();
|
||||
if (!results.isEmpty()) {
|
||||
itemProperties = results.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
return itemProperties;
|
||||
}
|
||||
|
||||
public List<PerfPerson> findAllById(Iterable<String> ids) {
|
||||
|
@ -83,29 +103,39 @@ public class SdkService {
|
|||
+ idsInList + ")";
|
||||
|
||||
final FeedOptions feedOptions = new FeedOptions();
|
||||
feedOptions.setEnableCrossPartitionQuery(true);
|
||||
feedOptions.enableCrossPartitionQuery(true);
|
||||
|
||||
final List<CosmosItemProperties> docs = null;
|
||||
|
||||
final Iterator<FeedResponse<CosmosItemProperties>> feedResponseIterator = cosmosSyncClient.getDatabase(dbName)
|
||||
.getContainer(collectionName)
|
||||
.queryItems(sql, feedOptions);
|
||||
while (feedResponseIterator.hasNext()) {
|
||||
final FeedResponse<CosmosItemProperties> next = feedResponseIterator.next();
|
||||
docs.addAll(next.results());
|
||||
}
|
||||
|
||||
final List<Document> docs = documentClient.queryDocuments(collectionLink, sql, feedOptions)
|
||||
.getQueryIterable().toList();
|
||||
|
||||
return fromDocuments(docs);
|
||||
}
|
||||
|
||||
public List<PerfPerson> findAll() {
|
||||
final List<Document> docs = documentClient.queryDocuments(collectionLink,
|
||||
"SELECT * FROM " + collectionName, new FeedOptions()).getQueryIterable().toList();
|
||||
|
||||
final String sql = "SELECT * FROM " + collectionName;
|
||||
final List<CosmosItemProperties> docs = getCosmosItemPropertiesList(sql);
|
||||
return fromDocuments(docs);
|
||||
}
|
||||
|
||||
public boolean deleteAll() {
|
||||
final List<Document> documents = documentClient.queryDocuments(collectionLink,
|
||||
"SELECT * FROM " + collectionName, new FeedOptions()).getQueryIterable().toList();
|
||||
final String sql = "SELECT * FROM " + collectionName;
|
||||
final List<CosmosItemProperties> documents = getCosmosItemPropertiesList(sql);
|
||||
|
||||
documents.forEach(document -> {
|
||||
try {
|
||||
documentClient.deleteDocument(document.getSelfLink(), null);
|
||||
} catch (DocumentClientException e) {
|
||||
cosmosSyncClient.getDatabase(dbName)
|
||||
.getContainer(collectionName)
|
||||
.getItem(document.id(), PartitionKey.None)
|
||||
.delete(new CosmosItemRequestOptions().partitionKey(PartitionKey.None));
|
||||
} catch (CosmosClientException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
});
|
||||
|
@ -113,63 +143,74 @@ public class SdkService {
|
|||
return true;
|
||||
}
|
||||
|
||||
private List<CosmosItemProperties> getCosmosItemPropertiesList(String sql) {
|
||||
final List<CosmosItemProperties> documents = new ArrayList<>();
|
||||
final Iterator<FeedResponse<CosmosItemProperties>> feedResponseIterator =
|
||||
cosmosSyncClient.getDatabase(dbName)
|
||||
.getContainer(collectionName)
|
||||
.queryItems(sql, new FeedOptions().enableCrossPartitionQuery(true));
|
||||
while (feedResponseIterator.hasNext()) {
|
||||
final FeedResponse<CosmosItemProperties> next = feedResponseIterator.next();
|
||||
documents.addAll(next.results());
|
||||
}
|
||||
return documents;
|
||||
}
|
||||
|
||||
public List<PerfPerson> searchDocuments(Sort sort) {
|
||||
final Sort.Order order = sort.iterator().next(); // Only one Order supported
|
||||
final List<Document> docs = documentClient.queryDocuments(collectionLink,
|
||||
"SELECT * FROM " + collectionName + " ORDER BY " + collectionName + "." + order.getProperty()
|
||||
+ " " + order.getDirection().name(), new FeedOptions()).getQueryIterable().toList();
|
||||
final String sql = "SELECT * FROM " + collectionName + " ORDER BY " + collectionName + "."
|
||||
+ order.getProperty() + " " + order.getDirection().name();
|
||||
final List<CosmosItemProperties> docs = getCosmosItemPropertiesList(sql);
|
||||
|
||||
return fromDocuments(docs);
|
||||
}
|
||||
|
||||
public long count() {
|
||||
final Object result = documentClient.queryDocuments(collectionLink,
|
||||
"SELECT VALUE COUNT(1) FROM " + collectionName, new FeedOptions())
|
||||
.getQueryIterable().toList().get(0).getHashMap().get("_aggregate");
|
||||
final String sql = "SELECT VALUE COUNT(1) FROM " + collectionName;
|
||||
final Iterator<FeedResponse<CosmosItemProperties>> feedResponseIterator = cosmosSyncClient.getDatabase(dbName)
|
||||
.getContainer(collectionName)
|
||||
.queryItems(sql, new FeedOptions());
|
||||
final Object result = feedResponseIterator.next().results().get(0).get("_aggregate");
|
||||
|
||||
return result instanceof Integer ? Long.valueOf((Integer) result) : (Long) result;
|
||||
}
|
||||
|
||||
public List<PerfPerson> findByName(String name) {
|
||||
final Iterator<Document> result = documentClient.queryDocuments(collectionLink,
|
||||
"SELECT * FROM " + collectionName + " WHERE " + collectionName + ".name='"
|
||||
+ name + "'", new FeedOptions()).getQueryIterator();
|
||||
|
||||
final String sql = "SELECT * FROM " + collectionName + " WHERE " + collectionName + ".name='"
|
||||
+ name + "'";
|
||||
final Iterator<CosmosItemProperties> result = getCosmosItemPropertiesList(sql).iterator();
|
||||
return fromDocuments(Lists.newArrayList(result));
|
||||
}
|
||||
|
||||
public void queryTwoPages(int pageSize) {
|
||||
final FeedOptions options = new FeedOptions();
|
||||
options.setPageSize(pageSize);
|
||||
options.setRequestContinuation(null);
|
||||
options.maxItemCount(pageSize);
|
||||
options.requestContinuation(null);
|
||||
|
||||
searchBySize(pageSize, options);
|
||||
searchBySize(pageSize, options);
|
||||
}
|
||||
|
||||
private List<PerfPerson> searchBySize(int size, FeedOptions options) {
|
||||
final FeedResponse<Document> q = documentClient
|
||||
.queryDocuments(collectionLink, "SELECT * FROM " + collectionName, options);
|
||||
final String sql = "SELECT * FROM " + collectionName;
|
||||
|
||||
final Iterator<Document> it = q.getQueryIterator();
|
||||
final Iterator<CosmosItemProperties> it = getCosmosItemPropertiesList(sql).iterator();
|
||||
final List<PerfPerson> entities = new ArrayList<>();
|
||||
int i = 0;
|
||||
while (it.hasNext() && i++ < size) {
|
||||
// This convert here is in order to mock data conversion in real use case, in order to compare with
|
||||
// Spring Data mapping
|
||||
final Document d = it.next();
|
||||
final CosmosItemProperties d = it.next();
|
||||
final PerfPerson entity = gson.fromJson(d.toJson(), PerfPerson.class);
|
||||
entities.add(entity);
|
||||
}
|
||||
|
||||
options.setRequestContinuation(q.getResponseContinuation());
|
||||
|
||||
count(); // Mock same behavior with Spring pageable query, requires total elements count
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
private List<PerfPerson> fromDocuments(List<Document> documents) {
|
||||
private List<PerfPerson> fromDocuments(List<CosmosItemProperties> documents) {
|
||||
return documents.stream().map(d -> gson.fromJson(d.toJson(), PerfPerson.class))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
|
|
@ -5,45 +5,49 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.performance.utils;
|
||||
|
||||
import com.microsoft.azure.documentdb.*;
|
||||
import com.azure.data.cosmos.CosmosClientException;
|
||||
import com.azure.data.cosmos.CosmosContainerProperties;
|
||||
import com.azure.data.cosmos.IncludedPath;
|
||||
import com.azure.data.cosmos.IndexingPolicy;
|
||||
import com.azure.data.cosmos.PartitionKeyDefinition;
|
||||
import com.azure.data.cosmos.internal.RequestOptions;
|
||||
import com.azure.data.cosmos.sync.CosmosSyncClient;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static com.microsoft.azure.spring.data.cosmosdb.common.TestConstants.ORDER_BY_STRING_PATH;
|
||||
|
||||
public class DatabaseUtils {
|
||||
public static void createDatabase(DocumentClient documentClient, String databaseName)
|
||||
throws DocumentClientException {
|
||||
public static void createDatabase(CosmosSyncClient documentClient, String databaseName)
|
||||
throws CosmosClientException {
|
||||
try {
|
||||
documentClient.deleteDatabase("dbs/" + databaseName, null);
|
||||
} catch (DocumentClientException e) {
|
||||
// Can use sync api once ready
|
||||
documentClient.getDatabase(databaseName).delete();
|
||||
} catch (Exception e) {
|
||||
// Ignore delete failure
|
||||
}
|
||||
|
||||
final Database myDatabase = new Database();
|
||||
myDatabase.setId(databaseName);
|
||||
|
||||
documentClient.createDatabase(myDatabase, null);
|
||||
documentClient.createDatabase(databaseName);
|
||||
}
|
||||
|
||||
public static void deleteCollection(DocumentClient documentClient, String databaseName, String collectionName)
|
||||
throws DocumentClientException{
|
||||
public static void deleteCollection(CosmosSyncClient documentClient, String databaseName, String collectionName)
|
||||
throws CosmosClientException{
|
||||
final RequestOptions requestOptions = new RequestOptions();
|
||||
requestOptions.setOfferThroughput(1000);
|
||||
|
||||
documentClient.deleteCollection("dbs/" + databaseName + "/colls/" + collectionName, requestOptions);
|
||||
documentClient.getDatabase(databaseName).getContainer(collectionName).delete();
|
||||
}
|
||||
|
||||
public static void createCollection(DocumentClient documentClient, String databaseName, String collectionName)
|
||||
throws DocumentClientException {
|
||||
final DocumentCollection myCollection = new DocumentCollection();
|
||||
myCollection.setId(collectionName);
|
||||
public static void createCollection(CosmosSyncClient documentClient, String databaseName, String collectionName)
|
||||
throws CosmosClientException {
|
||||
final CosmosContainerProperties containerProperties = new CosmosContainerProperties(collectionName,
|
||||
new PartitionKeyDefinition().paths(Collections.singletonList("/mypk")));
|
||||
|
||||
final IndexingPolicy policy = new IndexingPolicy();
|
||||
policy.setIncludedPaths(Collections.singletonList(new IncludedPath(ORDER_BY_STRING_PATH)));
|
||||
myCollection.setIndexingPolicy(policy);
|
||||
containerProperties.indexingPolicy(policy);
|
||||
|
||||
documentClient.createCollection("dbs/" + databaseName, myCollection, null);
|
||||
documentClient.getDatabase(databaseName).createContainer(containerProperties);
|
||||
}
|
||||
|
||||
public static String getDocumentLink(String databaseName, String collectionName, Object documentId) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository;
|
||||
|
||||
import com.microsoft.azure.documentdb.IndexingPolicy;
|
||||
import com.azure.data.cosmos.IndexingPolicy;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.TestUtils;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.mapping.Document;
|
||||
|
@ -13,20 +13,20 @@ import com.microsoft.azure.spring.data.cosmosdb.core.mapping.DocumentIndexingPol
|
|||
import com.microsoft.azure.spring.data.cosmosdb.domain.NoDBAnnotationPerson;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.domain.Role;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.domain.TimeToLiveSample;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
|
||||
public class DocumentDBAnnotationUnitTest {
|
||||
private DocumentDbEntityInformation<NoDBAnnotationPerson, String> personInfo;
|
||||
private DocumentDbEntityInformation<Role, String> roleInfo;
|
||||
public class CosmosAnnotationUnitTest {
|
||||
private CosmosEntityInformation<NoDBAnnotationPerson, String> personInfo;
|
||||
private CosmosEntityInformation<Role, String> roleInfo;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
personInfo = new DocumentDbEntityInformation<>(NoDBAnnotationPerson.class);
|
||||
roleInfo = new DocumentDbEntityInformation<>(Role.class);
|
||||
personInfo = new CosmosEntityInformation<>(NoDBAnnotationPerson.class);
|
||||
roleInfo = new CosmosEntityInformation<>(Role.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -45,9 +45,9 @@ public class DocumentDBAnnotationUnitTest {
|
|||
"should be default collection name");
|
||||
Assert.isTrue(personInfo.getRequestUnit() == TestConstants.DEFAULT_REQUEST_UNIT,
|
||||
"should be default request unit");
|
||||
Assert.isTrue(policy.getAutomatic() == TestConstants.DEFAULT_INDEXINGPOLICY_AUTOMATIC,
|
||||
Assert.isTrue(policy.automatic() == TestConstants.DEFAULT_INDEXINGPOLICY_AUTOMATIC,
|
||||
"should be default indexing policy automatic");
|
||||
Assert.isTrue(policy.getIndexingMode() == TestConstants.DEFAULT_INDEXINGPOLICY_MODE,
|
||||
Assert.isTrue(policy.indexingMode() == TestConstants.DEFAULT_INDEXINGPOLICY_MODE,
|
||||
"should be default indexing policy mode");
|
||||
|
||||
// IncludedPaths and ExcludedPaths
|
||||
|
@ -55,8 +55,8 @@ public class DocumentDBAnnotationUnitTest {
|
|||
// and the paths of policy will never be set from azure service.
|
||||
// testIndexingPolicyPathsEquals(policy.getIncludedPaths(), TestConstants.DEFAULT_INCLUDEDPATHS);
|
||||
// testIndexingPolicyPathsEquals(policy.getExcludedPaths(), TestConstants.DEFAULT_EXCLUDEDPATHS);
|
||||
Assert.isTrue(policy.getIncludedPaths().size() == 0, "default includedpaths size must be 0");
|
||||
Assert.isTrue(policy.getExcludedPaths().size() == 0, "default excludedpaths size must be 0");
|
||||
Assert.isTrue(policy.includedPaths().isEmpty(), "default includedpaths size must be 0");
|
||||
Assert.isTrue(policy.excludedPaths().isEmpty(), "default excludedpaths size must be 0");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -74,14 +74,14 @@ public class DocumentDBAnnotationUnitTest {
|
|||
"should be Role(class) collection name");
|
||||
Assert.isTrue(roleInfo.getRequestUnit() == TestConstants.REQUEST_UNIT,
|
||||
"should be Role(class) request unit");
|
||||
Assert.isTrue(policy.getAutomatic() == TestConstants.INDEXINGPOLICY_AUTOMATIC,
|
||||
Assert.isTrue(policy.automatic() == TestConstants.INDEXINGPOLICY_AUTOMATIC,
|
||||
"should be Role(class) indexing policy automatic");
|
||||
Assert.isTrue(policy.getIndexingMode() == TestConstants.INDEXINGPOLICY_MODE,
|
||||
Assert.isTrue(policy.indexingMode() == TestConstants.INDEXINGPOLICY_MODE,
|
||||
"should be Role(class) indexing policy mode");
|
||||
|
||||
// IncludedPaths and ExcludedPaths
|
||||
TestUtils.testIndexingPolicyPathsEquals(policy.getIncludedPaths(), TestConstants.INCLUDEDPATHS);
|
||||
TestUtils.testIndexingPolicyPathsEquals(policy.getExcludedPaths(), TestConstants.EXCLUDEDPATHS);
|
||||
TestUtils.testIndexingPolicyPathsEquals(policy.includedPaths(), TestConstants.INCLUDEDPATHS);
|
||||
TestUtils.testIndexingPolicyPathsEquals(policy.excludedPaths(), TestConstants.EXCLUDEDPATHS);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -94,8 +94,8 @@ public class DocumentDBAnnotationUnitTest {
|
|||
|
||||
@Test
|
||||
public void testDocumentAnnotationTimeToLive() {
|
||||
final DocumentDbEntityInformation<TimeToLiveSample, String> info =
|
||||
new DocumentDbEntityInformation<>(TimeToLiveSample.class);
|
||||
final CosmosEntityInformation<TimeToLiveSample, String> info =
|
||||
new CosmosEntityInformation<>(TimeToLiveSample.class);
|
||||
final Integer timeToLive = info.getTimeToLive();
|
||||
|
||||
Assert.notNull(timeToLive, "timeToLive should not be null");
|
|
@ -5,10 +5,10 @@
|
|||
*/
|
||||
package com.microsoft.azure.spring.data.cosmosdb.repository;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.domain.Person;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.SimpleDocumentDbRepository;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.SimpleCosmosRepository;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
@ -16,17 +16,17 @@ import org.mockito.Mock;
|
|||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SimpleDocumentDbRepositoryIllegalTest {
|
||||
private SimpleDocumentDbRepository<Person, String> repository;
|
||||
public class SimpleCosmosRepositoryIllegalTest {
|
||||
private SimpleCosmosRepository<Person, String> repository;
|
||||
|
||||
@Mock
|
||||
DocumentDbOperations dbOperations;
|
||||
CosmosOperations dbOperations;
|
||||
@Mock
|
||||
DocumentDbEntityInformation<Person, String> entityInformation;
|
||||
CosmosEntityInformation<Person, String> entityInformation;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
repository = new SimpleDocumentDbRepository<>(entityInformation, dbOperations);
|
||||
repository = new SimpleCosmosRepository<>(entityInformation, dbOperations);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
|
@ -7,11 +7,11 @@
|
|||
package com.microsoft.azure.spring.data.cosmosdb.repository;
|
||||
|
||||
import com.microsoft.azure.spring.data.cosmosdb.common.TestConstants;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.DocumentDbOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.core.CosmosOperations;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.domain.Address;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.domain.Person;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.DocumentDbEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.SimpleDocumentDbRepository;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.CosmosEntityInformation;
|
||||
import com.microsoft.azure.spring.data.cosmosdb.repository.support.SimpleCosmosRepository;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
|
@ -26,11 +26,11 @@ import java.util.List;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SimpleDocumentDbRepositoryUnitTest {
|
||||
public class SimpleCosmosRepositoryUnitTest {
|
||||
private static final Person TEST_PERSON =
|
||||
new Person(TestConstants.ID_1, TestConstants.FIRST_NAME, TestConstants.LAST_NAME,
|
||||
TestConstants.HOBBIES, TestConstants.ADDRESSES);
|
||||
|
@ -38,11 +38,11 @@ public class SimpleDocumentDbRepositoryUnitTest {
|
|||
private static final String PARTITION_VALUE_REQUIRED_MSG =
|
||||
"PartitionKey value must be supplied for this operation.";
|
||||
|
||||
SimpleDocumentDbRepository<Person, String> repository;
|
||||
private SimpleCosmosRepository<Person, String> repository;
|
||||
@Mock
|
||||
DocumentDbOperations dbOperations;
|
||||
CosmosOperations cosmosOperations;
|
||||
@Mock
|
||||
DocumentDbEntityInformation<Person, String> entityInformation;
|
||||
CosmosEntityInformation<Person, String> entityInformation;
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
|
@ -51,9 +51,9 @@ public class SimpleDocumentDbRepositoryUnitTest {
|
|||
public void setUp() {
|
||||
when(entityInformation.getJavaType()).thenReturn(Person.class);
|
||||
when(entityInformation.getCollectionName()).thenReturn(Person.class.getSimpleName());
|
||||
when(dbOperations.findAll(anyString(), any())).thenReturn(Arrays.asList(TEST_PERSON));
|
||||
when(cosmosOperations.findAll(anyString(), any())).thenReturn(Arrays.asList(TEST_PERSON));
|
||||
|
||||
repository = new SimpleDocumentDbRepository<>(entityInformation, dbOperations);
|
||||
repository = new SimpleCosmosRepository<>(entityInformation, cosmosOperations);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -67,7 +67,7 @@ public class SimpleDocumentDbRepositoryUnitTest {
|
|||
|
||||
@Test
|
||||
public void testFindOne() {
|
||||
when(dbOperations.findById(anyString(), anyString(), any())).thenReturn(TEST_PERSON);
|
||||
when(cosmosOperations.findById(anyString(), anyString(), any())).thenReturn(TEST_PERSON);
|
||||
|
||||
repository.save(TEST_PERSON);
|
||||
|
||||
|
@ -82,7 +82,7 @@ public class SimpleDocumentDbRepositoryUnitTest {
|
|||
|
||||
repository.save(TEST_PERSON);
|
||||
|
||||
when(dbOperations.findById(anyString(), anyString(), any()))
|
||||
when(cosmosOperations.findById(anyString(), anyString(), any()))
|
||||
.thenThrow(new UnsupportedOperationException(PARTITION_VALUE_REQUIRED_MSG));
|
||||
|
||||
final Person result = repository.findById(TEST_PERSON.getId()).get();
|
||||
|
@ -98,7 +98,7 @@ public class SimpleDocumentDbRepositoryUnitTest {
|
|||
TestConstants.UPDATED_HOBBIES, updatedAddress);
|
||||
repository.save(updatedPerson);
|
||||
|
||||
when(dbOperations.findById(anyString(), anyString(), any())).thenReturn(updatedPerson);
|
||||
when(cosmosOperations.findById(anyString(), anyString(), any())).thenReturn(updatedPerson);
|
||||
|
||||
final Person result = repository.findById(TEST_PERSON.getId()).get();
|
||||
assertEquals(updatedPerson, result);
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче