9.2 Working with NoSQL(Spring Boot 3.1.5 Reference 翻译)

131 阅读8分钟

9.2. Working with NoSQL Technologies

Spring Data提供了一些额外的项目以简化你使用NoSQL技术的成本。对NoSQL数据库的支持如下

在其中,SpringBoot为 Cassandra, Couchbase, Elasticsearch, LDAP, MongoDB, Neo4J and Redis提供了自动配置。除此之外,Spring Boot for Apache Geode为Apache Geode提供了自动配置。当然你也可以通过其他项目来使用NoSQL,但毫无疑问你需要自己对其进行配置。访问spring.io/projects/sp….已查阅相应的文档。

SpringBoot之前还为InfluxDB提供了自动配置,但是已经被废弃,因为 新的InfluxDB Java客户端提供了自己的SpringBoot集成方式。

9.2.1 Redis

Redis 是一个缓存,消息中间件。Spring 为 Lettuce and Jedis 提供了基本的自动配置,以及由Spring Data Redis提供的更高层次抽象。

默认情况下,spring-boot-starter-data-redis“Starter“使用Lettuce,可同时在传统或者reactive应用中使用。

Tip

我们同样提供了spring-boot-starter-data-redis-reactive,为了和其他提供reactive支持的NoSQL数据库一致。

Connecting to Redis

可以将已经自动配置的 RedisConnectionFactory, StringRedisTemplate, or vanilla RedisTemplate bean注入到你的代码。像下面一样

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final StringRedisTemplate template;

    public MyBean(StringRedisTemplate template) {
        this.template = template;
    }

    public Boolean someMethod() {
        return this.template.hasKey("spring");
    }
}

默认情况下,会连接到localhost:6379的redis server,可以通过spring.data.redis.*的配置项进行修改

spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.database=0
spring.data.redis.username=user
spring.data.redis.password=secret

Tip

你可以注册些LettuceClientConfigurationBuilderCustomizer的实现类的bean来进行更高级的自定义。还可以用ClientResourcesBuilderCustomizer来对ClientResources进行自定义。如果你使用的是Jedis,可以使用JedisClientConfigurationBuilderCustomizer。或者,你可以注册RedisStandaloneConfigurationRedisSentinelConfigurationRedisClusterConfiguration来完全控制配置。

默认情况下,如果commons-pool2是在classpath时,SpringBoot会自动配置一个连接池。

自动配置的连接池可以通过下面示例配置来使用SSL通信

spring.data.redis.ssl.enabled=true

可以在SSL bundle中配置SSL信任并应用到RedisConnectionFactory

spring.data.redis.ssl.bundle=example

9.2.2 MongoDB

MongoDB是一个开源的NOSQL文档数据库,使用了JSON-like的模式而不是传统的基于表的关系数据。SpringBoot提供了spring-boot-starter-data-mongodb and spring-boot-starter-data-mongodb-reactive “Starters”来简化MongoDB的使用。

Connecting to a MongoDB Database

你可以注入自动配置org.springframework.data.mongodb.MongoDatabaseFactory来访问MongoDB。默认情况下,会尝试连接到mongodb://localhost/test,如下示例展示了怎样连接到一个MongoDB数据库

import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;

import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final MongoDatabaseFactory mongo;

    public MyBean(MongoDatabaseFactory mongo) {
        this.mongo = mongo;
    }

    public MongoCollection<Document> someMethod() {
        MongoDatabase db = this.mongo.getMongoDatabase();
        return db.getCollection("users");
    }
}

如果自定义了自己的MongoClient,那么将使用你自定义来配置MongoDatabaseFactory

自动配置的MongoClient使用MongoClientSettings来创建。如果你自己定义了MongoClientSettings,那么将使用你自己自定义并且spring.data.mongodb配置项将会被忽略。否则,SpringBoot将会自动配置一个MongoClientSettings并应用spring.data.mongodb配置项。无论哪种方式,你都可以定义一个或多个MongoClientSettingsBuilderCustomizer来调整MongoClientSettings配置,每一个都会被MongoClientSettings.Builder按照 顺序调用来构件MongoClientSettings

你可以使用 spring.data.mongodb.uri配置项来修改URL,如下所示

spring.data.mongodb.uri=mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test

或者,你可以使用分散的配置项进行配置,如下所示

spring.data.mongodb.host=mongoserver1.example.com
spring.data.mongodb.port=27017
spring.data.mongodb.additional-hosts[0]=mongoserver2.example.com:23456
spring.data.mongodb.database=test
spring.data.mongodb.username=user
spring.data.mongodb.password=secret

自动配置的MongoClient可以通过如下设置来使用SSL

spring.data.mongodb.uri=mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test
spring.data.mongodb.ssl.enabled=true

可以通过在 SSL bundle 中配置自定义SSL 信任材料

spring.data.mongodb.uri=mongodb://user:secret@mongoserver1.example.com:27017,mongoserver2.example.com:23456/test
spring.data.mongodb.ssl.bundle=example

Tip

如果未指定spring.data.mongodb.port。可以通过host:port这种语法来修改端口,这种方式在修改additional-hosts的端口时会被用到。

Tip

如果你不使用Spring Data MongoDB,你可以注入MongoClient而不使用MongoDatabaseFactory。如果你想要完全控制MongoDB连接的建立,你可以声明自己的 MongoDatabaseFactory 或者 MongoClient bean。

MongoTemplate

Spring Data MongoDB 提供了一个MongoTemplate,它和Spring的JdbcTemplate非常相似。你可以直接注入使用。

import com.mongodb.client.MongoCollection;
import org.bson.Document;

import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final MongoTemplate mongoTemplate;

    public MyBean(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    public MongoCollection<Document> someMethod() {
        return this.mongoTemplate.getCollection("users");
    }

}

Spring Data MongoDB Repository

Spring Data包含了对MongoDB的repository支持。与前面讨论的JPA一样,都是基于方法的名称来自动构建查询语句。

实际上,Spring Data JPA和Spring Data MongoDB共享一套基础设施。拿之前的JPA案例来说,如果City现在是MongoDB的data class而不是JPA的@Entity。name下面代码同样会生效

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;

public interface CityRepository extends Repository<City, Long> {

    Page<City> findAll(Pageable pageable);

    City findByNameAndStateAllIgnoringCase(String name, String state);

}

Repositorie和data class都可以通过扫描发现,默认情况下,会扫描auto-configuration包下的,你可以通过@EnableMongoRepositories and @EntityScan来自定义扫描位置。

Tip

更多关于Spring Data MongoDB的细节,包含其丰富的对象映射技术,可参阅reference documentation

9.2.3 Neo4j

Neo4j是一个开源的NoSQL图数据库,相比于传统的RDBMS方法更适合连接大数据。SpringBoot为Neo4j提供了spring-boot-starter-data-neo4j “Starter”,简化Neo4j的使用。

Connecting to a Neo4j Database

为了使用Neo4j,你可以注入自动配置好的org.neo4j.driver.Driver。默认情况下,该实例会尝试连接到localhost:7687的Neo4j server,使用bolt协议。如下所示

import org.neo4j.driver.Driver;
import org.neo4j.driver.Session;
import org.neo4j.driver.Values;

import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final Driver driver;

    public MyBean(Driver driver) {
        this.driver = driver;
    }

    public String someMethod(String message) {
        try (Session session = this.driver.session()) {
            return session.executeWrite(
                    (transaction) -> transaction
                        .run("CREATE (a:Greeting) SET a.message = $message RETURN a.message + ', from node ' + id(a)",
                                Values.parameters("message", message))
                        .single()
                        .get(0)
                        .asString());
        }
    }
}

你可以使用 spring.neo4j.*配置项来对其进行自定义修改

spring.neo4j.uri=bolt://my-server:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=secret

自动配置的Driver是使用ConfigBuilder创建的。你可以声明一个或多个ConfigBuilderCustomizer来进行自定义。ConfigBuilder会按照顺序 进行调用来构建Driver

Spring Data Neo4j Repositories

Spring Data为Neo4j提供了repository支持。更多细节请查阅reference documentation

Spring Data Neo4j与Spring Data Jpa以及其他Spring Data模块一样共享通用的基础设施。你可以拿前面的JPA为例,定义City为Spring Data Neo4j的@Node而不是JPA的@Entity,repository还会正常工作

import java.util.Optional;

import org.springframework.data.neo4j.repository.Neo4jRepository;

public interface CityRepository extends Neo4jRepository<City, Long> {

    Optional<City> findOneByNameAndState(String name, String state);

}

spring-boot-starter-data-neo4j “Starter”不仅为repository提供了支持,还为事务管理提供了支持。SpringBoot即支持传统的也支持reactive的Neo4j repository,使用Neo4jTemplateReactiveNeo4jTemplate beans。当Project Reactor在classpath中时,reactive风格的也会被自动配置。

repository和entity都是通过扫描注册的。默认情况下,会扫描auto-configuration包下的。你可以使用@EnableNeo4jRepositories and @EntityScan注解来自定义位置。

Note

当应用使用reactive模式时,并没有对ReactiveTransactionManager自动配置,为了启用事务管理,下面的bean必须被定义。

import org.neo4j.driver.Driver;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.core.ReactiveDatabaseSelectionProvider;
import org.springframework.data.neo4j.core.transaction.ReactiveNeo4jTransactionManager;

@Configuration(proxyBeanMethods = false)
public class MyNeo4jConfiguration {

    @Bean
    public ReactiveNeo4jTransactionManager reactiveTransactionManager(Driver driver,
            ReactiveDatabaseSelectionProvider databaseNameProvider) {
        return new ReactiveNeo4jTransactionManager(driver, databaseNameProvider);
    }

}

9.2.4 Elasticsearch

Elasticsearch是一个开源的,分布式的,Restful搜索的搜索分析引擎。SpringBoot为Elasticsearch客户端提供了基本的自动配置。

SpringBoot支持多个客户端

  • 官方的底层REST客户端
  • 官方的Java API客户端
  • Spring Data Elasticsearch提供的ReactiveElasticsearchClient

SpringBoot提供了专门的Starter: spring-boot-starter-data-elasticsearch

Connecting to Elasticsearch Using REST clients

Elasticsearch提供了两种不同的REST客户端:org.elasticsearch.client:elasticsearch-rest-client提供的low-level clientco.elastic.clients:elasticsearch-java提供的Java API client。除此之外,SpringBoot还提供了 由org.springframework.data:spring-data-elasticsearch提供的reactive client。默认情况下,客户端会访问localhost:9200,你可以通过spring.elasticsearch.*配置项进行修改。

spring.elasticsearch.uris=https://search.example.com:9200
spring.elasticsearch.socket-timeout=10s
spring.elasticsearch.username=user
spring.elasticsearch.password=secret

Connecting to Elasticsearch Using RestClient

如果elasticsearch-rest-client在你的classpath下,SpringBoot会进行自动配置并注册一个RestClientbean。除了上面的配置项外,你可以定义实现RestClientBuilderCustomizer接口的类来对RestClient进行调整。要想完全控制client的配置,定义一个RestClientBuilderbean。

除此之外,如果elasticsearch-rest-client-sniffer在你的classpath下,Sniffer会被自动配置去返现Elasticsearch 集群的节点,并把它们设置进RestClientbean。要想调整Sniffer相关配置像下面一样。

spring.elasticsearch.restclient.sniffer.interval=10m
spring.elasticsearch.restclient.sniffer.delay-after-failure=30s

Connecting to Elasticsearch Using ElasticsearchClient

如果co.elastic.clients:elasticsearch-java在classpath下,SpringBoot会自动配置并注册一个ElasticsearchClientbean。

ElasticsearchClient所用的传输依赖之前所说的RestClient。因此,之前所说的配置项可以用来配置ElasticsearchClient。此外,你可以定义一个RestClientOptionsbean来进一步控制传输的行为。

Connecting to Elasticsearch using ReactiveElasticsearchClient

Spring Data Elasticsearch提供了ReactiveElasticsearchClient来以reactive的方式进行访问。如果 Spring Data Elasticsearch 和Reactor 在你的classpath下,SpringBoot会自动配置并注册一个ReactiveElasticsearchClient

ReactiveElasticsearchclient 所用的传输依赖之前所说的RestClient。因此,之前所说的配置项可以用来配置ReactiveElasticsearchClient。此外,你可以定义一个RestClientOptionsbean来进一步控制传输的行为。

Connecting to Elasticsearch by Using Spring Data

为了连接到Elasticsearch,一个ElasticsearchClientbean必须被定义,无论是通过SpringBoot自动配置还是手动定义。有了这个配置,就可以注入使用ElasticsearchTemplatebean。

import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final ElasticsearchTemplate template;

    public MyBean(ElasticsearchTemplate template) {
        this.template = template;
    }

    public boolean someMethod(String id) {
        return this.template.exists(id, User.class);
    }
}

如果有了spring-data-elasticsearch和Reactor,SpringBoot还会自动配置 ReactiveElasticsearchClientReactiveElasticsearchTemplate 为bean。

Spring Data Elasticsearch Repositories

Spring Data 为Elasticsearch提供了repository支持,就像之前的JPA repository一样,会根据方法名称自动构建查询。

实际上,Spring Data JPA和Spring Data Elasticsearch共享一套基础设施。那之前的JPA为例,让City现在是Elasticsearch的@Document类而不是JPA的@Entity,照样会正常运行。

Repositories 和 documents都是通过扫描注册的,默认会扫描auto-configuration包。你可以使用@EnableElasticsearchRepositories and @EntityScan来配置要扫描的位置。

Tip

关于Spring Data Elasticsearch,请查阅reference documentation

SpringBoot的Elasticsearch repositories既支持传统的也支持reactive的,即使用ElasticsearchRestTemplateReactiveElasticsearchTemplatebean。

如果你希望Elasticsearch repositories使用你自己的template,那么你可以添加自己的ElasticsearchRestTemplate或者ElasticsearchOperationsbean,只要它被命名为”elasticsearchTemplate“。同样的适用于ReactiveElasticsearchTemplateReactiveElasticsearchOperations,名称为”reactiveElasticsearchTemplate“。

也可以使用下面的配置来禁用调repositories。

spring.data.elasticsearch.repositories.enabled=false