Spring Data Codd RC1 的新特性

工程 | Oliver Drotbohm | 2014年2月7日 | ...

随着 Spring Data 发布列车目前正在开发的最后阶段临近,我认为是时候向您简要概述我们将在此版本中引入的一些新特性了。

如果您还不知道,发布列车是多个 Spring Data 模块的协调发布,以确保它们开箱即用地无缝协作。当前的发布列车以关系模型的发明者 Edgar F. Codd 的名字命名。

Spring Data Commons

由于 Spring Data Commons 模块为发布列车中包含的所有其他模块奠定了基础,因此其中的新特性也适用于各个存储模块。

对于 Codd 版本,我们将最低所需的 Spring 版本提升至 3.2.7,并改进了与 Spring 4.0 的兼容性,以便在更新到最新的 Spring 版本时提供无缝体验。当使用 Spring 4 和 Java 8 运行您的应用程序时,Spring Data 审计功能现在能够使用 JSR-310 类型填充实体的创建和修改日期。

abstract class BaseEntity {
    
    @CreatedDate ZonedDateTime createdDate;
    @LastModifiedDate ZonedDateTime modifiedDate;
}

此外,现在可以使用特定于模块的 @Enable…Auditing 注解(在 Thomas Darimont 关于第一个里程碑中引入的新特性的 博文 中了解更多信息)来激活审计功能。

从 Codd 开始,Spring Data 存储库将被急切地实例化,以确保存储库接口的验证被急切地触发,即使没有注入点在容器启动时显式请求存储库实例。要回退到旧的行为,请在存储库接口上使用 @Lazy 注解,就像您对其他 Spring bean 定义所做的那样。

在 Spring MVC 的 Web 支持方面,Spring Data 的 PagedResourcesAssembler 现在创建符合 RFC-6570 中定义的标准的页面导航链接。假设您有一个像这样的 Spring MVC 控制器

@Controller
class OrderController {
    
    @RequestMapping("/orders")
    HttpEntity<PagedResources<Resource<Order>>> showOrders(Pageable pageable, 
        PagedResourcesAssembler<Order> assembler) {

        Page<Order> orders = orderRepository.findAll(pageable);
        return new ResponseEntity<>(assembler.toResource(orders), HttpStatus.OK);
    }
}

PagedResourcesAssembler 将检查给定的 OrderPage,呈现内容和页面元信息,并根据需要添加 prevnext 链接。

GET /orders?page=0&size=10
Accept: application/hal+json

200 OK
{ _links : { self : { href : "/orders{?page,size,sort}",
                      templated : true },
             next : { href : "/orders?page=1&size=10" }},

  _embedded :  { orders : [ … ] },

  page : {
    size : 1,
    totalElements : 2,
    totalPages : 2,
    number : 0
  }
}

如您所见,self 链接清楚地指示了资源为自定义响应而接受的参数。next 链接提供了对与当前给定参数相对应的下一页的访问。

为了总结,Commons 模块对配置评估方式进行了重大更改,这将显著提高引导时间,尤其是在具有大量存储库的应用程序中。

Spring Data JPA

Spring Data JPA 模块主要进行了内部改进,并在与 JPA 和 CDI 的交互方面引入了新特性:我们升级到 EclipseLink 2.5.1 并改进了与 Hibernate 4.3 的兼容性,以确保我们的用户可以使用基于 JPA 2.1 的持久性提供程序。

用于 EntityManager 的构造函数注入

一个被反复请求的功能也已包含在此版本中:在设计应用程序组件时,能够将 EntityManager 实例注入到构造函数中。如果您编写需要访问 JPA EntityManager 的类,通常会使用 @PersistenceContext 来触发其注入。但是,我们通常认为构造函数注入是 多种原因 的最佳实践,因此无需对 EntityManager 回退到字段注入。

不幸的是,@PersistenceContext 注解目前不能用于构造函数参数。我已经为此 在 JPA 错误跟踪器中提交了一个工单,但我们当然不必等到 JPA 2.2 发布才能看到该功能。从 Spring Data JPA 1.5 版本开始,您将能够编写如下应用程序组件

class UserRepositoryImpl implements UserRepositoryCustom {
    
    private final EntityManager em;

    @Autowired // or @Inject
    public UserRepositoryImpl(EntityManager em) {
        this.em = em;
    }

    …
}

默认情况下,我们将注入由您 ApplicationContext 中声明的 EntityManagerFactoryBean 创建的 EntityManager 实例。如果您定义了多个,则可以使用 @Qualifier 指向您想要从中获取 EntityManagerEntityManagerFactoryBean 的 bean 名称。

在 CDI 环境中急切实例化存储库

当在 Spring 容器中使用 Spring Data 存储库时,存储库会被急切地实例化。即使在 Codd 之前,只要客户端组件通过注入点请求存储库,它们就会被实例化。因此,无论何时将存储库注入到客户端,您都可以确保获得一个完全初始化的应用程序组件,这仅仅是因为 Spring 组件模型保证了这一点。

然而,在 CDI 世界中,情况略有不同。当您访问应用程序组件时,无法保证其依赖项已初始化,因为在 CDI 组件模型中,只需注入代理并在第一次使用时触发实际的实例创建就可以了。

实际上,这可能导致 Spring Data 存储库在您的应用程序代码已经运行 JPA 事务时被实例化。存储库实例化的一部分是检查 JPA 命名查询以支持查询方法。根据 JPA 规范,此类命名查询的不存在(这在 Spring Data 上下文中是完全预期的状态)必须通过抛出异常来表达,并且根据定义,此异常必须在 JPA 中触发事务回滚。

这意味着通过在 CDI 中将应用程序组件初始化与正在运行的业务代码混合,当前者被调用时,您有可能会破坏后者。不幸的是,在 CDI 中没有办法开箱即用地强制急切实例化应用程序组件。有一些 特定于容器的方法,但没有一个在所有容器上都能可靠地工作(如果您碰巧找到一个,我将非常感兴趣)。

使用 Spring Data JPA 1.5,我们将提供一个 @Eager 注解,它将导致我们的 CDI 扩展触发存储库,从而避免应用程序组件创建和业务代码执行的重叠。

Spring Data REST

Spring Data REST 中的核心变化主要是一些重大的重构,尤其是在模块的映射配置和自定义部分。这还包括对我们为各个资源公开的默认关系类型的更改。

对于每个资源库,Spring Data REST 都会公开一个专用的 REST 资源,该资源遵循集合资源模式。这意味着我们有一个专用于实体集合的资源,以及一个专用于集合中每个项目的资源。

由于正确的 REST 客户端不应该自己创建它们交互的 URI,而是使用超媒体来遵循服务器提供的链接,因此我们需要公开两种不同的关系类型来指示集合资源和项目资源之间的区别。

从 Spring Data REST 2.0 开始,项目资源的关系类型是从资源库管理的域类的名称派生的。然后,集合资源的关系类型通过使用Evo Inflector库对项目资源关系进行复数化来派生。因此,对于管理Order实例的资源库,您将看到名为orders的链接指向集合资源,以及名为order的链接指向项目资源。

关系类型的这种变化对于 Spring Data REST 1.x 版本服务的超媒体客户端来说是一个重大变化,这也是将模块版本提升到 2.0 的主要原因之一。另一个方面是,随着模块的 M1 版本,我们转向了HAL作为 Spring Data REST 公开的默认媒体类型。我们正在研究对其他超媒体格式的支持,例如Collection+JSON等,但 HAL 似乎获得了相当多的关注。亚马逊最近发布了他们的AppStream REST API,并使用 HAL 作为表示格式。

Spring Data Neo4j / MongoDB

Spring Data Neo4j 模块中最大的变化(因此版本号变为 3.0)是支持 Neo4j 2.0。因此,要利用该版本中最新和最强大的功能,请务必尝试一下 Codd 发布候选版本。

在 MongoDB 方面,最重要的新功能是在聚合框架中支持 Spring 表达式语言。Spring Data 工程师 Thomas Darimont 有一篇关于我们已在 Codd 的 M1 版本中发布的所有功能的详细博文,以防您错过了它。

如上所述,当然,Codd 中引入的所有 Spring Data Commons 的新功能实际上也都会传递到 Neo4j 和 MongoDB 模块中。

展望

GA 版本计划于 2014 年 2 月底发布。我们在 Spring Data Commons wiki 中有一个精心策划的更改日志,其中列出了此版本中引入的所有重要功能。

我们感谢您进行任何预发布测试,并在我们的JIRA实例中报告发现的任何潜在问题。

获取 Spring 时事通讯

与 Spring 时事通讯保持联系

订阅

抢先一步

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

了解更多

获取支持

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

了解更多

即将举行的活动

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

查看全部