全面的大量新功能,尤其是Reactive,Kotlin和Performance。包括整个产品组合中的大量改进和新功能,并且重点关注三个主要主题:Reactive,Kotlin和Performance。该版本增加了声明式反应式事务和协程/流程支持等功能,并提供了高达 60%* 更快的查找器方法。
让我们从Moore的一些Reactive功能开始。
声明式Reactive事务
Lovelace发行版 以 封闭式的方式 引入了对响应式事务的早期支持,从而留出了一些改进的空间。以下清单显示了该样式:
Lovelace中的反应式事务(使用MongoDB)
<b>public</b> Mono<Process> doSomething(Long id) { <b>return</b> template.inTransaction().execute(txTemplate -> { <b>return</b> txTemplate.findById(id) .flatMap(it -> start(txTemplate, it)) .flatMap(it -> verify(it)) .flatMap(it -> finish(txTemplate, it)); }).next(); }
在前面的代码段中,必须通过inTransaction()在闭包内使用可识别事务的模板显式调用来启动事务,最后调用next()以将返回值Flux转换为a Mono来满足方法签名,即使findById(…)已经仅发出一个元素。
显然,这不是进行反应式事务的最直观的方法。因此,让我们看看使用声明式反应式事务支持的相同流程。与Spring的事务 支持一样 ,您需要一个组件来为您处理交易。对于反应式事务,
ReactiveTransactionManager是由MongoDB和R2DBC模块提供。以下清单显示了这样的组件: @EnableTransactionManagement <b>class</b> Config <b>extends</b> AbstractReactiveMongoConfiguration { <font><i>// …</i></font><font> @Bean ReactiveTransactionManager mgr(ReactiveMongoDatabaseFactory f) { <b>return</b> <b>new</b> ReactiveMongoTransactionManager(f); } } </font>
在这里,您可以使用@Transactional基础结构来注释方法,并依靠该基础结构来启动,提交和回滚事务流,以通过 Reactor Context 处理生命周期。这可以让你把代码从Lovelace转换成以下方法,删除与它的作用域模板和多余的封闭的需要Flux来Mono改造:
Declarative Reactive Transactions in Moore (with MongoDB)
@Transactional <b>public</b> Mono<Process> doSomething(Long id) { <b>return</b> template.findById(id) .flatMap(it -> start(template, it)) .flatMap(it -> verify(it)) .flatMap(it -> finish(template, it)); }
响应式Elasticsearch存储库
Spring Data Elasticsearch现在提供了反应性模板和存储库支持,该支持基于完全基于反应式Elasticsearch REST客户端而又基于Spring的REST客户端构建WebClient。
该客户端通过在Java High-Level REST Client附近公开一个熟悉的API,为日常搜索操作提供一流的支持,并在需要时进行必要的削减。模板和存储库API的组合使您可以根据需要无缝过渡到响应式而不会迷失方向。以下清单显示了如何配置Elasticsearch以使用反应式客户端:
<b>class</b> Config <b>extends</b> AbstractReactiveElasticsearchConfiguration { <font><i>// …</i></font><font> @Bean <b>public</b> ReactiveElasticsearchClient reactiveClient() { <b>return</b> ReactiveRestClients.create(localhost()); } } @Autowired ReactiveElasticsearchTemplate template; </font><font><i>//…</i></font><font> Criteria criteria = <b>new</b> Criteria(</font><font>"topics"</font><font>).contains(</font><font>"spring"</font><font>) .and(</font><font>"date"</font><font>).greaterThanEqual(today()) Flux<Conference> result = template.find(<b>new</b> CriteriaQuery(criteria), Conference.<b>class</b>); </font>
反应式查询
Querydsl 提供了一种出色的方式来定义多个数据存储的类型安全查询,并且已经有相当长的一段时间支持非反应性数据访问。为了在响应式场景中提供支持,我们添加了响应式执行层,可让您运行Predicate支持的查询。的ReactiveQuerydslPredicateExecutor,当添加到存储库接口,提供了所有的入口点,如下面的示例所示:
<b>interface</b> SampleRepository <b>extends</b> …, ReactiveQuerydslPredicateExecutor<…> { <font><i>// …</i></font><font> } @Autowired SampleRepository repository; </font><font><i>// …</i></font><font> Predicate predicate = QCustomer.customer.lastname.eq(</font><font>"Matthews"</font><font>); Flux<Customer> result = repository.findAll(predicate); </font>
支持Kotlin协程和MongoDB标准API DSL
点击标题见原文
性能提升
基准测试显示JPA单属性查找器方法(例如findByTitle(…))的吞吐量提高了近60%
实体回调API
支持Redis流
JPA存储过程的多个输出参数
@NamedStoredProcedureQuery(name = <font>"User.s1p"</font><font>, procedureName = </font><font>"s1p"</font><font>, parameters = { @StoredProcedureParameter(mode = IN, name = </font><font>"in_1"</font><font>, type = …), @StoredProcedureParameter(mode = OUT, name = </font><font>"out_1"</font><font>, type = …), @StoredProcedureParameter(mode = OUT, name = </font><font>"out_2"</font><font>, type = …)}) @Table(name = </font><font>"SD_User"</font><font>) <b>class</b> User { … } <b>interface</b> UserRepository <b>extends</b> JpaRepository<…> { @Procedure(name = </font><font>"User.s1p"</font><font>) Map<String, Integer> callS1P(@Param(</font><font>"in_1"</font><font>) Integer arg); } </font>
关于存储库方法的声明性MongoDB聚合
使用MongoDB,复杂的数据处理是通过 聚合 来完成的,对于这些 聚合 ,Spring Data提供了一个特定的(流利的)API,并对操作和表达式进行了抽象。但是,Stackoverflow告诉我们人们倾向于在命令行上进行聚合,然后将其转换为Java代码。该翻译原来是一个主要的痛点。因此,我们借此机会介绍@Aggregation了一种在存储库方法中运行聚合的直接方法。以下示例显示了如何执行此操作:
声明式MongoDB聚合:
<b>interface</b> OrderRepository <b>extends</b> CrudRepository<Order, Long> { @Aggregation(<font>"{ $group : { _id : '$cust_id', total : { $sum : '$amount' }}}"</font><font>) List<TotalByCustomer> totalByCustomer(Sort sort); @Aggregation(pipeline = { </font><font>"{ $match : { customerId : ?0 }}"</font><font>, </font><font>"{ $count : total }"</font><font> }) Long totalOrdersForCustomer(String customerId); } </font>
@Aggregation像它的亲戚@Query注释一样支持参数替换,并且如果由查询方法参数提供,则对聚合添加排序,如前面的示例所示。
还有更多
点击标题见原文