原题目:Spring 认证中国教育管理中心 -Spring Data Couchbase 教程三(Spring 中国教育管理中心)
Spring Data Couchbase 教程三
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. 验证依赖项
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
当初您须要在配置中增加两个 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>(容许产生一个能够存储在 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/…
}
Spring Data Couchbase 教程三
留神两者 @CreatedBy 和 @LastModifiedBy 都放在一个 String 字段上,所以咱们 AuditorAware 必须应用 String.
示例 19. 示例 AuditorAware 实现
public class NaiveAuditorAware implements AuditorAware<String> {
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;
...
}
- 应用 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<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity);
Optional<T> findById(ID primaryKey);
Iterable<T> findAll();
long count();
void delete(T entity);
boolean existsById(ID primaryKey);
// … more functionality omitted.
}
保留给定的实体。
返回由给定 ID 标识的实体。
返回所有实体。
返回实体的数量。
删除给定的实体。
批示具备给定 ID 的实体是否存在。
Spring Data Couchbase 教程三
咱们还提供了特定于持久性技术的形象,例如 JpaRepository 或 MongoRepository。这些接口扩大 CrudRepository,并露出上面的长久化技术在另外的能力,以比拟通用的持久性与技术无关的接口,如 CrudRepository。
在 之上 CrudRepository,还有一个
PagingAndSortingRepository 形象,它增加了额定的办法来简化对实体的分页拜访:
示例
25.PagingAndSortingRepository 界面
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
要拜访 User 页面大小为 20 的第二页,您能够执行以下操作:
PagingAndSortingRepository<User, Long> repository = // … get access to a bean
Page<User> users = repository.findAll(PageRequest.of(1, 20));
除了查询方法之外,还能够应用计数和删除查问的查问派生。以下列表显示了派生计数查问的接口定义:
示例 26. 派生计数查问
interface UserRepository extends CrudRepository<User, Long> {
long countByLastname(String lastname);
}
以下清单显示了派生删除查问的接口定义:
示例 27. 派生删除查问
interface UserRepository extends CrudRepository<User, Long> {
long deleteByLastname(String lastname);
List<User> removeByLastname(String lastname);
}
4.2. 查询方法
规范 CRUD 性能存储库通常对底层数据存储进行查问。应用 Spring Data,申明这些查问变成了一个四步过程:
申明一个扩大 Repository 或其子接口之一的接口,并将其键入应解决的域类和 ID 类型,如以下示例所示:interface PersonRepository extends Repository<Person, Long> {…}
在接口上申明查询方法。interface PersonRepository extends Repository<Person, Long> {List<Person> findByLastname(String lastname); }
设置 Spring 以应用 JavaConfig 或 XML configuration 为这些接口创立代理实例。要应用 Java 配置,请创立一个相似于以下内容的类:import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @EnableJpaRepositories class Config {…}要应用 XML 配置,请定义一个相似于以下内容的 bean:<?xml version=”1.0″ encoding=”UTF-8″?> <beans xmlns=”http://www.springframework.org/schema/beans” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:jpa=”http://www.springframework.org/schema/data/jpa” xsi:schemaLocation=”http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/jpa https://www.springframework.org/schema/data/jpa/spring-jpa.xsd”> <jpa:repositories base-package=”com.acme.repositories”/> </beans> 此示例中应用了 JPA 命名空间。如果您将存储库形象用于任何其余存储,则须要将其更改为存储模块的适当命名空间申明。换句话说,您应该替换 jpa,例如,mongodb。另外请留神,JavaConfig 变体没有显式配置包,因为默认应用带正文的类的包。要自定义要扫描的包,请应用 basePackage…特定于数据存储的存储库的 @Enable${store}Repositories-annotation 的属性之一。
注入存储库实例并应用它,如下例所示:class SomeClient {private final PersonRepository repository; SomeClient(PersonRepository repository) {this.repository = repository;} void doSomething() { List<Person> persons = repository.findByLastname(“Matthews”); } }
以下局部具体解释了每个步骤:
定义存储库接口
定义查询方法
创立存储库实例
Spring Data Repository 的自定义实现