Spring认证中国教育管理中心-Spring Data Couchbase教程八

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

Spring Data Couchbase教程八

4.8.3.存储库填充器

如果您使用 Spring JDBC 模块,您可能熟悉DataSource使用 SQL 脚本填充 a 的支持。存储库级别也有类似的抽象,尽管它不使用 SQL 作为数据定义语言,因为它必须独立于存储。因此,填充器支持 XML(通过 Spring 的 OXM 抽象)和 JSON(通过 Jackson)来定义用于填充存储库的数据。

假设您有一个名为的文件data.json,其内容如下:

示例 72. JSON 中定义的数据

[ { "_class" : "com.acme.Person",
 "firstname" : "Dave",
  "lastname" : "Matthews" },
  { "_class" : "com.acme.Person",
 "firstname" : "Carter",
  "lastname" : "Beauford" } ]

您可以使用 Spring Data Commons 中提供的存储库命名空间的填充器元素来填充存储库。要将前面的数据填充到您的 中PersonRepository,请声明一个类似于以下内容的填充器:

示例 73.声明一个 Jackson 存储库填充器

<?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:repository="http://www.springframework.org/schema/data/repository"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/repository
    https://www.springframework.org/schema/data/repository/spring-repository.xsd">

  <repository:jackson2-populator locations="classpath:data.json" />

</beans>

前面的声明导致data.json文件被 Jackson 读取和反序列化ObjectMapper。

JSON 对象解组的类型是通过检查_classJSON 文档的属性来确定的。基础设施最终会选择适当的存储库来处理反序列化的对象。

要改为使用 XML 来定义存储库应填充的数据,您可以使用该unmarshaller-populator元素。您将其配置为使用 Spring OXM 中可用的 XML 编组器选项之一。有关详细信息,请参阅Spring 参考文档。以下示例显示如何使用 JAXB 解组存储库填充器:

示例 74. 声明解组存储库填充器(使用 JAXB)

<?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:repository="http://www.springframework.org/schema/data/repository"
  xmlns:oxm="http://www.springframework.org/schema/oxm"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/repository
    https://www.springframework.org/schema/data/repository/spring-repository.xsd
    http://www.springframework.org/schema/oxm
    https://www.springframework.org/schema/oxm/spring-oxm.xsd">

  <repository:unmarshaller-populator locations="classpath:data.json"
    unmarshaller-ref="unmarshaller" />

  <oxm:jaxb2-marshaller contextPath="com.acme" />

</beans>

5. Couchbase 存储库

Spring Data repository 抽象的目标是显着减少为各种持久性存储实现数据访问层所需的样板代码量。

默认情况下,如果操作是单文档操作并且 ID 已知,则操作由 Key/Value 支持。对于所有其他操作,默认情况下会生成 N1QL 查询,因此必须为高性能数据访问创建适当的索引。

请注意,您可以为查询调整所需的一致性(请参阅使用一致性查询)并拥有由不同存储桶支持的不同存储库(请参阅[
couchbase.repository.multibucket])

5.1。配置

虽然始终存在对存储库的支持,但您需要在一般情况下或为特定命名空间启用它们。如果您扩展
AbstractCouchbaseConfiguration,只需使用@EnableCouchbaseRepositories注释。它提供了许多可能的选项来缩小或自定义搜索路径,最常见的选项之一是basePackages.

另请注意,如果您在 Spring Boot 中运行,则自动配置支持已经为您设置了注释,因此您只需要在想要覆盖默认值时使用它。

示例 75.基于注释的存储库设置

@Configuration
@EnableCouchbaseRepositories(basePackages = {"com.couchbase.example.repos"})
public class Config extends AbstractCouchbaseConfiguration {
    //...
}

[
couchbase.repository.multibucket] 中描述了高级用法。

5.2.用法

在最简单的情况下,您的存储库将扩展CrudRepository<T, String>,其中 T 是您要公开的实体。让我们看一下 UserInfo 的存储库:

示例 76. UserInfo 存储库

import org.springframework.data.repository.CrudRepository;

public interface UserRepository extends CrudRepository<UserInfo, String> {
}

请注意,这只是一个接口,而不是一个实际的类。在后台,当您的上下文被初始化时,您的存储库描述的实际实现将被创建,您可以通过常规 bean 访问它们。这意味着您将节省大量样板代码,同时仍将完整的 CRUD 语义暴露给您的服务层和应用程序。

现在,让我们想象一下,我们@Autowire的UserRepository一类,使得使用它。我们有哪些可用的方法?

Spring Data Couchbase教程八

现在太棒了!只需定义一个接口,我们就可以在托管实体之上获得完整的 CRUD 功能。

虽然公开的方法为您提供了种类繁多的访问模式,但您通常需要定义自定义的访问模式。您可以通过向界面添加方法声明来做到这一点,这将在后台自动解析为请求,我们将在下一节中看到。

5.3.存储库和查询

5.3.1。基于 N1QL 的查询

先决条件是在存储实体的存储桶上创建了一个 PRIMARY INDEX。

这是一个例子:

示例 77. 具有 N1QL 查询的扩展 UserInfo 存储库

public interface UserRepository extends CrudRepository<UserInfo, String> {

    @Query("#{#n1ql.selectEntity} WHERE role = 'admin' AND #{#n1ql.filter}")
    List<UserInfo> findAllAdmins();

    List<UserInfo> findByFirstname(String fname);
}

在这里,我们看到了两种 N1QL 支持的查询方式。

第一种方法使用Query注释来提供 N1QL 内联语句。 SpEL(Spring 表达式语言)由#{和之间的 SpEL 表达式块支持}。 SpEL 提供了一些特定于 N1QL 的值:

  • #n1ql.selectEntity 允许轻松确保语句将选择构建完整实体所需的所有字段(包括文档 ID 和 CAS 值)。
  • #n1ql.filter 在 WHERE 子句中添加一个条件,将实体类型与 Spring Data 用于存储类型信息的字段匹配。
  • #n1ql.bucket 将替换为存储实体的存储桶的名称,以反引号转义。
  • #n1ql.fields 将替换为重建实体所需的字段列表(例如,对于 SELECT 子句)。
  • #n1ql.delete将被delete from声明所取代。
  • #n1ql.returning 将替换为重建实体所需的返回子句。

我们建议您始终使用selectEntitySpEL 和带有 SpEL 的 WHERE 子句filter(否则您的查询可能会受到来自其他存储库的实体的影响)。

基于字符串的查询支持参数化查询。您可以使用诸如“$1”之类的位置占位符,在这种情况下,每个方法参数将按顺序映射到$1, $2, $3... 或者,您可以使用“$someString”语法使用命名占位符。方法参数将使用参数名称与其对应的占位符匹配,可以通过使用(例如)注释每个参数(aPageable或除外Sort)来覆盖该占位符。您不能在查询中混合使用这两种方法,如果这样做会得到。@Param@Param("someString")IllegalArgumentException

请注意,您可以混合使用 N1QL 占位符和 SpEL。N1QL 占位符仍将考虑所有方法参数,因此请务必使用正确的索引,如下例所示:

示例 78. 混合 SpEL 和 N1QL 占位符的内联查询

@Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} AND #{[0]} = $2")
public List<User> findUsersByDynamicCriteria(String criteriaField, Object criteriaValue)

这允许您生成与例如类似的查询。AND name = "someName"或者AND age = 3,使用单个方法声明。

您还可以在 N1QL 查询中进行单次投影(前提是它只选择一个字段并只返回一个结果,通常是一个聚合,如COUNT, AVG, MAX... )。这样的投影将有一个简单的返回类型,如long,boolean或String。这是打算预测到的DTO。

另一个例子:
#{#n1ql.selectEntity} WHERE #{#n1ql.filter} AND test = $1
相当于
SELECT #{#n1ql.fields} FROM #{#n1ql.bucket} WHERE #{#n1ql.filter} AND test = $1

SpEL 与 Spring Security 的实际应用

当您想要根据其他 Spring 组件(如 Spring Security)注入的数据进行查询时,SpEL 会很有用。这是扩展 SpEL 上下文以访问此类外部数据所需执行的操作。

首先,您需要实现一个
EvaluationContextExtension(使用如下支持类):

class SecurityEvaluationContextExtension extends EvaluationContextExtensionSupport {

  @Override
  public String getExtensionId() {
    return "security";
  }

  @Override
  public SecurityExpressionRoot getRootObject() {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    return new SecurityExpressionRoot(authentication) {};
  }
}

然后,为了让 Spring Data Couchbase 能够访问关联的 SpEL 值,您需要做的就是在配置中声明一个相应的 bean:

@Bean
EvaluationContextExtension securityExtension() {
    return new SecurityEvaluationContextExtension();
}

这对于根据连接用户的角色制作查询很有用,例如:

@Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} AND " +
"role = '?#{hasRole('ROLE_ADMIN') ? 'public_admin' : 'admin'}'")
List<UserInfo> findAllAdmins(); //only ROLE_ADMIN users will see hidden admins

删除查询示例:

@Query("#{#n1ql.delete} WHERE #{#n1ql.filter} AND " +
"username = $1 #{#n1ql.returning}")
UserInfo removeUser(String username);

第二种方法使用 Spring-Data 的查询派生机制从方法名称和参数构建 N1QL 查询。这将产生一个如下所示的查询:SELECT … FROM …​ WHERE firstName = "valueOfFnameAtRuntime". 您可以结合这些条件,甚至使用类似名称进行计数countByFirstname或使用类似名称进行限制findFirst3ByLastname...

实际上,生成的 N1QL 查询还将包含一个额外的 N1QL 标准,以便仅选择与存储库的实体类匹配的文档。

支持大多数 Spring-Data 关键字:.@Query (N1QL) 方法名称中支持的关键字

Spring Data Couchbase教程八

Spring Data Couchbase教程八

您可以使用此方法同时使用计数查询和限制查询结果功能。

使用 N1QL,存储库的另一个可能接口是
PagingAndSortingRepository(扩展CrudRepository)。它增加了两种方法:

Spring Data Couchbase教程八

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技能咖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值