Spring认证中国教育管理中心-Spring Data Couchbase教程一

_原题是:Spring认证中国教育管理中心-Spring Data Couchbase教程一(Spring中国教育管理中心)
Spring Data Couchbase教程一
1.1安装
所有用于生产的版本都分布在 Maven Central 和 Spring 发布存储库中。因此,可以像任何其他 maven 依赖项一样包含该库:
示例 1. 通过 maven 包含依赖
【Spring认证中国教育管理中心-Spring Data Couchbase教程一】

org.springframework.data spring-data-couchbase 4.2.5


这将引入几个依赖项,包括底层的 Couchbase Java SDK、常见的 Spring 依赖项以及 Jackson 作为 JSON 映射基础设施。
您还可以从Spring 快照存储库(
https://repo.spring.io/libs-s...) 中获取快照,并从Spring 里程碑存储库(https://repo.spring.io/libs-m...) 中获取里程碑版本。这是一个关于如何使用当前 SNAPSHOT 依赖项的示例:
示例 2. 使用快照版本

org.springframework.data
spring-data-couchbase
4.3.0-SNAPSHOT


spring-libs-snapshot
Spring Snapshot Repository
https://repo.spring.io/libs-s...

一旦你在类路径上获得了所有需要的依赖项,你就可以开始配置它了。仅支持 Java 配置(XML 配置已在 4.0 中删除)。
1.2.基于注解的配置(“JavaConfig”)
要开始,您需要做的就是子类化
AbstractCouchbaseConfiguration并实现抽象方法。
示例 3. 扩展
AbstractCouchbaseConfiguration
@Configuration
public class Config extends AbstractCouchbaseConfiguration {
@Override public String getConnectionString() { return "couchbase://127.0.0.1"; }@Override public String getUserName() { return "Administrator"; }@Override public String getPassword() { return "password"; }@Override public String getBucketName() { return "travel-sample"; }

}
Spring Data Couchbase教程一
连接字符串由主机列表和可选方案 ( couchbase://) 组成,如上面的代码所示。您需要提供的只是要引导到的 Couchbase 节点列表(用 分隔,)。请注意,虽然在开发中一台主机就足够了,但建议在此处添加 3 到 5 个引导节点。Couchbase 将自动从集群中获取所有节点,但您提供的唯一节点可能会在您启动应用程序时遇到问题。
该userName和password在你的Couchbase Server群集通过RBAC(基于角色的访问控制)配置。在bucketName反映您要使用该配置桶。
此外,SDK 环境可以通过覆盖返回配置的configureEnvironment方法 来调整。
ClusterEnvironment.BuilderClusterEnvironment
更多的东西可以从这个配置中作为自定义 bean 进行自定义和覆盖(例如存储库、验证和自定义转换器)。
如果您使用SyncGatewayand CouchbaseMobile,您可能会遇到以_.为前缀的字段的问题。由于默认情况下 Spring Data Couchbase 将类型信息存储为_class属性,这可能会出现问题。覆盖typeKey()(例如返回
MappingCouchbaseConverter.TYPEKEY_SYNCGATEWAY_COMPATIBLE)以更改所述属性的名称。
如果您启动应用程序,您应该会在日志中看到 Couchbase INFO 级别的日志记录,这表明底层 Couchbase Java SDK 正在连接到数据库。如果报告任何错误,请确保给定的凭据和主机信息正确。
  1. 建模实体
    本章描述如何对实体建模并解释它们在 Couchbase 服务器本身中的对应表示。
2.1对象映射基础
本节涵盖 Spring Data 对象映射、对象创建、字段和属性访问、可变性和不变性的基础知识。请注意,本节仅适用于不使用底层数据存储(如 JPA)的对象映射的 Spring Data 模块。还请务必查阅特定于存储的部分以获取特定于存储的对象映射,例如索引、自定义列或字段名称等。
Spring Data 对象映射的核心职责是创建域对象的实例并将 store-native 数据结构映射到这些实例上。这意味着我们需要两个基本步骤:
使用公开的构造函数之一创建实例。
实例填充以实现所有公开的属性。
2.1.1对象创建
Spring Data 自动尝试检测持久实体的构造函数以用于实现该类型的对象。解析算法的工作原理如下:
如果只有一个构造函数,则使用它。
如果有多个构造函数并且恰好一个用 注释@PersistenceConstructor,则使用它。
如果有无参数构造函数,则使用它。其他构造函数将被忽略。
值解析假定构造函数参数名称与实体的属性名称匹配,即解析将像要填充属性一样执行,包括映射中的所有自定义(不同的数据存储列或字段名称等)。这还需要类文件中可用的参数名称信息或@ConstructorProperties构造函数上存在的注释。
可以使用 Spring Framework 的@Valuevalue annotation 使用 store-specific SpEL 表达式来自定义 value 解析。
对象创建内部
为了避免反射的开销,Spring Data 对象创建默认使用运行时生成的工厂类,它会直接调用领域类的构造函数。即对于这个示例类型:
class Person {
Person(String firstname, String lastname) { … }
}
我们将在运行时创建一个在语义上等同于这个的工厂类:
class PersonObjectInstantiator implements ObjectInstantiator {
Object newInstance(Object... args) {
return new Person((String) args[0], (String) args[1]);

}
}
与反射相比,这给了我们大约 10% 的性能提升。要使域类有资格进行此类优化,它需要遵守一组约束:
它不能是私人课程
它不能是非静态内部类
它不能是 CGLib 代理类
Spring Data 使用的构造函数不能是私有的
如果这些条件中的任何一个匹配,Spring Data 将通过反射回退到实体实例化。
2.1.2.物业人口
一旦创建了实体的实例,Spring Data 就会填充该类的所有剩余持久属性。除非已经由实体的构造函数填充(即通过其构造函数参数列表使用),否则将首先填充标识符属性以允许解析循环对象引用。之后,在实体实例上设置所有尚未由构造函数填充的非瞬态属性。为此,我们使用以下算法:
如果属性是不可变的但公开了一个with…方法(见下文),我们使用该with…方法创建一个具有新属性值的新实体实例。
如果定义了属性访问(即通过getter 和setter 访问),我们将调用setter 方法。
如果属性是可变的,我们直接设置字段。
如果属性是不可变的,我们将使用持久性操作(请参阅对象创建)使用的构造函数来创建实例的副本。
默认情况下,我们直接设置字段值。
Property population internals
与我们在对象构造中的优化类似,我们还使用 Spring Data 运行时生成的访问器类与实体实例进行交互。
class Person {
private final Long id;
private String firstname;
private @AccessType(Type.PROPERTY) String lastname;
Person() {
this.id = null;

}
Person(Long id, String firstname, String lastname) {
// Field assignments

}
Person withId(Long id) {
return new Person(id, this.firstname, this.lastame);

}
void setLastname(String lastname) {
this.lastname = lastname;

}
}
示例 4. 生成的属性访问器
class PersonPropertyAccessor implements PersistentPropertyAccessor {
private static final MethodHandle firstname;
private Person person;
public void setProperty(PersistentProperty property, Object value) {
String name = property.getName(); if ("firstname".equals(name)) { firstname.invoke(person, (String) value); } else if ("id".equals(name)) { this.person = person.withId((Long) value); } else if ("lastname".equals(name)) { this.person.setLastname((String) value); }

}
}
PropertyAccessor 持有底层对象的可变实例。这是为了启用其他不可变属性的突变。
默认情况下,Spring Data 使用字段访问来读取和写入属性值。根据private字段的可见性规则,MethodHandles用于与字段交互。
该类公开了一个withId(…)用于设置标识符的方法,例如,当将实例插入数据存储并生成标识符时。调用withId(…)会创建一个新Person对象。所有后续的突变都将发生在新的实例中,而前一个不变。
使用属性访问允许直接方法调用而不使用MethodHandles.
与反射相比,这给了我们大约 25% 的性能提升。要使域类有资格进行此类优化,它需要遵守一组约束:
类型不得位于默认值或java包下。
类型及其构造函数必须是 public
作为内部类的类型必须是static.
使用的 Java 运行时必须允许在原始ClassLoader. Java 9 和更高版本施加了某些限制。
默认情况下,Spring Data 尝试使用生成的属性访问器,如果检测到限制,则回退到基于反射的访问器。
让我们看一下以下实体:
示例 5. 示例实体
class Person {
private final @Id Long id;
private final String firstname, lastname;
private final LocalDate birthday;
private final int age;
private String comment;
private @AccessType(Type.PROPERTY) String remarks;
static Person of(String firstname, String lastname, LocalDate birthday) {
return new Person(null, firstname, lastname, birthday, Period.between(birthday, LocalDate.now()).getYears());

}
Person(Long id, String firstname, String lastname, LocalDate birthday, int age) {
this.id = id; this.firstname = firstname; this.lastname = lastname; this.birthday = birthday; this.age = age;

}
Person withId(Long id) {
return new Person(id, this.firstname, this.lastname, this.birthday, this.age);

}
void setRemarks(String remarks) {
this.remarks = remarks;

}
}
Spring Data Couchbase教程一
标识符属性是最终的,但null在构造函数中设置为。该类公开了一个withId(…)用于设置标识符的方法,例如,当将实例插入数据存储并生成标识符时。Person创建新实例时,原始实例保持不变。相同的模式通常适用于存储管理但可能必须更改以进行持久性操作的其他属性。wither 方法是可选的,因为持久性构造函数(参见 6)实际上是一个复制构造函数,并且设置属性将被转换为创建一个应用了新标识符值的新实例。
的firstname和lastname特性是通过吸气剂可能暴露普通不可变属性。
该age属性是不可变的,但从该属性派生而来birthday。使用所示的设计,数据库值将胜过默认值,因为 Spring Data 使用唯一声明的构造函数。即使意图是应该首选计算,重要的是此构造函数也将其age作为参数(可能会忽略它),否则属性填充步骤将尝试设置年龄字段并由于它是不可变的且没有with…方法而失败在场。
该comment属性是可变的,通过直接设置其字段来填充。
的remarks特性是可变的,并且通过设置填充comment直接字段或通过调用用于setter方法
该类公开了一个工厂方法和一个用于创建对象的构造函数。这里的核心思想是使用工厂方法而不是额外的构造函数来避免构造函数通过@PersistenceConstructor. 相反,属性的默认设置是在工厂方法中处理的。

    推荐阅读