Java-hoz készült Azure Spring Data Cosmos-ügyfélkódtár

Az Azure Spring Data Cosmos Spring Data-támogatást nyújt az Azure Cosmos DB-hez a Spring Data-keretrendszeren alapuló SQL API használatával. Az Azure Cosmos DB egy globálisan elosztott adatbázis-szolgáltatás, amely lehetővé teszi a fejlesztők számára, hogy különböző szabványos API-k , például AZ SQL, MongoDB, Cassandra, Graph és Table használatával dolgozzanak az adatokkal.

Spring data-verzió támogatása

Ez a projekt mindkét spring-data-commons 2.2.xspring-data-commons 2.3.x verziót támogatja. A Maven-felhasználók a spring-boot-starter-parent projekttől örökölhetnek egy függőségkezelési szakaszt, amely lehetővé teszi, hogy a Spring kezelje a függőségek verzióit.

<!-- Inherit defaults from Spring Boot -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>${spring.boot.version}</version>
</parent>

Ezzel a beállítással felülbírálhatja az egyes függőségeket is, ha felülbírál egy tulajdonságot a saját projektjében. Ha például egy másik Spring Data-kiadási vonatra szeretne frissíteni, az alábbiakat kell hozzáadnia a pom.xml.

<properties>
    <spring-data-releasetrain.version>${spring.data.version}</spring-data-releasetrain.version>
</properties>

Ha nem szeretné használni a spring-boot-starter-parentszolgáltatást, továbbra is megtarthatja a függőségkezelés előnyeit egy scope=import függőség használatával:

<dependencyManagement>
     <dependencies>
        <dependency>
            <!-- Import dependency management from Spring Boot -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring.boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Ez a beállítás nem teszi lehetővé az egyes függőségek felülbírálását a fent ismertetett tulajdonság használatával. Ha ugyanezt az eredményt szeretné elérni, a bejegyzés előtt hozzá kell adnia egy bejegyzést a spring-boot-dependencies projekt dependencyManagement objektumához. Ha például egy másik Spring Data-kiadási betanításra szeretne frissíteni, az alábbiakat kell hozzáadnia a pom.xml.

<dependencyManagement>
    <dependencies>
        <!-- Override Spring Data release train provided by Spring Boot -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-releasetrain</artifactId>
            <version>${spring.data.version}</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring.boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

Megjegyzés

Cserélje le a ${spring.boot.version} Spring Boot és ${spring.data.version} a Spring Data projektben használni kívánt verzióit.

Első lépések

A csomag belefoglalása

Ha Mavent használ, adja hozzá a következő függőséget.

<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-spring-data-cosmos</artifactId>
    <version>LATEST</version>
</dependency>

Előfeltételek

  • Java Development Kit (JDK), 8-es vagy újabb verzió.
  • Aktív Azure-fiók. Ha még nincs fiókja, létrehozhat egy ingyenes fiókot. Másik lehetőségként az Azure Cosmos DB Emulator is használhatja a fejlesztéshez és teszteléshez. Mivel az emulátor https-tanúsítványa önaláírt, importálnia kell a tanúsítványát a Java megbízható tanúsítványtárolójába, amelyet itt ismertetünk
  • (Nem kötelező) Az SLF4J egy fakitermelési homlokzat.
  • (Nem kötelező) Az SLF4J-kötés egy adott naplózási keretrendszer SLF4J-vel való társítására szolgál.
  • (Nem kötelező) Maven

SLF4J-ra csak akkor van szükség, ha naplózást tervez használni, töltsön le egy SLF4J-kötést is, amely összekapcsolja az SLF4J API-t a választott naplózási implementációval. További információt az SLF4J felhasználói kézikönyvében talál.

Konfigurációs osztály beállítása

A konfigurációs osztály beállításához ki kell terjesztenie a AbstractCosmosConfiguration

Az Azure-spring-data-cosmos támogatja és Query Metricstámogatja Response Diagnostics String a . A lekérdezési metrikák engedélyezéséhez állítsa queryMetricsEnabled a jelölőt true (igaz) értékre az application.properties tulajdonságban. A jelző beállítása mellett implementálhatja ResponseDiagnosticsProcessor a diagnosztikai adatok naplózását is.

@Configuration
@EnableCosmosRepositories
public class AppConfiguration extends AbstractCosmosConfiguration {

    private static final Logger LOGGER = LoggerFactory.getLogger(AppConfiguration.class);

    @Value("${azure.cosmos.uri}")
    private String uri;

    @Value("${azure.cosmos.key}")
    private String key;

    @Value("${azure.cosmos.secondaryKey}")
    private String secondaryKey;

    @Value("${azure.cosmos.database}")
    private String dbName;

    @Value("${azure.cosmos.queryMetricsEnabled}")
    private boolean queryMetricsEnabled;

    private AzureKeyCredential azureKeyCredential;

    @Bean
    public CosmosClientBuilder getCosmosClientBuilder() {
        this.azureKeyCredential = new AzureKeyCredential(key);
        DirectConnectionConfig directConnectionConfig = new DirectConnectionConfig();
        GatewayConnectionConfig gatewayConnectionConfig = new GatewayConnectionConfig();
        return new CosmosClientBuilder()
            .endpoint(uri)
            .credential(azureKeyCredential)
            .directMode(directConnectionConfig, gatewayConnectionConfig);
    }

    @Override
    public CosmosConfig cosmosConfig() {
        return CosmosConfig.builder()
                           .enableQueryMetrics(queryMetricsEnabled)
                           .responseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation())
                           .build();
    }

    public void switchToSecondaryKey() {
        this.azureKeyCredential.update(secondaryKey);
    }

    @Override
    protected String getDatabaseName() {
        return "testdb";
    }

    private static class ResponseDiagnosticsProcessorImplementation implements ResponseDiagnosticsProcessor {

        @Override
        public void processResponseDiagnostics(@Nullable ResponseDiagnostics responseDiagnostics) {
            LOGGER.info("Response Diagnostics {}", responseDiagnostics);
        }
    }

}

Konfiguráció testreszabása

Testre szabhatja DirectConnectionConfig vagy GatewayConnectionConfig mindkettőt, és megadhatja, hogy a CosmosClientBuilder bean testre szabható legyen CosmosAsyncClient

@Bean
public CosmosClientBuilder getCosmosClientBuilder() {

    DirectConnectionConfig directConnectionConfig = new DirectConnectionConfig();
    GatewayConnectionConfig gatewayConnectionConfig = new GatewayConnectionConfig();
    return new CosmosClientBuilder()
        .endpoint(uri)
        .directMode(directConnectionConfig, gatewayConnectionConfig);
}

@Override
public CosmosConfig cosmosConfig() {
    return CosmosConfig.builder()
                       .enableQueryMetrics(queryMetricsEnabled)
                       .responseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation())
                       .build();
}

Alapértelmezés szerint az aktuális csomagban keres minden olyan felületet, @EnableCosmosRepositories amely kibővíti a Spring Data adattárának egyik felületét. Ha a projektelrendezés több projektből áll, a konfigurációs osztályt megjegyzésekkel láthatja el egy másik gyökércsomag @EnableCosmosRepositories(basePackageClass=UserRepository.class) beolvasásához.

Entitás definiálása

Egyszerű entitás definiálása elemként az Azure Cosmos DB-ben.

Entitások definiálásához adja hozzá a @Container megjegyzést, és adja meg a tárolóhoz kapcsolódó tulajdonságokat, például a tároló nevét, a kérelemegységeket (KÉRELEM), az élettartamot, és automatikusan hozza létre a tárolót.

A tárolók automatikusan létrejönnek, hacsak nem szeretné őket. A autoCreateContainer tárolók automatikus létrehozásának letiltásához állítsa hamisra a széljegyzetben @Container .

Megjegyzés

Alapértelmezés szerint az újonnan létrehozott tárolókhoz rendelt kérelemegységek 400. Adjon meg különböző ru-értéket az SDK által létrehozott tároló kérelemegységeinek testreszabásához (a minimális RU-érték 400).

@Container(containerName = "myContainer", ru = "400")
public class User {
    private String id;
    private String firstName;


    @PartitionKey
    private String lastName;

    public User() {
        // If you do not want to create a default constructor,
        // use annotation @JsonCreator and @JsonProperty in the full args constructor
    }

    public User(String id, String firstName, String lastName) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return String.format("User: %s %s, %s", firstName, lastName, id);
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

A id mező elemazonosítóként lesz használva az Azure Cosmos DB-ben. Ha egy másik, például firstName elemként idhasznált mezőt szeretne használni, egyszerűen jegyzettel fűzze hozzá a mezőt @Id .

A jegyzet @Container(containerName="myContainer") a tároló nevét határozza meg az Azure Cosmos DB-ben.

A mező megjegyzése @PartitionKeylastName partíciókulcsként adja meg ezt a mezőt az Azure Cosmos DB-ben.

Egyedi kulcskényszer hozzáadása

A tárolójegyzet alatt egyedi kulcsszabályzatot definiálhat.

Az egyedi kulcsokról itt olvashat bővebben.

@Container(containerName = "myContainer", ru = "400")
@CosmosUniqueKeyPolicy(uniqueKeys = {
    @CosmosUniqueKey(paths = {"/lastName", "/zipCode"}),
    @CosmosUniqueKey(paths = {"/city"})
})

Tárolók létrehozása automatikus skálázási átviteli sebességgel

A széljegyzet autoScale mező megadja az automatikus skálázási átviteli sebességgel létrehozni kívánt tárolót, ha igaz értékre van állítva. Az alapértelmezett érték hamis, ami azt jelenti, hogy a tárolók manuális átviteli sebességgel jönnek létre.

Az automatikus skálázás átviteli sebességéről itt olvashat bővebben

@Container(containerName = "myContainer", autoScale = true, ru = "4000")
public class UserSample {
    @Id
    private String emailAddress;

}

Beágyazott partíciókulcs támogatása

A Spring Data Cosmos SDK támogatja a beágyazott partíciókulcsot. Beágyazott partíciókulcs hozzáadásához használjon partitionKeyPath megjegyzésmezőt @Container .

partitionKeyPath A csak a beágyazott partíciókulcs elérési útjának támogatására használható. A partíciókulcsok általános támogatásához használja a @PartitionKey jegyzetet.

Alapértelmezés szerint @PartitionKey a széljegyzetek elsőbbséget élveznek, hacsak nincs megadva.

Az alábbi példa bemutatja, hogyan használható megfelelően a Beágyazott partíciókulcs funkció.

@Container(containerName = "nested-partition-key", partitionKeyPath = "/nestedEntitySample/nestedPartitionKey")
public class NestedPartitionKeyEntitySample {

    private NestedEntitySample nestedEntitySample;
}
public class NestedEntitySample {
    private String nestedPartitionKey;
}

Adattárak létrehozása

Kibővíti a CosmosRepository interfészt, amely a Spring Data-adattár támogatását biztosítja.

@Repository
public interface UserRepository extends CosmosRepository<User, String> {
    Iterable<User> findByFirstName(String firstName);
    long countByFirstName(String firstName);
    User findOne(String id, String lastName);
}
  • findByFirstName A metódus egyéni lekérdezési módszer, a firstName elemenként talál elemeket.

QueryAnnotation: jegyzetekkel ellátott lekérdezések használata az adattárakban

Az Azure Spring Data Cosmos támogatja a jegyzetekkel ellátott lekérdezések megadását az adattárakban a használatával @Query.

Íme néhány példa a széljegyzetes lekérdezésekre szinkronban CosmosRepository:

public interface AnnotatedQueriesUserRepositoryCodeSnippet extends CosmosRepository<User, String> {
    @Query("select * from c where c.firstName = @firstName and c.lastName = @lastName")
    List<User> getUsersByFirstNameAndLastName(@Param("firstName") String firstName, @Param("lastName") String lastName);

    @Query("select * from c offset @offset limit @limit")
    List<User> getUsersWithOffsetLimit(@Param("offset") int offset, @Param("limit") int limit);

    @Query("select value count(1) from c where c.firstName = @firstName")
    long getNumberOfUsersWithFirstName(@Param("firstName") String firstName);
}

Íme néhány példa a jegyzetekkel ellátott lekérdezésekre a következőben ReactiveCosmosRepository:

public interface AnnotatedQueriesUserReactiveRepositoryCodeSnippet extends ReactiveCosmosRepository<User, String> {
    @Query("select * from c where c.firstName = @firstName and c.lastName = @lastName")
    Flux<User> getUsersByTitleAndValue(@Param("firstName") int firstName, @Param("lastName") String lastName);

    @Query("select * from c offset @offset limit @limit")
    Flux<User> getUsersWithOffsetLimit(@Param("offset") int offset, @Param("limit") int limit);

    @Query("select count(c.id) as num_ids, c.lastName from c group by c.lastName")
    Flux<ObjectNode> getCoursesGroupByDepartment();

    @Query("select value count(1) from c where c.lastName = @lastName")
    Mono<Long> getNumberOfUsersWithLastName(@Param("lastName") String lastName);
}

A jegyzetben megadott lekérdezések megegyeznek a Cosmos-lekérdezésekkel. Az SQL-lekérdezésekkel kapcsolatos további információkért tekintse meg a következő cikkeket a Cosmosban:

Alkalmazásosztály létrehozása

Az alábbi példa egy alkalmazásosztályt valósít meg az összes összetevővel.

@SpringBootApplication
public class SampleApplication implements CommandLineRunner {

    @Autowired
    private UserRepository repository;

    @Autowired
    private ApplicationContext applicationContext;

    public static void main(String[] args) {
        SpringApplication.run(SampleApplication.class, args);
    }

    public void run(String... var1) {

        final User testUser = new User("testId", "testFirstName", "testLastName");

        repository.deleteAll();
        repository.save(testUser);

        // to find by Id, please specify partition key value if collection is partitioned
        final User result = repository.findOne(testUser.getId(), testUser.getLastName());

        //  Switch to secondary key
        UserRepositoryConfiguration bean =
            applicationContext.getBean(UserRepositoryConfiguration.class);
        bean.switchToSecondaryKey();

        //  Now repository will use secondary key
        repository.save(testUser);

    }
}

Automatikusan kapcsolja be a UserRepository felületet a mentéshez, törléshez, kereséshez és hasonló műveletek végrehajtásához.

A Spring Data Azure Cosmos DB a CosmosTemplatekeresési és mentési metódusok mögötti lekérdezéseket használja és ReactiveCosmosTemplatehajtja végre. A sablont saját maga is használhatja összetettebb lekérdezésekhez.

Fő fogalmak

CrudRepository és ReactiveCrudRepository

Az Azure Spring Data Cosmos támogatja a ReactiveCrudRepository és a CrudRepository szolgáltatást, amely alapvető CRUD-funkciókat biztosít:

  • save
  • findAll
  • findOne azonosító szerint
  • deleteAll
  • törlés azonosító szerint
  • entitás törlése

Spring Data-széljegyzetek

A tartományosztályban id lévő mezőket 2 módon lehet az Azure Cosmos DB-elem mezőjére leképezni: – a tartományi osztályban lévő mezők megjegyzésekkel való ellátása @Id, a mező a Cosmos DB elemére id lesz leképezve. - a mező nevét állítsa be a következőre id: ez a mező az Azure Cosmos DB Item elemére id lesz leképezve.

Támogatja a sztring típusú UUID-k automatikus létrehozását a @GeneratedValue széljegyzet használatával. A sztring típusú azonosítóval rendelkező entitás id mezőjével @GeneratedValue a beszúrás előtt automatikusan létrehozhat egy véletlenszerű UUID-t.

public class GeneratedIdEntity {

    @Id
    @GeneratedValue
    private String id;

}
  • SpEL-kifejezés és egyéni tároló neve.
    • Alapértelmezés szerint a tároló neve a felhasználói tartományosztály osztályneve lesz. A testreszabáshoz adja hozzá a @Container(containerName="myCustomContainerName") jegyzetet a tartományosztályhoz. A tárolómező spEL-kifejezéseket (pl. container = "${dynamic.container.name}" vagy container = "#{@someBean.getContainerName()}") is támogat a tárolónevek programozott/konfigurációs tulajdonságokon keresztül történő megadásához.
    • Ahhoz, hogy az SpEL-kifejezések megfelelően működjenek, hozzá kell adnia @DependsOn("expressionResolver") a Spring Application osztályhoz.
@SpringBootApplication
@DependsOn("expressionResolver")
public class SampleApplication {

}
  • Az Egyéni IndexingPolicy alapértelmezés szerint az IndexingPolicy beállítást az Azure szolgáltatás állítja be. A testreszabáshoz adjon hozzá széljegyzetet @CosmosIndexingPolicy a tartományi osztályhoz. Ez a széljegyzet 4 testre szabandó attribútummal rendelkezik, lásd:
// Indicate if indexing policy use automatic or not
// Default value is true
boolean automatic() default Constants.DEFAULT_INDEXING_POLICY_AUTOMATIC;

// Indexing policy mode, option Consistent.
IndexingMode mode() default IndexingMode.CONSISTENT;

// Included paths for indexing
String[] includePaths() default {};

// Excluded paths for indexing
String[] excludePaths() default {};

Azure Cosmos DB-partíció

Az Azure-spring-data-cosmos támogatja az Azure Cosmos DB-partíciót.

Ha meg szeretne adni egy partíciókulcs-mezőnek szánt tartományosztálymezőt, egyszerűen jegyzetelje meg.@PartitionKey

CRUD-művelet végrehajtásakor adja meg a partíció értékét.

A CRUD partícióval kapcsolatos további mintáért tekintse meg itt a tesztet

Optimista zárolás

Az Azure-spring-data-cosmos támogatja az optimista zárolást adott tárolók esetében, ami azt jelenti, hogy az elemenkénti upserts/deletes meghiúsul, kivétellel abban az esetben, ha az elemet időközben egy másik folyamat módosítja.

Ha engedélyezni szeretné az optimista zárolást egy tárolóhoz, csak hozzon létre egy sztringmezőt _etag , és jelölje meg a @Version jegyzettel. Tekintse meg a következőket:

@Container(containerName = "myContainer")
public class MyItem {
    String id;
    String data;
    @Version
    String _etag;
}

Egyéni Spring Data-lekérdezés, lapozható és rendezhető

Az Azure-spring-data-cosmos támogatja a spring data egyéni lekérdezéseket, például egy keresési műveletet, például findByAFieldAndBField

Támogatja a Spring Data lapozható, szeletelhető és rendezhető elemét. – Az adatbázisfiókon elérhető kérelemegységek alapján a CosmosDB a kért méretnél kisebb vagy annál kisebb elemeket tud visszaadni. – Mivel a visszaadott elemek száma változó minden iterációban, a felhasználónak nem szabad a totalPageSize függvényre támaszkodnia, és ehelyett a lapozható elemekre való iterálást így kell elvégezni.

private List<T> findAllWithPageSize(int pageSize) {

    final CosmosPageRequest pageRequest = new CosmosPageRequest(0, pageSize, null);
    Page<T> page = repository.findAll(pageRequest);
    List<T> pageContent = page.getContent();
    while (page.hasNext()) {
        Pageable nextPageable = page.nextPageable();
        page = repository.findAll(nextPageable);
        pageContent = page.getContent();
    }
    return pageContent;
}
public interface SliceQueriesUserRepository extends CosmosRepository<User, String> {
    @Query("select * from c where c.lastName = @lastName")
    Slice<User> getUsersByLastName(@Param("lastName") String lastName, Pageable pageable);
}
private List<User> getUsersByLastName(String lastName, int pageSize) {

    final CosmosPageRequest pageRequest = new CosmosPageRequest(0, pageSize, null);
    Slice<User> slice = repository.getUsersByLastName(lastName, pageRequest);
    List<User> content = slice.getContent();
    while (slice.hasNext()) {
        Pageable nextPageable = slice.nextPageable();
        slice = repository.getUsersByLastName(lastName, nextPageable);
        content.addAll(slice.getContent());
    }
    return content;
}

Spring Boot Starter-adat rest

Az Azure-spring-data-cosmos támogatja a spring-boot-starter-data-rest használatát.

  • Támogatja a listázást és a beágyazott típust a tartományi osztályban.
  • Konfigurálható ObjectMapper bean egyedi névvel cosmosObjectMapper, csak akkor konfigurálja a testre szabott ObjectMappert, ha valóban szükség van rá. Például:
@Bean(name = "cosmosObjectMapper")
public ObjectMapper objectMapper() {
    return new ObjectMapper(); // Do configuration to the ObjectMapper if required
}

Naplózás

Az Azure-spring-data-cosmos szabványos spring-data széljegyzetek használatával támogatja az adatbázis-entitások mezőinek naplózását.

Ez a funkció úgy engedélyezhető, hogy széljegyzeteket ad @EnableCosmosAuditing hozzá az alkalmazás konfigurációjához.

Az entitások a @CreatedBy, és @LastModifiedDatea . @CreatedDate@LastModifiedBy Ezek a mezők automatikusan frissülnek.

@Container(containerName = "myContainer")
public class AuditableUser {
    private String id;
    private String firstName;
    @CreatedBy
    private String createdBy;
    @CreatedDate
    private OffsetDateTime createdDate;
    @LastModifiedBy
    private String lastModifiedBy;
    @LastModifiedDate
    private OffsetDateTime lastModifiedByDate;
}

Többadatbázisos konfiguráció

Az Azure-spring-data-cosmos támogatja a többadatbázisos konfigurációt, beleértve a "több adatbázisfiókot" és az "egyetlen fiókot, több adatbázissal".

Több adatbázisos fiókok

A példa az application.properties fájlt használja:

# primary account cosmos config
azure.cosmos.primary.uri=your-primary-cosmosDb-uri
azure.cosmos.primary.key=your-primary-cosmosDb-key
azure.cosmos.primary.secondaryKey=your-primary-cosmosDb-secondary-key
azure.cosmos.primary.database=your-primary-cosmosDb-dbName
azure.cosmos.primary.populateQueryMetrics=if-populate-query-metrics

# secondary account cosmos config
azure.cosmos.secondary.uri=your-secondary-cosmosDb-uri
azure.cosmos.secondary.key=your-secondary-cosmosDb-key
azure.cosmos.secondary.secondaryKey=your-secondary-cosmosDb-secondary-key
azure.cosmos.secondary.database=your-secondary-cosmosDb-dbName
azure.cosmos.secondary.populateQueryMetrics=if-populate-query-metrics

Az entitás és az adattár definíciója a fentihez hasonló. Különböző adatbázis-entitásokat különböző csomagokba helyezhet.

A @EnableReactiveCosmosRepositories Cosmos-sablon felhasználódefiníciója vagy @EnableCosmosRepositories támogatása. Használja reactiveCosmosTemplateRef vagy cosmosTemplateRef konfigurálja annak a babnak CosmosTemplate a ReactiveCosmosTemplate nevét, amelyet az észlelt adattárakkal használ.

Ha több Cosmos-adatbázisfiókkal rendelkezik, több CosmosAsyncClientis definiálható. Ha egyetlen Cosmos-fiók több adatbázissal rendelkezik, ugyanezzel CosmosAsyncClient inicializálhatja a Cosmos-sablont.

@Configuration
@EnableReactiveCosmosRepositories(basePackages = "com.azure.spring.sample.cosmos.multi.database.multiple.account.repository",
    reactiveCosmosTemplateRef = "primaryDatabaseTemplate")
public class PrimaryDatasourceConfiguration extends AbstractCosmosConfiguration{

    private static final String PRIMARY_DATABASE = "primary_database";

    @Bean
    @ConfigurationProperties(prefix = "azure.cosmos.primary")
    public CosmosProperties primary() {
        return new CosmosProperties();
    }

    @Bean
    public CosmosClientBuilder primaryClientBuilder(@Qualifier("primary") CosmosProperties primaryProperties) {
        return new CosmosClientBuilder()
            .key(primaryProperties.getKey())
            .endpoint(primaryProperties.getUri());
    }

    @Bean
    public ReactiveCosmosTemplate primaryDatabaseTemplate(CosmosAsyncClient cosmosAsyncClient,
                                                          CosmosConfig cosmosConfig,
                                                          MappingCosmosConverter mappingCosmosConverter) {
        return new ReactiveCosmosTemplate(cosmosAsyncClient, PRIMARY_DATABASE, cosmosConfig, mappingCosmosConverter);
    }

    @Override
    protected String getDatabaseName() {
        return PRIMARY_DATABASE;
    }
}
@Configuration
@EnableCosmosRepositories(cosmosTemplateRef  = "secondaryDatabaseTemplate")
public class SecondaryDatasourceConfiguration {

    private static final Logger LOGGER = LoggerFactory.getLogger(SecondaryDatasourceConfiguration.class);
    public static final String SECONDARY_DATABASE = "secondary_database";

    @Bean
    @ConfigurationProperties(prefix = "azure.cosmos.secondary")
    public CosmosProperties secondary() {
        return new CosmosProperties();
    }

    @Bean("secondaryCosmosClient")
    public CosmosAsyncClient getCosmosAsyncClient(@Qualifier("secondary") CosmosProperties secondaryProperties) {
        return CosmosFactory.createCosmosAsyncClient(new CosmosClientBuilder()
            .key(secondaryProperties.getKey())
            .endpoint(secondaryProperties.getUri()));
    }

    @Bean("secondaryCosmosConfig")
    public CosmosConfig getCosmosConfig() {
        return CosmosConfig.builder()
            .enableQueryMetrics(true)
            .responseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation())
            .build();
    }

    @Bean
    public CosmosTemplate secondaryDatabaseTemplate(@Qualifier("secondaryCosmosClient") CosmosAsyncClient client,
                                                    @Qualifier("secondaryCosmosConfig") CosmosConfig cosmosConfig,
                                                    MappingCosmosConverter mappingCosmosConverter) {
        return new CosmosTemplate(client, SECONDARY_DATABASE, cosmosConfig, mappingCosmosConverter);
    }

    private static class ResponseDiagnosticsProcessorImplementation implements ResponseDiagnosticsProcessor {

        @Override
        public void processResponseDiagnostics(@Nullable ResponseDiagnostics responseDiagnostics) {
            LOGGER.info("Response Diagnostics {}", responseDiagnostics);
        }
    }
}

A fenti példában két Cosmos-fiókunk van. A következőképpen hozhatja létre a CosmosAsyncClient következőt:

@Bean("secondaryCosmosClient")
public CosmosAsyncClient getCosmosAsyncClient(@Qualifier("secondary") CosmosProperties secondaryProperties) {
    return CosmosFactory.createCosmosAsyncClient(new CosmosClientBuilder()
        .key(secondaryProperties.getKey())
        .endpoint(secondaryProperties.getUri()));
}

@Bean("secondaryCosmosConfig")
public CosmosConfig getCosmosConfig() {
    return CosmosConfig.builder()
        .enableQueryMetrics(true)
        .responseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation())
        .build();
}

Ha definiálni queryMetricsEnabled szeretné vagy ResponseDiagnosticsProcessorszeretné, létrehozhatja a CosmosConfig Cosmos-sablont.

@Bean("secondaryCosmosConfig")
public CosmosConfig getCosmosConfig() {
    return CosmosConfig.builder()
        .enableQueryMetrics(true)
        .responseDiagnosticsProcessor(new ResponseDiagnosticsProcessorImplementation())
        .build();
}

Hozzon létre egy osztályt Application :

@SpringBootApplication
public class MultiDatabaseApplication implements CommandLineRunner {

    @Autowired
    private CosmosUserRepository cosmosUserRepository;

    @Autowired
    private MysqlUserRepository mysqlUserRepository;

    @Autowired
    @Qualifier("secondaryDatabaseTemplate")
    private CosmosTemplate secondaryDatabaseTemplate;

    @Autowired
    @Qualifier("primaryDatabaseTemplate")
    private ReactiveCosmosTemplate primaryDatabaseTemplate;

    private final CosmosUser cosmosUser = new CosmosUser("1024", "1024@geek.com", "1k", "Mars");
    private static CosmosEntityInformation<CosmosUser, String> userInfo = new CosmosEntityInformation<>(CosmosUser.class);

    public static void main(String[] args) {
        SpringApplication.run(MultiDatabaseApplication.class, args);
    }

    public void run(String... var1) throws Exception {

        CosmosUser cosmosUserGet = primaryDatabaseTemplate.findById(cosmosUser.getId(), cosmosUser.getClass()).block();
        // Same to this.cosmosUserRepository.findById(cosmosUser.getId()).block();
        MysqlUser mysqlUser = new MysqlUser(cosmosUserGet.getId(), cosmosUserGet.getEmail(), cosmosUserGet.getName(), cosmosUserGet.getAddress());
        mysqlUserRepository.save(mysqlUser);
        mysqlUserRepository.findAll().forEach(System.out::println);
        CosmosUser secondaryCosmosUserGet = secondaryDatabaseTemplate.findById(CosmosUser.class.getSimpleName(), cosmosUser.getId(), CosmosUser.class);
        System.out.println(secondaryCosmosUserGet);
    }


    @PostConstruct
    public void setup() {
        primaryDatabaseTemplate.createContainerIfNotExists(userInfo).block();
        primaryDatabaseTemplate.insert(CosmosUser.class.getSimpleName(), cosmosUser, new PartitionKey(cosmosUser.getName())).block();
        // Same to this.cosmosUserRepository.save(user).block();
        secondaryDatabaseTemplate.createContainerIfNotExists(userInfo);
        secondaryDatabaseTemplate.insert(CosmosUser.class.getSimpleName(), cosmosUser, new PartitionKey(cosmosUser.getName()));
   }

    @PreDestroy
    public void cleanup() {
        primaryDatabaseTemplate.deleteAll(CosmosUser.class.getSimpleName(), CosmosUser.class).block();
        // Same to this.cosmosUserRepository.deleteAll().block();
        secondaryDatabaseTemplate.deleteAll(CosmosUser.class.getSimpleName() , CosmosUser.class);
        mysqlUserRepository.deleteAll();
    }
}

Egyetlen fiók több adatbázissal

A példa az application.properties fájlt használja:

azure.cosmos.uri=your-cosmosDb-uri
azure.cosmos.key=your-cosmosDb-key
azure.cosmos.secondary-key=your-cosmosDb-secondary-key
azure.cosmos.database=your-cosmosDb-dbName
azure.cosmos.populate-query-metrics=if-populate-query-metrics

Az entitás és az adattár definíciója a fentihez hasonló. Különböző adatbázis-entitásokat különböző csomagokba helyezhet.

A különbözőekkel reactiveCosmosTemplateRef több adatbázist is definiálhat EnableReactiveCosmosRepositories egyetlen Cosmos-fiókban.

@Configuration
public class DatasourceConfiguration {

    private static final String DATABASE1 = "database1";
    private static final String DATABASE2 = "database2";

    @Bean
    public CosmosProperties cosmosProperties() {
        return new CosmosProperties();
    }

    @Bean
    public CosmosClientBuilder primaryClientBuilder(CosmosProperties cosmosProperties) {
        return new CosmosClientBuilder()
            .key(cosmosProperties.getKey())
            .endpoint(cosmosProperties.getUri());
    }

    @EnableReactiveCosmosRepositories(basePackages = "com.azure.spring.sample.cosmos.multi.database.repository1",
        reactiveCosmosTemplateRef = "database1Template")
    public class Database1Configuration extends AbstractCosmosConfiguration {

        @Bean
        public ReactiveCosmosTemplate database1Template(CosmosAsyncClient cosmosAsyncClient,
                                                              CosmosConfig cosmosConfig,
                                                              MappingCosmosConverter mappingCosmosConverter) {
            return new ReactiveCosmosTemplate(cosmosAsyncClient, DATABASE1, cosmosConfig, mappingCosmosConverter);
        }

        @Override
        protected String getDatabaseName() {
            return DATABASE1;
        }
    }

    @EnableReactiveCosmosRepositories(basePackages = "com.azure.spring.sample.cosmos.multi.database.repository2",
        reactiveCosmosTemplateRef = "database2Template")
    public class Database2Configuration {

        @Bean
        public ReactiveCosmosTemplate database2Template(CosmosAsyncClient cosmosAsyncClient,
                                                              CosmosConfig cosmosConfig,
                                                              MappingCosmosConverter mappingCosmosConverter) {
            return new ReactiveCosmosTemplate(cosmosAsyncClient, DATABASE2, cosmosConfig, mappingCosmosConverter);
        }

    }
}

Hozzon létre egy osztályt Application :

@SpringBootApplication
public class MultiDatabaseApplication implements CommandLineRunner {

    @Autowired
    private User1Repository user1Repository;

    @Autowired
    @Qualifier("database1Template")
    private ReactiveCosmosTemplate database1Template;

    @Autowired
    @Qualifier("database2Template")
    private ReactiveCosmosTemplate database2Template;

    private final User1 user1 = new User1("1024", "1024@geek.com", "1k", "Mars");
    private static CosmosEntityInformation<User1, String> user1Info = new CosmosEntityInformation<>(User1.class);

    private final User2 user2 = new User2("2048", "2048@geek.com", "2k", "Mars");
    private static CosmosEntityInformation<User2, String> user2Info = new CosmosEntityInformation<>(User2.class);


    public static void main(String[] args) {
        SpringApplication.run(MultiDatabaseApplication.class, args);
    }

    public void run(String... var1) throws Exception {

        User1 database1UserGet = database1Template.findById(User1.class.getSimpleName(), user1.getId(), User1.class).block();
        // Same to userRepository1.findById(user.getId()).block()
        System.out.println(database1UserGet);
        User2 database2UserGet = database2Template.findById(User2.class.getSimpleName(), user2.getId(), User2.class).block();
        System.out.println(database2UserGet);
    }

    @PostConstruct
    public void setup() {
        database1Template.createContainerIfNotExists(user1Info).block();
        database1Template.insert(User1.class.getSimpleName(), user1, new PartitionKey(user1.getName())).block();
        // Same to this.userRepository1.save(user).block();
        database2Template.createContainerIfNotExists(user2Info).block();
        database2Template.insert(User2.class.getSimpleName(), user2, new PartitionKey(user2.getName())).block();
    }

    @PreDestroy
    public void cleanup() {
        database1Template.deleteAll(User1.class.getSimpleName(), User1.class).block();
        // Same to this.userRepository1.deleteAll().block();
        database2Template.deleteAll(User2.class.getSimpleName(), User2.class).block();
    }
}

Bétaverziós csomag

Az ágból master létrehozott bétaverziók elérhetők. Tekintse meg a bétaverziós csomagok használatára vonatkozó utasításokat .

Hibaelhárítás

Általános kérdések

Ha bármilyen hibába ütközik, kérjük, jelentse be a problémát itt.

Ha új funkciót vagy módosításokat szeretne javasolni, ugyanúgy jelentse be a problémát, mint egy hiba esetén.

Ügyfélnaplózás engedélyezése

Az Azure-spring-data-cosmos az SLF4j-t használja naplózási homlokzatként, amely támogatja a népszerű naplózási keretrendszerekbe, például a log4j-be és a logbackbe való bejelentkezést. Ha például a spring logbacket szeretné naplózási keretrendszerként használni, adja hozzá a következő XML-t az erőforrások mappához.

<configuration>
  <include resource="/org/springframework/boot/logging/logback/base.xml"/>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
      </pattern>
    </encoder>
  </appender>
  <root level="info">
    <appender-ref ref="STDOUT"/>
  </root>
  <logger name="com.azure.cosmos" level="error"/>
  <logger name="org.springframework" level="error"/>
  <logger name="io.netty" level="error"/>
  <!-- This will enable query logging, to include query parameter logging, set this logger to TRACE -->  
  <logger name="com.azure.cosmos.implementation.SqlQuerySpecLogger" level="DEBUG"/>  
</configuration>

Példák

Tekintse meg itt a mintaprojektet.

Több adatbázisos fiókok

Tekintse meg a többadatbázisos mintaprojektet.

Egyetlen fiók több adatbázissal

Tekintse meg a többadatbázisos mintaprojekttel rendelkező önálló fiókot.

Következő lépések

Közreműködés

A projektben szívesen fogadjuk a hozzájárulásokat és a javaslatokat. A legtöbb hozzájárulás megköveteli, hogy elfogadja a közreműködői licencszerződést (CLA), amelyben kijelenti, hogy ön jogosult arra, és ténylegesen meg is adja nekünk a hozzájárulás használatára vonatkozó jogokat.

A lekéréses kérelmek elküldésekor egy CLA-robot automatikusan meghatározza, hogy kell-e biztosítania CLA-t, és megfelelően kitölti a lekéréses kérelmet (például címke, megjegyzés). Egyszerűen csak kövesse a robot által megadott utasításokat. Ezt csak egyszer kell elvégeznie az összes olyan tárházban, amely a CLA-t használja.

A projekt a Microsoft nyílt forráskódú projekteket szabályozó etikai kódexe, a Microsoft Open Source Code of Conduct hatálya alá esik. További információért tekintse meg a viselkedési szabályzat gyik- vagy kapcsolatfelvételi útmutatóját, vagy vegye fel a kapcsolatot opencode@microsoft.com az esetleges további kérdésekkel vagy megjegyzésekkel.

Impressions