Spring Data Couchbase教程三
寂寞的心情wang 发布于2022-01 浏览:460 回复:0
0
收藏

原标题:Spring认证中国教育管理中心-Spring Data Couchbase教程三(Spring中国教育管理中心)

 
2.4.乐观锁定
在某些情况下,您可能希望确保在对文档执行变异操作时不会覆盖其他用户的更改。为此,您有三个选择:事务(自 Couchbase 6.5 起)、悲观并发(锁定)或乐观并发。

乐观并发往往比悲观并发或事务提供更好的性能,因为没有对数据持有实际锁,也没有存储有关操作的额外信息(没有事务日志)。

为了实现乐观锁定,Couchbase 使用 CAS(比较和交换)方法。当文档发生变异时,CAS 值也会发生变化。CAS 对客户端是不透明的,您唯一需要知道的是它会随着内容或元信息的变化而变化。

在其他数据存储中,可以通过带有递增计数器的任意版本字段来实现类似的行为。由于 Couchbase 以更好的方式支持这一点,因此很容易实现。如果您想要自动乐观锁定支持,您需要做的就是@Version在长字段上添加注释,如下所示:

示例 14. 具有乐观锁定的文档。

@Document
public class User {

@Version
private long version;

// constructor, getters, setters...
}
如果您通过模板或存储库加载文档,版本字段将自动填充当前 CAS 值。请务必注意,您不应该访问该字段,甚至不应该自行更改它。将文档保存回来后,它将成功或失败并带有
OptimisticLockingFailureException. 如果您遇到此类异常,则进一步的方法取决于您希望在应用程序方面实现的目标。您应该重试完整的加载-更新-写入周期,或者将错误传播到上层以进行正确处理。

2.5.验证
该库支持 JSR 303 验证,它直接基于实体中的注释。当然,您可以在服务层中添加各种验证,但这样可以很好地与您的实际实体耦合。

要使其工作,您需要包含两个额外的依赖项。JSR 303 和一个实现它的库,比如 hibernate 支持的库:

示例 15. 验证依赖项


javax.validation
validation-api


org.hibernate
hibernate-validator

现在您需要在配置中添加两个 bean:

示例 16. 验证 bean

@Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}

@Bean
public ValidatingCouchbaseEventListener validationEventListener() {
return new ValidatingCouchbaseEventListener(validator());
}
现在您可以使用 JSR303 注释来注释您的字段。如果验证save()失败,
ConstraintViolationException则抛出 a。

示例 17. 示例验证注释

@Size(min = 10)
@Field
private String name;
2.6.审计
可以通过 Spring Data 审计机制自动审计实体(跟踪哪个用户创建了对象、更新了对象以及在什么时间)。

首先,请注意,只有具有@Version注释字段的实体才能被审计以进行创建(否则框架会将创建解释为更新)。

审核工作由标注领域有@CreatedBy,@CreatedDate,@LastModifiedBy和@LastModifiedDate。持久化实体时,框架将自动在这些字段上注入正确的值。xxxDate 注释必须放在一个Date字段上(或兼容的,例如 jodatime 类),而 xxxBy 注释可以放在任何类的字段上T(尽管两个字段必须是相同的类型)。

要配置审计,首先需要在上下文中有一个审计感知 bean。所说的 bean 必须是类型的AuditorAware(允许产生一个可以存储在T我们之前看到的类型的 xxxBy 字段中的值)。其次,您必须@Configuration使用@EnableCouchbaseAuditing注释在您的班级中激活审核。

这是一个例子:

示例 18. 示例审计实体

@Document
public class AuditedItem {

@Id
private final String id;

private String value;

@CreatedBy
private String creator;

@LastModifiedBy
private String lastModifiedBy;

@LastModifiedDate
private Date lastModification;

@CreatedDate
private Date creationDate;

@Version
private long version;

//..omitted constructor/getters/setters/...
}
 
注意两者@CreatedBy和@LastModifiedBy都放在一个String字段上,所以我们AuditorAware必须使用String.

示例 19. 示例 AuditorAware 实现

public class NaiveAuditorAware implements AuditorAware {

private String auditor = "auditor";

@Override
public String getCurrentAuditor() {
return auditor;
}

public void setAuditor(String auditor) {
this.auditor = auditor;
}
}
为了将所有这些联系在一起,我们使用 java 配置来声明一个 AuditorAware bean 并激活审计:

示例 20. 示例审计配置

@Configuration
@EnableCouchbaseAuditing //this activates auditing
public class AuditConfiguration extends AbstractCouchbaseConfiguration {

//... a few abstract methods omitted here

// this creates the auditor aware bean that will feed the annotations
@Bean
public NaiveAuditorAware testAuditorAware() {
return new NaiveAuditorAware();
}
3.自动生成密钥
本章描述了如何使用内置机制自动生成 couchbase 文档键。支持两种类型的自动生成策略。

使用属性生成密钥
使用 uuid 生成密钥
couchbase 支持的最大密钥长度为 250 字节。

3.1配置
要自动生成的键应使用 注释@GeneratedValue。默认策略是USE_ATTRIBUTES. 密钥的前缀和后缀可以作为实体本身的一部分提供,这些值不会持久化,它们仅用于密钥生成。前缀和后缀使用order值排序。默认顺序是0,多个没有顺序的前缀会覆盖前一个。如果 id 的值已经可用,则将跳过自动生成。可以使用 提供连接的分隔符delimiter,默认分隔符是.。

示例 21. GeneratedValue 的注解

@Document
public class User {
@Id @GeneratedValue(strategy = USE_ATTRIBUTES, delimiter = ".")
private String id;
@IdPrefix(order=0)
private String userPrefix;
@IdSuffix(order=0)
private String userSuffix;
...
}
3.2.使用属性生成密钥
使用文档属性的组合生成密钥是一种常见的做法。使用属性的键生成连接所有用 注释的属性值IdAttribute,基于提供的类似于前缀和后缀的顺序。

示例 22.IdAttribute 的注释

@Document
public class User {
@Id @GeneratedValue(strategy = USE_ATTRIBUTES)
private String id;
@IdAttribute
private String userid;
...
}
3.3.使用 uuid 生成密钥
这种自动生成使用 UUID 随机生成器来生成文档密钥,消耗 16 字节的密钥空间。此机制仅推荐用于测试脚手架。

示例 23.唯一密钥生成的注释

@Document
public class User {
@Id @GeneratedValue(strategy = UNIQUE)
private String id;
...
}
4. 使用 Spring 数据存储库
Spring Data repository 抽象的目标是显着减少为各种持久性存储实现数据访问层所需的样板代码量。

Spring Data 存储库文档和您的模块

本章介绍 Spring Data 存储库的核心概念和接口。本章中的信息来自 Spring Data Commons 模块。它使用 Java Persistence API (JPA) 模块的配置和代码示例。您应该调整 XML 名称空间声明和要扩展的类型,以适应您使用的特定模块的等效项。“命名空间参考”涵盖了 XML 配置,所有支持存储库 API 的 Spring Data 模块都支持该配置。“存储库查询关键字”涵盖了存储库抽象一般支持的查询方法关键字。有关模块特定功能的详细信息,请参阅本文档中有关该模块的章节。

4.1核心概念
Spring Data 存储库抽象中的中央接口是Repository. 它需要域类来管理以及域类的 ID 类型作为类型参数。此接口主要用作标记接口,以捕获要使用的类型并帮助您发现扩展此接口的接口。该CrudRepository接口为被管理的实体类提供了复杂的 CRUD 功能。

示例 24.CrudRepository接口

public interface CrudRepository extends Repository {

S save(S entity);

Optional findById(ID primaryKey);

Iterable findAll();

long count();

void delete(T entity);

boolean existsById(ID primaryKey);

// … more functionality omitted.
}
保存给定的实体。

返回由给定 ID 标识的实体。

返回所有实体。

返回实体的数量。

删除给定的实体。

指示具有给定 ID 的实体是否存在。

 
我们还提供了特定于持久性技术的抽象,例如JpaRepository或MongoRepository。这些接口扩展CrudRepository,并露出下面的持久化技术在另外的能力,以比较通用的持久性与技术无关的接口,如CrudRepository。

在 之上CrudRepository,还有一个
PagingAndSortingRepository抽象,它添加了额外的方法来简化对实体的分页访问:

示例
25.PagingAndSortingRepository界面

public interface PagingAndSortingRepository extends CrudRepository {

Iterable findAll(Sort sort);

Page findAll(Pageable pageable);
}
要访问User页面大小为 20的第二页,您可以执行以下操作:

PagingAndSortingRepository repository = // … get access to a bean
Page users = repository.findAll(PageRequest.of(1, 20));
除了查询方法之外,还可以使用计数和删除查询的查询派生。以下列表显示了派生计数查询的接口定义:

示例 26.派生计数查询

interface UserRepository extends CrudRepository {

long countByLastname(String lastname);
}
以下清单显示了派生删除查询的接口定义:

示例 27.派生删除查询

interface UserRepository extends CrudRepository {

long deleteByLastname(String lastname);

List removeByLastname(String lastname);
}
4.2.查询方法
标准 CRUD 功能存储库通常对底层数据存储进行查询。使用 Spring Data,声明这些查询变成了一个四步过程:

声明一个扩展 Repository 或其子接口之一的接口,并将其键入应处理的域类和 ID 类型,如以下示例所示:interface PersonRepository extends Repository { … }
在接口上声明查询方法。interface PersonRepository extends Repository { List findByLastname(String lastname); }
设置 Spring 以使用JavaConfig或XML configuration为这些接口创建代理实例。要使用 Java 配置,请创建一个类似于以下内容的类:import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @EnableJpaRepositories class Config { … }要使用 XML 配置,请定义一个类似于以下内容的 bean:   此示例中使用了 JPA 命名空间。如果您将存储库抽象用于任何其他存储,则需要将其更改为存储模块的适当命名空间声明。换句话说,您应该交换jpa,例如,mongodb。另外请注意,JavaConfig 变体没有显式配置包,因为默认使用带注释的类的包。要自定义要扫描的包,请使用basePackage…特定于数据存储的存储库的@Enable${store}Repositories-annotation的属性之一。
注入存储库实例并使用它,如下例所示:class SomeClient { private final PersonRepository repository; SomeClient(PersonRepository repository) { this.repository = repository; } void doSomething() { List persons = repository.findByLastname("Matthews"); } }
以下部分详细解释了每个步骤:

定义存储库接口
定义查询方法
创建存储库实例
Spring Data Repository 的自定义实现

收藏
点赞
0
个赞
TOP
切换版块