Spring Data Couchbase 2.0

工程 | Josh Long | 2016年2月10日 | ...

这是来自Couchbase的Simon BASLÉ的交叉发布博客。您可以在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用户提供更多功能。

第一个里程碑于去年8月发布,然后是候选版本,从那时起,实现了其他功能(和错误修复),现在可以向公众发布GA版本。

让我们快速浏览一下发生了哪些变化(使用⭐到⭐⭐⭐的符号表示我们认为每个功能有多棒和重要?)。

Spring Data Couchbase 2.0中的新功能

Spring Data Couchbase的1.x版本和2.x版本之间的主要区别在于

  • 配置元素更接近Couchbase的实际情况:环境、集群、桶(可能允许您创建每个连接到不同桶甚至不同集群的CouchbaseTemplate!)
  • 支持自定义存储库方法不再总是使用视图完成,现在(默认情况下)通过N1QL完成,这更加灵活,并且需要更少的服务器端维护。
  • 使用视图的自定义方法进行了一些修改,以更好地遵循Spring Data的理念。这会稍微降低一些灵活性,但实现是从方法名称(通过“查询推导”)生成的。
  • 您现在可以使用视图对数据进行地理空间查询(或者如果您超过3个维度,则进行多维查询)。

当然,您仍然可以通过使用CouchbaseTemplate而不是CouchbaseRepository接口来访问更低级别的API,并且您甚至可以从SDK访问底层的Bucket

通过N1QL的存储库方法

⭐⭐⭐

Couchbase 4.0中的主要新功能是N1QL,这是一种适用于JSON文档的SQL扩展(因此它向SQL添加了JSON相关的特性)。

这对Repository模式和Spring Data中的查询推导尤其有用,因为绝大多数查询推导关键字都可以轻松转换为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函数

另一项以前不支持的新功能是,如果您有一个reduce函数,则执行该函数。现在,为了执行它,您只需在@View注释中将reduce标志设置为true。

如果对您有意义(即您实际上使用了“count”reduce函数),您也可以在方法名前缀“count”而不是“find”。

请注意,Couchbase中的reduce函数可以是除预先存在的_count之外的其他内容,甚至可以返回除long之外的其他内容,例如JsonObject,例如内置的_stats

类似地,在方法名称中添加变体“topX”或“firstX”将导致在请求上设置附加限制(例如,findFirst5ByLastName将列表限制为5个结果)。

配置一致性,读取您自己的写入

⭐⭐⭐

在使用异步填充的辅助索引(如视图和GSI(支持N1QL的新辅助索引引擎))时,经常会出现需要立即读取先前写入操作的修改。

这意味着只要数据仍在索引过程中,视图/N1QL就不应该给出答案,因此这牺牲了一些性能以换取一致性。

相反(并且是Spring Data Couchbase的当前默认设置)是通过接受返回陈旧数据来优先考虑性能。

我们添加了用于配置框架通过查询推导构建的所有查询(基于视图或基于N1QL)的全局语义,方法是在一致性概念周围提供一个小的抽象。

这是通过覆盖AbstractCouchbaseConfigurationgetDefaultConsistency()方法来完成的。Consistency是一个枚举,允许您在READ_YOUR_OWN_WRITESSTRONGLY_CONSISTENTUPDATE_AFTEREVENTUALLY_CONSISTENT之间进行选择。请参阅官方文档,以获取有关它们的工作原理以及它们在查询时产生的影响的更多信息。

您也可以在XML中通过在<couchbase:template>标签上使用一致性属性来实现。

自GA以来,存储库中的CRUD方法现在也考虑了默认配置的一致性。

更改存储的JSON中的类型信息字段

一些用户报告了Spring Data和Couchbase Mobile方面的问题,Sync Gateway拒绝包含以下划线为前缀的字段的文档。

这对Spring Data来说是个问题,因为它默认情况下将类型信息存储在_class字段中:()

解决方案是允许通过配置修改该类型信息字段的名称。您可以通过覆盖AbstractCouchbaseConfiguration中的typeKey()方法来做到这一点。例如,您可以使用常量MappingCouchbaseConverter.TYPEKEY_SYNCGATEWAY_COMPATIBLE(即“javaClass”)。

此字段是生成的N1QL查询用于过滤仅与存储库实体对应的文档的字段。

在N1QL派生查询中支持Pageable/PageRequest

⭐⭐

使用 N1QL,对于通过查询派生生成的查询,现在支持PageableSort 参数。

  • 基于 N1QL 的PagingAndSortingRepository 支持。
  • 添加了两个依赖于 N1QL 进行分页和/或排序的findAll 方法。使用默认配置的一致性。

使用空间视图进行地理空间和多维查询

⭐⭐⭐

使用坐标查询 Couchbase!如果您的实体具有Point(或xy)位置,则可以使用以下方式查找它:

  • 边界框: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 表示法来

  1. 确保将正确的选择和过滤应用于语句,以便构建和返回实体:使用#{#n1ql.selectEntity} 生成SELECT ... FROM ... 子句,并在WHERE 子句中使用#{#n1ql.filter} 将查询限制到正确的实体。
  2. 计算值或从 Spring 上下文中配置的外部 SpEL 值提供程序中检索数据。

存储库“主”索引创建可以自动触发

⭐⭐

⚠️ 重要:这被认为是开发/测试期间的辅助手段,不建议在生产环境中使用

为了确保给定存储库中实体的 N1QL 索引在开发或预生产环境中被激活,可以使用@N1qlPrimaryIndexed(启用桶范围的自由格式查询)和@N1qlSecondaryIndexed(仅索引与实体类型对应的文档,类似于 SpEL #{#n1ql.filter} 生成的 WHERE 子句)对其进行注解。

此外,CRUD 操作的备份视图可以通过使用@ViewIndexed 注解存储库来自动创建(您需要提供设计文档名称,该名称应对应于实体的简单类名,首字母小写)。

此功能还必须通过在AbstractCouchbaseConfiguration 中重新定义indexManager bean 来选择加入。

使用单行投影时,现在支持简单返回类型(基本类型和String

⭐⭐

这尤其针对具有聚合函数(如COUNT(*)AVG(field) 等)的内联 N1QL 查询。查询必须返回具有单个投影的单行。

在 N1QL 内联查询中支持命名参数

⭐⭐

使用命名参数或位置参数,但不能同时使用两者。命名参数的语法为$paramName,要求每个方法参数都使用@Param("paramName") 进行注解。

其他功能

其他功能包括

  • 修复 bean 命名,以便 Spring Data Couchbase 创建的所有 bean 都以“couchbase”为前缀,以避免与其他存储发生冲突。
  • 现在支持更改所有存储库的基类(遵循 Spring Data 通用文档中记录的过程)
  • 如果索引已过期,则CouchbaseTemplate 中的查找方法会消除已删除的文档。
  • 可以在@Document 上设置过期时间,作为long + timeUnit

还实现了一些错误修复和相较于 RC1 的改进。

文档

⭐⭐⭐

文档 也得到了改进,增加了面向 Couchbase 的示例,说明如何向存储库添加自定义方法的实现、如何更改所有存储库的基类、如何在内联查询中处理 SpEL 等。

关于 Spring Cache 的说明

Spring Cache 支持已从 Spring Data 存储库中移除。它仍然存在,我们计划对其进行改进。目前,您可以在 GitHub 上的 Couchbase 存储库 中找到它,但它很快就会重新集成到 Spring 项目的官方系列中。

获取 Spring Data Couchbase

您可以将以下内容添加到项目的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

获取 Spring 新闻通讯

与 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,以加速您的进步。

了解更多

获取支持

Tanzu Spring 在一个简单的订阅中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区中所有即将举行的活动。

查看全部