乐趣区

关于spring:Spring-Data-JPA-参考文档三

原题目:Spring 认证 |Spring Data JPA 参考文档三(内容起源:Spring 中国教育管理中心)

Spring Data JPA 参考文档三
手动接线

如果您的自定义实现仅应用基于注解的配置和主动拆卸,则后面显示的办法成果很好,因为它被视为任何其余 Spring bean。如果您的实现片段 bean 须要非凡连贯,您能够依据上一节中形容的约定申明 bean 并为其命名。而后,基础设施通过名称援用手动定义的 bean 定义,而不是本人创立一个。以下示例显示了如何手动连贯自定义实现:

示例 38. 自定义实现的手动接线

<repositories base-package=”com.acme.repository” />

<beans:bean id=”userRepositoryImpl” class=”…”>

<!– further configuration –>

</beans:bean>

4.6.2. 自定义根底存储库

当您想要自定义根本存储库行为以便影响所有存储库时,上一节中形容的办法须要自定义每个存储库接口。要改为更改所有存储库的行为,您能够创立一个扩大持久性技术特定存储库基类的实现。而后,此类充当存储库代理的自定义基类,如以下示例所示:

示例 39. 自定义存储库基类

class MyRepositoryImpl<T, ID>

extends SimpleJpaRepository<T, ID> {

private final EntityManager entityManager;

MyRepositoryImpl(JpaEntityInformation entityInformation,

EntityManager entityManager) {

super(entityInformation, entityManager);

// Keep the EntityManager around to used from the newly introduced methods.

this.entityManager = entityManager;

}

@Transactional

public <S extends T> S save(S entity) {

// implementation goes here

}

}

Spring Data JPA 参考文档三
该类须要具备特定于商店的存储库工厂实现应用的超类的构造函数。如果存储库基类有多个构造函数,则笼罩一个 EntityInformation 加上存储特定根底构造对象(例如一个 EntityManager 或模板类)的构造函数。

最初一步是让 Spring Data 基础设施晓得定制的存储库基类。在 Java 配置中,您能够应用注解的 repositoryBaseClass 属性来实现 @Enable${store}Repositories,如下例所示:

示例 40. 应用 JavaConfig 配置自定义存储库基类

@Configuration

@EnableJpaRepositories(repositoryBaseClass = MyRepositoryImpl.class)

class ApplicationConfiguration {…}

XML 命名空间中提供了相应的属性,如以下示例所示:

示例 41. 应用 XML 配置自定义存储库基类

<repositories base-package=”com.acme.repository”

base-class=”….MyRepositoryImpl” />

4.7. 从聚合根公布事件

存储库治理的实体是聚合根。在域驱动设计应用程序中,这些聚合根通常公布域事件。Spring Data 提供了一个名为的正文 @DomainEvents,您能够在聚合根的办法上应用该正文,以使该公布尽可能简略,如以下示例所示:

示例 42. 从聚合根公开域事件

class AnAggregateRoot {

@DomainEvents

Collection<Object> domainEvents() {

// … return events you want to get published here

}

@AfterDomainEventPublication

void callbackMethod() {

// … potentially clean up domain events list

}

}

应用的办法 @DomainEvents 能够返回单个事件实例或事件汇合。它不能承受任何论据。

公布所有事件后,咱们就有了一个用 @
AfterDomainEventPublication. 您能够应用它潜在地清理要公布的事件列表(以及其余用处)。

该办法被称为一个 Spring 数据存储库的每一次一个 save(…),saveAll(…),delete(…)或 deleteAll(…)办法被调用。

4.8. Spring 数据扩大

本节记录了一组 Spring Data 扩大,这些扩大反对在各种上下文中应用 Spring Data。目前,大部分集成都针对 Spring MVC。

4.8.1. Querydsl 扩大

Querydsl 是一个框架,能够通过其晦涩的 API 构建动态类型的 SQL 类查问。

几个 Spring Data 模块通过 提供与 Querydsl 的集成 QuerydslPredicateExecutor,如以下示例所示:


43.QuerydslPredicateExecutor 接口

public interface QuerydslPredicateExecutor<T> {

Optional<T> findById(Predicate predicate);

Iterable<T> findAll(Predicate predicate);

long count(Predicate predicate);

boolean exists(Predicate predicate);

// … more functionality omitted.

}

查找并返回与 匹配的单个实体 Predicate。

查找并返回与 匹配的所有实体 Predicate。

返回与 匹配的实体数 Predicate。

返回匹配的实体是否 Predicate 存在。

Spring Data JPA 参考文档三
要应用 Querydsl 反对,请扩大 QuerydslPredicateExecutor 您的存储库界面,如以下示例所示:

示例 44. 存储库上的 Querydsl 集成

interface UserRepository extends CrudRepository<User, Long>, QuerydslPredicateExecutor<User> {

}

后面的示例容许您应用 QuerydslPredicate 实例编写类型平安的查问,如以下示例所示:

Predicate predicate = user.firstname.equalsIgnoreCase(“dave”)

.and(user.lastname.startsWithIgnoreCase(“mathews”));

userRepository.findAll(predicate);

4.8.2. 网络反对

反对存储库编程模型的 Spring Data 模块附带了各种 Web 反对。Web 相干组件要求 Spring MVC JAR 位于类门路上。其中一些甚至提供与 Spring HATEOAS 的集成。通常,通过应用 @
EnableSpringDataWebSupportJavaConfig 配置类中的正文来启用集成反对,如以下示例所示:

示例 45. 启用 Spring Data Web 反对

@Configuration

@EnableWebMvc

@EnableSpringDataWebSupport

class WebConfiguration {}

该 @
EnableSpringDataWebSupport 批注注册几个组件。咱们将在本节前面探讨这些。它还检测类门路上的 Spring HATEOAS 并为其注册集成组件(如果存在)。

或者,如果您应用 XML 配置,请注册
SpringDataWebConfiguration 或 HateoasAwareSpringDataWebConfiguration 作为 Spring bean,如以下示例所示(对于 SpringDataWebConfiguration):

示例 46. 在 XML 中启用 Spring Data Web 反对

<bean class=”org.springframework.data.web.config.SpringDataWebConfiguration” />

<!– If you use Spring HATEOAS, register this one instead of the former –>

<bean class=”org.springframework.data.web.config.HateoasAwareSpringDataWebConfiguration” />

根本网络反对

上一节中显示的配置注册了一些根本组件:

A 应用 DomainClassConverter 类让 Spring MVC 从申请参数或门路变量解析存储库治理的域类的实例。

HandlerMethodArgumentResolver 让 Spring MVC 从申请参数解析 Pageable 和 Sort 实例的实现。

Jackson Modules 用于反 / 序列化 Point 和 等类型 Distance,或存储特定类型,具体取决于所应用的 Spring 数据模块。

应用 DomainClassConverter 类

本 DomainClassConverter 类让你在 Spring MVC 中的控制器办法签名应用域类型间接使您不用手动通过资源库查找的状况下,如下例所示:

示例 47. 在办法签名中应用域类型的 Spring MVC 控制器

@Controller

@RequestMapping(“/users”)

class UserController {

@RequestMapping(“/{id}”)

String showUserForm(@PathVariable(“id”) User user, Model model) {

model.addAttribute(“user”, user);

return “userForm”;

}

}

Spring Data JPA 参考文档三
该办法 User 间接接管实例,不须要进一步查找。能够通过让 Spring MVCid 先将门路变量转换为域类的类型,最终通过调用 findById(…)为域类型注册的存储库实例来拜访实例来解析实例。

目前,存储库必须实现 CrudRepository 能力被发现进行转换。

用于可分页和排序的
HandlerMethodArgumentResolvers

的配置片段中,在示出前一节还注册一个
PageableHandlerMethodArgumentResolver,以及实例 SortHandlerMethodArgumentResolver。注册启用 Pageable 并 Sort 作为无效的控制器办法参数,如以下示例所示:

示例 48. 应用 Pageable 作为控制器办法参数

@Controller

@RequestMapping(“/users”)

class UserController {

private final UserRepository repository;

UserController(UserRepository repository) {

this.repository = repository;

}

@RequestMapping

String showUsers(Model model, Pageable pageable) {

model.addAttribute(“users”, repository.findAll(pageable));

return “users”;

}

}

Spring Data JPA 参考文档三
后面的办法签名导致 Spring MVC 尝试 Pageable 应用以下默认配置从申请参数派生实例:

Spring Data JPA 参考文档三
要自定义此行为,请别离注册一个实现
PageableHandlerMethodArgumentResolverCustomizer 接口或 SortHandlerMethodArgumentResolverCustomizer 接口的 bean。它的 customize() 办法被调用,让您更改设置,如以下示例所示:

@Bean SortHandlerMethodArgumentResolverCustomizer sortCustomizer() {

return s -> s.setPropertyDelimiter(“<–>”);

}

如果设置现有的属性 MethodArgumentResolver 不足以满足您的目标,请扩大
SpringDataWebConfiguration 或启用 HATEOAS 的等效项,笼罩 pageableResolver() 或 sortResolver()办法,并导入您的自定义配置文件而不是应用 @Enable 正文。

如果您须要从申请中解析多个 Pageable 或多个 Sort 实例(例如,对于多个表),您能够应用 Spring 的 @Qualifier 注解来辨别一个和另一个。申请参数必须以 为前缀 ${qualifier}_。以下示例显示了生成的办法签名:

String showUsers(Model model,

@Qualifier(“thing1”) Pageable first,

@Qualifier(“thing2”) Pageable second) {…}

您必须填充 thing1_page、thing2_page 等。

Pageable 传递给办法的默认值等效于 a PageRequest.of(0, 20),但您能够通过应用参数 @PageableDefault 上的正文来自定义它 Pageable。

对可分页的超媒体反对

Spring HATEOAS 附带了一个示意模型类 (PagedResources),它容许 Page 应用必要的 Page 元数据和链接来丰盛实例的内容,让客户端轻松导航页面。aPage 到 a 的转换 PagedResources 是由 Spring HATEOASResourceAssembler 接口的实现实现的,称为 PagedResourcesAssembler. 以下示例显示了如何应用 aPagedResourcesAssembler 作为控制器办法参数:

示例 49. 应用 PagedResourcesAssembler 作为控制器办法参数

@Controller

class PersonController {

@Autowired PersonRepository repository;

@RequestMapping(value = “/persons”, method = RequestMethod.GET)

HttpEntity<PagedResources<Person>> persons(Pageable pageable,

PagedResourcesAssembler assembler) {

Page<Person> persons = repository.findAll(pageable);

return new ResponseEntity<>(assembler.toResources(persons), HttpStatus.OK);

}

}

启用配置,如后面的示例所示,能够 PagedResourcesAssembler 将 用作控制器办法参数。调用 toResources(…)它有以下成果:

的内容 Page 成为 PagedResources 实例的内容。

该 PagedResources 对象 PageMetadata 附加了一个实例,并填充了来自 Page 和底层 的信息 PageRequest。

将 PagedResources 可能会 prev 和 next 连贯链路,依据页面的状态。链接指向办法映射到的 URI。增加到该办法的分页参数与 的设置相匹配,
PageableHandlerMethodArgumentResolver 以确保稍后能够解析链接。

假如咱们 Person 在数据库中有 30 个实例。您当初能够触发申请 () 并看到相似于以下内容的输入:GET
http://localhost:8080/persons

{“links” : [ { “rel” : “next”,

“href” : “http://localhost:8080/persons?page=1&size=20” }

],

“content” : [

… // 20 Person instances rendered here

],

“pageMetadata” : {

“size” : 20,

“totalElements” : 30,

“totalPages” : 2,

“number” : 0

}

}

组装器生成了正确的 URI 并抉择了默认配置,以将参数解析 Pageable 为行将到来的申请。这意味着,如果您更改该配置,链接将主动恪守更改。默认状况下,汇编器指向调用它的控制器办法,但您能够通过传递一个自定义 Link 来自定义它,该自定义用作构建分页链接的根底,这会重载该
PagedResourcesAssembler.toResource(…) 办法。

Spring Data Jackson 模块

外围模块和一些特定于商店的模块附带一组 Jackson 模块,用于 Spring Data 域应用的类型,例如
org.springframework.data.geo.Distance 和 org.springframework.data.geo.Point。

一旦启用 Web 反对并可用,
com.fasterxml.jackson.databind.ObjectMapper 就会导入这些模块。

在初始化期间 SpringDataJacksonModules,像 一样
SpringDataJacksonConfiguration,被基础设施接管,以便申明的 com.fasterxml.jackson.databind.Modules 可供 Jackson 应用 ObjectMapper。

以下域类型的数据绑定混合由公共根底构造注册。

org.springframework.data.geo.Distance

org.springframework.data.geo.Point

org.springframework.data.geo.Box

org.springframework.data.geo.Circle

org.springframework.data.geo.Polygon

单个模块可能会提供额定的 SpringDataJacksonModules.

无关更多详细信息,请参阅商店特定局部。

网页数据绑定反对

您能够应用 Spring Data 投影(在 Projections 中形容)通过应用 JSONPath 表达式(须要 Jayway JsonPath 或 XPath 表达式(须要 XmlBeam)来绑定传入的申请无效负载,如以下示例所示:

示例 50. 应用 JSONPath 或 XPath 表达式的 HTTP 负载绑定

@ProjectedPayload

public interface UserPayload {

@XBRead(“//firstname”)

@JsonPath(“$..firstname”)

String getFirstname();

@XBRead(“/lastname”)

@JsonPath({“$.lastname”, “$.user.lastname”})

String getLastname();

}

能够应用在后面的例子中为一个 Spring MVC 处理程序办法参数或通过应用所示类型
ParameterizedTypeReference 上的办法之一 RestTemplate。后面的办法申明将尝试查找 firstname 给定文档中的任何地位。该 lastnameXML 查问是对输出文档的顶层进行。其 JSON 变体 lastname 首先尝试顶级,但如果前者不返回值,也会尝试 lastname 嵌套在 user 子文档中。这样,无需客户端调用公开的办法(通常是基于类的无效负载绑定的毛病)即可轻松加重源文档构造的更改。

如 Projections 中所述,反对嵌套投影。如果该办法返回简单的非接口类型,ObjectMapper 则应用 Jackson 来映射最终值。

对于 Spring MVC,必要的转换器一旦 @
EnableSpringDataWebSupport 处于活动状态就会主动注册,并且所需的依赖项在类门路上可用。对于应用 RestTemplate,注册 ProjectingJackson2HttpMessageConverter(JSON)或 XmlBeamHttpMessageConverter 手动。

无关更多信息,请参阅标准 Spring 数据示例存储库中的 Web 投影示例。

Querydsl 网络反对

对于那些具备 QueryDSL 集成的商店,您能够从 Request 查问字符串中蕴含的属性派生查问。

思考以下查问字符串:

?firstname=Dave&lastname=Matthews

给定 User 后面示例中的对象,您能够应用 将查问字符串解析为以下值
QuerydslPredicateArgumentResolver,如下所示:

QUser.user.firstname.eq(“Dave”).and(QUser.user.lastname.eq(“Matthews”))

@
EnableSpringDataWebSupport 当在类门路上找到 Querydsl 时,会主动启用该性能以及。

将 a 增加 @QuerydslPredicate 到办法签名提供了一个随时可用的 Predicate,您能够应用
QuerydslPredicateExecutor.

类型信息通常从办法的返回类型解析。因为该信息不肯定与域类型匹配,因而应用 的 root 属性可能是一个好主见 QuerydslPredicate。

以下示例显示了如何 @QuerydslPredicate 在办法签名中应用:

@Controller

class UserController {

@Autowired UserRepository repository;

@RequestMapping(value = “/”, method = RequestMethod.GET)

String index(Model model, @QuerydslPredicate(root = User.class) Predicate predicate,

Pageable pageable, @RequestParam MultiValueMap<String, String> parameters) {

model.addAttribute(“users”, repository.findAll(predicate, pageable));

return “index”;

}

}

将查问字符串参数解析为匹配 Predicatefor User。

Spring Data JPA 参考文档三
默认绑定如下:

Object 在简略的属性上 eq。

Object 在像属性一样的汇合上 contains。

Collection 在简略的属性上 in。

您能够通过 Java 8 的 bindings 属性 @QuerydslPredicate 或通过应用 Java 8default methods 并将 QuerydslBinderCustomizer 办法增加到存储库接口来自定义这些绑定,如下所示:

interface UserRepository extends CrudRepository<User, String>,

QuerydslPredicateExecutor<User>,

QuerydslBinderCustomizer<QUser> {

@Override

default void customize(QuerydslBindings bindings, QUser user) {

bindings.bind(user.username).first((path, value) -> path.contains(value))

bindings.bind(String.class)

.first((StringPath path, String value) -> path.containsIgnoreCase(value));

bindings.excluding(user.password);

}

}

QuerydslPredicateExecutor 提供对特定 finder 办法的拜访 Predicate。

QuerydslBinderCustomizer 存储库界面上定义的主动拾取和快捷方式 @QuerydslPredicate(bindings=…)。

将 username 属性的绑定定义为简略 contains 绑定。

将 String 属性的默认绑定定义为不辨别大小写的 contains 匹配。

password 从 Predicate 解析中排除该属性。

Spring Data JPA 参考文档三
你能够注册一个
QuerydslBinderCustomizerDefaults 从资源库或利用特定的绑定之前豆放弃默认 Querydsl 绑定 @QuerydslPredicate。

退出移动版