抢先一步
VMware 提供培训和认证,助你快速提升。
了解更多这是一篇来自 Simon BASLÉ (@simonbasle) 的交叉发布博客,他来自 Couchbase。你可以在 twitter (
@simonbasle
) 或 github 上找到他。如需了解更多关于 Couchbase 和 Couchbase Java SDK 的信息,请访问开发者门户。再次感谢 Simon 和你的团队的杰出工作!-Josh
Spring Data Couchbase 2.0 是对原有 Spring Data Couchbase 1.4.x 连接器的重写。它基于 Couchbase Java 2.2 SDK,并大量使用了新的查询语言 N1QL(在 Couchbase Server 4.0 中引入),为 Spring Data 用户提供更多功能。
第一个里程碑版本已于去年八月发布,随后是候选发布版本,自那以后又实现了更多功能(和错误修复),现在 GA 版本可以向公众发布了。
让我们快速浏览一下有哪些变化(使用 ⭐ 到 ⭐⭐⭐ 表示我们认为每个功能有多棒和多重要?)
Spring Data Couchbase 的 1.x 版本与 2.x 版本之间的主要区别在于
CouchbaseTemplate
实例!)当然,你仍然可以使用 CouchbaseTemplate
而非 CouchbaseRepository
接口来访问较低级别的 API,你甚至可以直接从 SDK 访问底层的 Bucket
。
⭐⭐⭐
Couchbase 4.0 的重大新功能是 N1QL,它是一个工作在 JSON 文档上的 SQL 扩展(因此它为 SQL 添加了与 JSON 相关的特定性)。
这对于 Spring Data 中的 Repository
模式和查询派生尤其有利,因为绝大多数查询派生关键字都可以轻松转换为 N1QL。
N1QL 现在是存储库方法的默认后备 Couchbase 功能。如果你想明确指定执行的查询,也可以选择使用 @Query 接口。
public interface UserRepository extends Repository<User, String> {
User findByUsernameEquals(String username);
List<User> findByUsernameContains(String contains);
@Query //optional for N1QL query derivation but more explicit
List<User> findByAgeBetween(int minAge, int maxAge);
}
⭐⭐
此版本的一个重大变化是,现在基于视图的存储库查询(即自定义存储库方法)更符合 Spring Data 的理念。它们也必须显式使用 @View(viewName="something")
进行注解。
这意味着不应有任何 Couchbase 特定的东西泄露到你的存储库接口中。相反,你可以对大多数查询使用查询派生机制。
查询派生在一定程度上也是可能的,一些关键字可以在视图支持的方法中被接受。
public interface UserRepository extends Repository<User, String> {
@Override
@View(designDocument = "user", viewName = "customFindAllView")
Iterable<User> findAll();
@View(viewName = "customFindByNameView")
User findByUsernameIs(String lowKey);
@View(viewName = "customFindByNameView")
List<User> findByUsernameBetween(String lowKey, String highKey);
}
⭐
另一个以前不支持的新功能是执行 reduce 函数(如果存在)。现在,为了执行它,你只需在 @View
注解中将 reduce
标志设置为 true。
如果对你有意义(即你实际使用了“count”reduce 函数),你也可以将方法前缀改为“count”而不是“find”。
请注意,Couchbase 中的 reduce 函数可以不同于预先存在的 _count 函数,它甚至可以返回除了 long 之外的其他类型,比如 JsonObject
,就像内置的 _stats
那样。
类似地,在方法名中添加“topX”或“firstX”变体将导致对请求设置额外的限制(例如,findFirst5ByLastName
将把结果列表限制为 5 个)。
⭐⭐⭐
在使用视图和 GSI(支持 N1QL 的新二级索引引擎)等异步填充的二级索引时,经常出现的一个问题是需要立即读取先前写操作所做的修改。
这意味着只要数据仍在索引过程中,视图/N1QL就不应返回结果,因此这将牺牲一些性能以换取一致性。
相反正好相反(以及 Spring Data Couchbase 当前的默认行为)是优先考虑性能,接受返回陈旧数据。
我们通过提供围绕 Consistency 概念的小抽象,增加了全局语义来配置框架通过查询派生构建的所有查询(基于视图或基于 N1QL 的)。
这可以通过覆盖 AbstractCouchbaseConfiguration
的 getDefaultConsistency()
方法来完成。Consistency
是一个枚举,允许你在 READ_YOUR_OWN_WRITES
、STRONGLY_CONSISTENT
、UPDATE_AFTER
和 EVENTUALLY_CONSISTENT
之间进行选择。有关它们具体如何工作以及在查询时的影响,请参阅官方文档。
你也可以在 XML 中通过使用 <couchbase:template>
标签上的 consistency 属性来完成。
自 GA 版本以来,存储库中的 CRUD 方法现在也考虑了默认配置的一致性。
⭐
一些用户报告了 Spring Data 和 Couchbase Mobile 方面的问题,Sync Gateway 会拒绝包含以下划线为前缀的字段的文档。
这对 Spring Data 来说是个问题,因为它默认将类型信息存储在 _class
字段中 :(
解决方案是通过配置允许修改该类型信息字段的名称。你可以通过覆盖 AbstractCouchbaseConfiguration
中的 typeKey()
方法来实现。例如,你可以使用常量 MappingCouchbaseConverter.TYPEKEY_SYNCGATEWAY_COMPATIBLE
(其值为 "javaClass
")。
这个字段是生成的 N1QL 查询用来过滤只对应于存储库实体的文档的字段。
Pageable
/PageRequest
⭐⭐
使用 N1QL,对于通过查询派生生成的查询,现在支持 Pageable
和 Sort
参数。
PagingAndSortingRepository
支持。findAll
方法,它们依赖 N1QL 进行分页和/或排序。使用默认配置的一致性。⭐⭐⭐
使用坐标查询 Couchbase!如果你的实体有 Point
(或 x
和 y
)位置信息,你可以通过以下方式查找:
findByLocationWithin(Box area)
findByLocationWithin(Circle area)
, findByLocationWithin(Point center, Distance radius)
。findByLocationWithin(Polygon area)
, findByLocationWithin(Point[] polygon)
。findByLocationNear(Point near, Distance maxDistance)
。圆形和多边形之类的查询在服务器端会作为边界框近似快速执行,然后框架会在呈现结果之前消除误报。
你可以利用 Couchbase 空间视图的多维特性,为你的查询添加额外维度(例如,查询城市中深夜仍开放的商店等)。
public interface DimensionalPartyRepository extends CrudRepository<Party, String> {
@Dimensional(designDocument = "partyGeo", spatialViewName = "byLocation")
List<Party> findByLocationNear(Point p, Distance d);
@Dimensional(designDocument = "partyGeo", spatialViewName = "byLocation")
List<Party> findByLocationWithin(Box boundingBox);
@Dimensional(designDocument = "partyGeo", spatialViewName = "byLocation")
List<Party> findByLocationWithin(Polygon zone);
@Dimensional(designDocument = "partyGeo", spatialViewName = "byLocationAndAttendees", dimensions = 3)
List<Party> findByLocationWithinAndAttendeesGreaterThan(Polygon zone, double minAttendees);
}
注意:如果你想重用注解,你也可以这样做(对 @View
和 @Query
也有效)
public interface DimensionalPartyRepository extends CrudRepository<Party, String> {
//define your own meta-annotation
@Dimensional(designDocument = "partyGeo", spatialViewName = "byLocation", dimensions = 2)
@Retention(RetentionPolicy.RUNTIME)
@interface IndexedByLocation { }
//use it :)
@IndexedByLocation
List<Party> findByLocationNear(Point p, Distance d);
@IndexedByLocation
List<Party> findByLocationWithin(Box boundingBox);
@IndexedByLocation
List<Party> findByLocationWithin(Polygon zone);
//here we use a variation with 3 dimensions, so we need to revert to @Dimensional
@Dimensional(designDocument = "partyGeo", spatialViewName = "byLocationAndAttendees", dimensions = 3)
List<Party> findByLocationWithinAndAttendeesGreaterThan(Polygon zone, double minAttendees);
}
N1QL
@Query
现在支持 SpEL⭐⭐⭐
内联查询可以使用 SpEL 表达式来:
#{#n1ql.selectEntity}
生成 SELECT ... FROM ...
子句,并在 WHERE
子句中使用 #{#n1ql.filter}
将查询限制到正确的实体。⭐⭐
⚠️ 重要:这被认为是开发/测试期间的辅助手段,不建议在生产环境中使用
为了确保给定存储库中实体的 N1QL 索引在开发或预生产环境中被激活,可以使用 @N1qlPrimaryIndexed
注解(启用桶范围内的自由查询)和 @N1qlSecondaryIndexed
注解(仅索引对应于实体类型的文档,类似于 SpEL #{#n1ql.filter}
生成的 WHERE 子句)。
此外,CRUD 操作的后备视图可以通过在存储库上使用 @ViewIndexed
注解来自动创建(你需要提供设计文档名称,该名称应与实体的简单类名相对应,首字母小写)。
此功能必须通过在 AbstractCouchbaseConfiguration
中重新定义 indexManager
bean 来额外启用。
String
)⭐⭐
这尤其适用于带有聚合函数(如 COUNT(*)
、AVG(field)
等)的内联 N1QL 查询... 查询必须返回单行且只有单个投影。
⭐⭐
使用命名参数或位置参数,但不能同时使用两者。命名参数的语法是 $paramName
,要求每个方法参数都用 @Param("paramName")
注解。
⭐
其他功能包括
couchbase
" 前缀,以避免与其他存储发生冲突。CouchbaseTemplate
中的 find 方法中排除。@Document
上设置,格式为 long
+ timeUnit
还实现了一些相对于 RC1 的错误修复和改进。
⭐⭐⭐
文档也得到了改进,增加了面向 Couchbase 的示例,如如何向存储库添加自定义方法的实现、如何更改所有存储库的基类、如何在内联查询中处理 SpEL 等。
Spring Cache 支持已从 Spring Data 存储库中移出。它仍然存在,我们计划对其进行改进。目前你可以在 github 上的 Couchbase 存储库中找到它,但它很快会重新整合到官方 Spring 项目家族中。
你可以在项目的 pom.xml
中添加以下内容以获取此 GA 版本(在 dependencies
部分)
<!--<dependencies>-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-couchbase</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<!--</dependencies>-->
我们希望你喜欢此版本及其带来的所有新功能。下一步将是重新加入 Hopper
发布列车,预计在夏季前发布 2.1
版本。