原标题:Spring认证中国教育管理中心-Spring Data Couchbase教程九(Spring中国教育管理中心)
5.3.2.自动索引管理
默认情况下,预计用户会为其查询创建和管理最佳索引。尤其是在开发初期,自动创建索引可以快速上手。
对于 N1QL,提供了以下注释,这些注释需要附加到实体(在类或字段上):
@QueryIndexed: 放置在一个字段上,表示该字段应该是索引的一部分
@CompositeQueryIndex:放置在类上,表示应该在多个字段(复合)上创建索引。
@CompositeQueryIndexes:如果CompositeQueryIndex应该创建多个,则此注释将采用它们的列表。
例如,这是您在实体上定义复合索引的方式:
示例 79. 两个字段的复合索引具有排序
@Document
@CompositeQueryIndex(fields = {"id", "name desc"})
public class Airline {
@Id
String id;
@QueryIndexed
String name;
@PersistenceConstructor
public Airline(String id, String name) {
this.id = id;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
}
默认情况下,索引创建被禁用。如果要启用它,则需要在配置中覆盖它:
示例 80.启用自动索引创建
@Override
protected boolean autoIndexCreation() {
return true;
}
5.3.3.查询一致性
默认情况下,使用 N1QL 的存储库查询使用NOT_BOUNDED扫描一致性。这意味着结果会快速返回,但来自索引的数据可能还不包含来自先前写入操作的数据(称为最终一致性)。如果您需要查询的“准备好自己的写入”语义,则需要使用@ScanConsistency注释。这是一个例子:
示例 81. 使用不同的扫描一致性
@Repository
public interface AirportRepository extends PagingAndSortingRepository {
@Override
@ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS)
Iterable findAll();
}
5.3.4.DTO 预测
Spring Data Repositories 通常在使用查询方法时返回域模型。但是,有时,您可能出于各种原因需要更改该模型的视图。在本节中,您将学习如何定义投影以提供简化和简化的资源视图。
看下面的域模型:
@Entity
public class Person {
@Id @GeneratedValue
private Long id;
private String firstName, lastName;
@OneToOne
private Address address;
…
}
@Entity
public class Address {
@Id @GeneratedValue
private Long id;
private String street, state, country;
…
}
这Person有几个属性:
id 是主键
firstName并且lastName是数据属性
address 是指向另一个域对象的链接
现在假设我们创建一个相应的存储库,如下所示:
interface PersonRepository extends CrudRepository {
Person findPersonByFirstName(String firstName);
}
Spring Data 将返回包含其所有属性的域对象。有两个选项可以检索address属性。一种选择是为这样的Address对象定义一个存储库:
interface AddressRepository extends CrudRepository {}
在这种情况下,usingPersonRepository仍然会返回整个Person对象。使用AddressRepository将只返回Address.
但是,如果您根本不想暴露address细节怎么办?您可以通过定义一个或多个投影来为您的存储库服务的使用者提供一种替代方案。
示例 82. 简单投影
interface NoAddresses {
String getFirstName();
String getLastName();
}
此投影具有以下详细信息:
一个普通的 Java 接口,使其具有声明性。
导出firstName.
导出lastName.
该NoAddresses投影仅拥有干将firstName和lastName这意味着它不会成为的任何地址信息。在这种情况下,查询方法定义返回NoAdresses而不是Person.
interface PersonRepository extends CrudRepository {
NoAddresses findByFirstName(String firstName);
}
投影声明了基础类型和与公开属性相关的方法签名之间的契约。因此需要根据底层类型的属性名称来命名 getter 方法。如果基础属性是 named firstName,那么 getter 方法必须被命名,getFirstName否则 Spring Data 无法查找源属性。
6. 反应式 Couchbase 存储库
6.1。介绍
本章描述了对 couchbase 的响应式存储库支持。这建立在Couchbase 存储库中解释的核心存储库支持之上。因此,请确保您对那里解释的基本概念有充分的理解。
6.2.反应式组合库
Couchbase Java SDK 3.x 从 RxJava 迁移到 Reactor,因此它与响应式 Spring 生态系统完美融合。
Reactive Couchbase 存储库提供项目 Reactor 包装器类型,并且可以通过简单地从特定于库的存储库接口之一扩展来使用:
ReactiveCrud 存储库
反应式排序存储库
6.3.用法
让我们创建一个简单的实体开始:
示例 83. 示例 Person 实体
public class Person {
@Id
private String id;
private String firstname;
private String lastname;
private Address address;
// … getters and setters omitted
}
相应的存储库实现可能如下所示:
示例 84. 持久化 Person 实体的基本存储库接口
public interface ReactivePersonRepository extends ReactiveSortingRepository {
Flux findByFirstname(String firstname);
Flux findByFirstname(Publisher firstname);
Flux findByFirstnameOrderByLastname(String firstname, Pageable pageable);
Mono findByFirstnameAndLastname(String firstname, String lastname);
}
对于 JavaConfig,请使用@
EnableReactiveCouchbaseRepositories注解。注释带有与命名空间元素相同的属性。如果没有配置基本包,基础设施将扫描带注释的配置类的包。
另请注意,如果您在 Spring Boot 设置中使用它,您可能可以省略注释,因为它是为您自动配置的。
示例 85. 存储库的 JavaConfig
@Configuration
@EnableReactiveCouchbaseRepositories
class ApplicationConfig extends AbstractCouchbaseConfiguration {
// ... (see configuration for details)
}
随着我们的域存储库的扩展,ReactiveSortingRepository它为您提供了 CRUD 操作以及对实体进行排序访问的方法。使用存储库实例只是将依赖项注入客户端的问题。
示例 86. 对 Person 实体的排序访问
public class PersonRepositoryTests {
@Autowired
ReactivePersonRepository repository;
@Test
public void sortsElementsCorrectly() {
Flux persons = repository.findAll(Sort.by(new Order(ASC, "lastname")));
assertNotNull(perons);
}
}
6.4.存储库和查询
Spring Data 的 Reactive Couchbase 带有阻塞存储库和查询已经提供的完整查询支持
7. 模板&直接操作
该模板提供了对底层数据库的较低级别的访问,并且还用作存储库的基础。每当存储库对您的需要来说太高级时,模板将为您提供良好服务的机会很大。请注意,您始终可以通过在
AbstractCouchbaseConfiguration.
7.1。支持的操作
模板可以通过couchbaseTemplate和
reactiveCouchbaseTemplatebean访问您的上下文。一旦获得了对它的引用,就可以对它运行各种操作。除了通过存储库之外,您还需要在模板中始终指定要转换的目标实体类型。
模板使用流式 API,允许您根据需要链接可选运算符。例如,以下是您存储用户然后通过其 ID 再次找到它的方式:
示例 87. 流畅的模板访问
// Create an Entity
User user = new User(UUID.randomUUID().toString(), "firstname", "lastname");
// Upsert it
couchbaseTemplate.upsertById(User.class).one(user);
// Retrieve it again
User found = couchbaseTemplate.findById(User.class).one(user.getId());
如果您想对操作使用自定义持久性要求,upsert您可以将其链接到:
示例 88. 具有持久性的 Upsert
User modified = couchbaseTemplate
.upsertById(User.class)
.withDurability(DurabilityLevel.MAJORITY)
.one(user);
以类似的方式,您可以执行 N1QL 操作:
示例 89. 模板上的 N1QL 查询
final List foundUsers = couchbaseTemplate
.findByQuery(User.class)
.consistentWith(QueryScanConsistency.REQUEST_PLUS)
.all();
8.交易支持
Couchbase 支持分布式事务。本节介绍如何将它与 Spring Data Couchbase 一起使用。
8.1。要求
Couchbase 服务器 6.5 或更高版本。
Couchbase Java 客户端 3.0.0 或更高版本。建议遵循 maven 交易库的传递依赖。
应该配置 NTP,以便 Couchbase 集群的节点与时间同步。时间不同步不会导致错误行为,但会影响元数据清理。
8.2.入门和配置
如果正在使用 maven(或等效项),则couchbase-transactions需要将工件包含在您的文件中pom.xml。
团体: com.couchbase.client
神器: couchbase-transactions
版本:最新版本,即 1.0.0
一旦它被包含在您的项目中,您需要创建一个Transactions对象。方便的是,它可以成为您的 spring data
couchbaseAbstractCouchbaseConfiguration实现的一部分:
例 90. 事务配置
@Configuration
static class Config extends AbstractCouchbaseConfiguration {
// Usual Setup
@Override public String getConnectionString() { /* ... */ }
@Override public String getUserName() { /* ... */ }
@Override public String getPassword() { /* ... */ }
@Override public String getBucketName() { /* ... */ }
@Bean
public Transactions transactions(final Cluster couchbaseCluster) {
return Transactions.create(couchbaseCluster, TransactionConfigBuilder.create()
// The configuration can be altered here, but in most cases the defaults are fine.
.build());
}
}
一旦@Bean配置,你可以从你的服务(或任何其他类),自动装配它来使用它。请参阅参考文档 了解如何使用Transactions该类。由于您还需要访问电流Collection,我们建议您也自动CouchbaseClientFactory连接并从那里访问它:
示例 91. 事务访问
@Autowired
Transactions transactions;
@Autowired
CouchbaseClientFactory couchbaseClientFactory;
public void doSomething() {
transactions.run(ctx -> {
ctx.insert(couchbaseClientFactory.getDefaultCollection(), "id", "content");
ctx.commit();
});
}
8.3.对象转换
由于事务库本身不了解您的 spring 数据实体类型,因此您需要在读/写时来回转换才能正确交互。幸运的是,您需要做的就是自动装配MappingCouchbaseConverter并使用它:
示例 92. 写入时的事务转换
@Autowired
MappingCouchbaseConverter mappingCouchbaseConverter;
public void doSomething() {
transactions.run(ctx -> {
Airline airline = new Airline("demo-airline", "at");
CouchbaseDocument target = new CouchbaseDocument();
mappingCouchbaseConverter.write(airline, target);
ctx.insert(couchbaseClientFactory.getDefaultCollection(), target.getId(), target.getContent());
ctx.commit();
});
}
读取时可以使用相同的方法:
示例 93. 读取时的事务转换
TransactionGetResult getResult = ctx.get(couchbaseClientFactory.getDefaultCollection(), "doc-id");
CouchbaseDocument source = new CouchbaseDocument(getResult.id());
source.setContent(getResult.contentAsObject());
Airline read = mappingCouchbaseConverter.read(Airline.class, source);
我们还在研究将事务库更紧密地集成到 Spring 数据库生态系统中。:leveloffset: -1