1. Introduction
1.介绍
After our introduction to Spring Data Couchbase, in this second tutorial we focus on the support for entity validation (JSR-303), optimistic locking, and different levels of query consistency for a Couchbase document database.
在我们的介绍了Spring Data Couchbase之后,在第二个教程中,我们将重点介绍对实体验证(JSR-303)、乐观锁定以及Couchbase文档数据库的不同级别的查询一致性的支持。
2. Entity Validation
2.实体验证
Spring Data Couchbase provides support for JSR-303 entity validation annotations. In order to take advantage of this feature, first we add the JSR-303 library to the dependencies section of our Maven project:
Spring Data Couchbase提供了对JSR-303实体验证注释的支持。为了利用这一特性,首先我们将JSR-303库添加到Maven项目的依赖项中。
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
Then we add an implementation of JSR-303. We will use the Hibernate implementation:
然后我们添加一个JSR-303的实现。我们将使用Hibernate的实现。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.4.Final</version>
</dependency>
Finally, we add a validator factory bean and corresponding Couchbase event listener to our Couchbase configuration:
最后,我们在Couchbase配置中添加一个验证器工厂bean和相应的Couchbase事件监听器。
@Bean
public LocalValidatorFactoryBean localValidatorFactoryBean() {
return new LocalValidatorFactoryBean();
}
@Bean
public ValidatingCouchbaseEventListener validatingCouchbaseEventListener() {
return new ValidatingCouchbaseEventListener(localValidatorFactoryBean());
}
The equivalent XML configuration looks like this:
相当的XML配置看起来像这样。
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
<bean id="validatingEventListener"
class="org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbaseEventListener"/>
Now we add JSR-303 annotations to our entity classes. When a constraint violation is encountered during a persistence operation, the operation will fail, throwing a ConstraintViolationException.
现在我们将JSR-303注解添加到我们的实体类中。当在持久化操作中遇到违反约束的情况时,该操作将失败,抛出一个ConstraintViolationException。
Here is a sample of the constraints that we can enforce involving our Student entities:
下面是我们可以执行的涉及我们的Student实体的约束的一个例子。
@Field
@NotNull
@Size(min=1, max=20)
@Pattern(regexp="^[a-zA-Z .'-]+$")
private String firstName;
...
@Field
@Past
private DateTime dateOfBirth;
3. Optimistic Locking
3.乐观的锁定
Spring Data Couchbase does not support multi-document transactions similar to those you can achieve in other Spring Data modules such as Spring Data JPA (via the @Transactional annotation), nor does it provide a rollback feature.
Spring Data Couchbase不支持多文档事务,类似于你可以在其他Spring Data模块(如Spring Data JPA)中实现的事务(通过@Transactional注解),它也不提供回滚功能。
However it does support optimistic locking in much the same way as other Spring Data modules through the use of the @Version annotation:
然而,通过使用@Version注解,它确实以与其他Spring Data模块相同的方式支持乐观的锁定。
@Version
private long version;
Under the covers, Couchbase uses what is known as a “compare and swap” (CAS) mechanism to achieve optimistic locking at the datastore level.
Couchbase使用所谓的 “比较和交换”(CAS)机制来实现数据存储层面的乐观锁定。
Each document in Couchbase has an associated CAS value that is modified automatically any time the document’s metadata or contents are altered. The use of the @Version annotation on a field causes that field to be populated with the current CAS value whenever a document is retrieved from Couchbase.
Couchbase中的每个文档都有一个相关的CAS值,当文档的元数据或内容被改变时,这个CAS值会被自动修改。在一个字段上使用@Version注解会使该字段在每次从Couchbase中检索文档时被填充上当前的CAS值。
When you attempt to save the document back to Couchbase, this field is checked against the current CAS value in Couchbase. If the values do not match, the persistence operation will fail with an OptimisticLockingException.
当你试图把文档保存回Couchbase时,这个字段会与Couchbase中当前的CAS值进行核对。如果数值不匹配,持久化操作将以OptimisticLockingException失败。
It is extremely important to note that you should never attempt to access or modify this field in your code.
需要注意的是极其重要的是,你千万不要试图在你的代码中访问或修改这个字段。
4. Query Consistency
4.查询的一致性
When implementing a persistence layer over Couchbase, you have to consider the possibility of stale reads and writes. This is because when documents are inserted, updated, or deleted, it may take some time before the backing views and indexes are updated to reflect these changes.
当在Couchbase上实现持久化层时,你必须考虑陈旧的读和写的可能性。这是因为当文档被插入、更新或删除时,可能需要一些时间才能更新支持的视图和索引以反映这些变化。
And if you have a large dataset backed by a cluster of Couchbase nodes, this can become a significant problem, especially for a OLTP system.
如果你有一个由Couchbase节点集群支持的大型数据集,这可能会成为一个重要的问题,特别是对于OLTP系统。
Spring Data provides a robust level of consistency for some repository and template operations, plus a couple of options that let you determine the level of read and write consistency that is acceptable for your application.
Spring Data为一些存储库和模板操作提供了强大的一致性水平,另外还有几个选项,让你决定你的应用程序可以接受的读写一致性水平。
4.1. Levels of Consistency
4.1.一致性的级别
Spring Data allows you to specify various levels of query consistency and staleness for your application via the Consistency enum found in the org.springframework.data.couchbase.core.query package.
Spring Data允许你通过在org.springframework.data.couchbase.core.query包中找到的Consistency枚举,为你的应用程序指定各种级别的查询一致性和恒定性。
This enum defines the following levels of query consistency and staleness, from least to most strict:
这个枚举定义了以下查询一致性和滞后性的级别,从最不严格到最严格。
- EVENTUALLY_CONSISTENT
- stale reads are allowed
- indexes are updated according to Couchbase standard algorithm
- UPDATE_AFTER
- stale reads are allowed
- indexes are updated after each request
- DEFAULT_CONSISTENCY (same as READ_YOUR_OWN_WRITES)
- READ_YOUR_OWN_WRITES
- stale reads are not allowed
- indexes are updated after each request
- STRONGLY_CONSISTENT
- stale reads are not allowed
- indexes are updated after each statement
4.2. Default Behavior
4.2.默认行为
Consider the case where you have documents that have been deleted from Couchbase, and the backing views and indexes have not been fully updated.
考虑一下这样的情况:你有被从Couchbase中删除的文档,而支持的视图和索引还没有被完全更新。
The CouchbaseRepository built-in method deleteAll() safely ignores documents that were found by the backing view but whose deletion is not yet reflected by the view.
CouchbaseRepository内置方法deleteAll()可以安全地忽略那些被支持的视图发现但其删除尚未被视图反映的文件。
Likewise, the CouchbaseTemplate built-in methods findByView and findBySpatialView offer a similar level of consistency by not returning documents that were initially found by the backing view but which have since been deleted.
同样,CouchbaseTemplate内置方法findByView和findBySpatialView通过不返回最初由支持视图找到但后来被删除的文档,提供了类似的一致性。
For all other template methods, built-in repository methods, and derived repository query methods, according to the official Spring Data Couchbase 2.1.x documentation as of this writing, Spring Data uses a default consistency level of Consistency.READ_YOUR_OWN_WRITES.
对于所有其他的模板方法、内置的存储库方法和派生的存储库查询方法,根据本文写作时的官方Spring Data Couchbase 2.1.x文档,Spring Data使用的默认一致性级别为Consistency.READ_YOUR_OWN_WRITES.。
It is worth noting that earlier versions of the library used a default of Consistency.UPDATE_AFTER.
值得注意的是,早期版本的库使用默认的Consistency.UPDATE_AFTER。
Whichever version you are using, if you have any reservations about blindly accepting the default consistency level being provided, Spring offers two methods by which you can declaratively control the consistency level(s) being used, as the following subsections will describe.
无论你使用的是哪个版本,如果你对盲目接受所提供的默认一致性级别有任何保留,Spring提供了两种方法,你可以通过这些方法声明地控制所使用的一致性级别,下面的小节将介绍这一点。
4.3. Global Consistency Setting
4.3.全局一致性设置
If you are using Couchbase repositories and your application calls for a stronger level of consistency, or if it can tolerate a weaker level, then you may override the default consistency setting for all repositories by overriding the getDefaultConsistency() method in your Couchbase configuration.
如果你正在使用Couchbase存储库,并且你的应用程序需要更强的一致性,或者它可以容忍更弱的一致性,那么你可以通过覆盖Couchbase配置中的getDefaultConsistency()方法来覆盖所有存储库的默认一致性设置。
Here is how you can override global consistency level in your Couchbase configuration class:
以下是你如何在Couchbase配置类中覆盖全局一致性水平。
@Override
public Consistency getDefaultConsistency() {
return Consistency.STRONGLY_CONSISTENT;
}
Here is the equivalent XML configuration:
下面是等效的XML配置。
<couchbase:template consistency="STRONGLY_CONSISTENT"/>
Note that the price of stricter levels of consistency is increased latency at query time, so be sure to tailor this setting based on the needs of your application.
请注意,更严格的一致性水平的代价是查询时的延迟增加,所以一定要根据你的应用程序的需要来调整这个设置。
For example, a data warehouse or reporting application in which data is often appended or updated only in a batch would be a good candidate for EVENTUALLY_CONSISTENT, whereas an OLTP application should probably tend towards the more strict levels such as READ_YOUR_OWN_WRITES or STRONGLY_CONSISTENT.
例如,数据仓库或报告应用程序中的数据经常只在批处理中追加或更新,将是EVENTUALLY_CONSISTENT的良好候选者,而OLTP应用程序可能应该倾向于更严格的级别,如READ_YOUR_OWN_WRITES或STRONGLY_CONSISTENT。
4.4. Custom Consistency Implementation
4.4.自定义一致性的实现
If you need more finely tuned consistency settings, you can override the default consistency level on a query-by-query basis by providing your own repository implementation for any queries whose consistency level you want to control independently and making use of the queryView and/or queryN1QL methods provided by CouchbaseTemplate.
如果你需要更精细的一致性设置,你可以在逐个查询的基础上覆盖默认的一致性水平,方法是为任何你想独立控制一致性水平的查询提供你自己的存储库实现,并利用queryView和/或queryN1QL方法,由CouchbaseTemplate提供。
Let’s implement a custom repository method called findByFirstNameStartsWith for our Student entity for which we do not want to allow stale reads.
让我们为我们的Student实体实现一个名为findByFirstNameStartsWith的自定义存储库方法,我们不希望允许陈旧的读取。
First, create an interface containing the custom method declaration:
首先,创建一个包含自定义方法声明的接口。
public interface CustomStudentRepository {
List<Student> findByFirstNameStartsWith(String s);
}
Next, implement the interface, setting the Stale setting from the underlying Couchbase Java SDK to the desired level:
接下来,实现这个接口,将底层Couchbase Java SDK的Stale设置到所需的水平。
public class CustomStudentRepositoryImpl implements CustomStudentRepository {
@Autowired
private CouchbaseTemplate template;
public List<Student> findByFirstNameStartsWith(String s) {
return template.findByView(ViewQuery.from("student", "byFirstName")
.startKey(s)
.stale(Stale.FALSE),
Student.class);
}
}
Finally, by having your standard repository interface extend both the generic CrudRepository interface and your custom repository interface, clients will have access to all the built-in and derived methods of your standard repository interface, plus any custom methods you implemented in your custom repository class:
最后,通过让你的标准版本库接口同时扩展通用CrudRepository接口和你的自定义版本库接口,客户端将可以访问你的标准版本库接口的所有内置和派生方法,以及你在自定义版本库类中实现的任何自定义方法。
public interface StudentRepository extends CrudRepository<Student, String>,
CustomStudentRepository {
...
}
5. Conclusion
5.结论
In this tutorial, we showed how to implement JSR-303 entity validation and achieve optimistic locking capability when using the Spring Data Couchbase community project.
在本教程中,我们展示了在使用Spring Data Couchbase社区项目时,如何实现JSR-303实体验证并实现乐观的锁定能力。
We also discussed the need for understanding query consistency in Couchbase, and we introduced the different levels of consistency provided by Spring Data Couchbase.
我们还讨论了了解Couchbase中查询一致性的必要性,我们介绍了Spring Data Couchbase提供的不同级别的一致性。
Finally, we explained the default consistency levels used by Spring Data Couchbase globally and for a few specific methods, and we demonstrated ways to override the global default consistency setting as well as how to override consistency settings on a query-by-query basis by providing your own custom repository implementations.
最后,我们解释了Spring Data Couchbase在全局和一些特定方法中使用的默认一致性级别,我们还演示了覆盖全局默认一致性设置的方法,以及如何通过提供你自己的自定义存储库实现,在逐个查询的基础上覆盖一致性设置。
You can view the complete source code for this tutorial in the GitHub project.
你可以在GitHub项目中查看本教程的完整源代码。
To learn more about Spring Data Couchbase, visit the official Spring Data Couchbase project site.
要了解有关Spring Data Couchbase的更多信息,请访问官方的Spring Data Couchbase项目网站。