为什么Spring Data REST项目资源不会自动应用摘录投影?

26

我做了一个投影,应该会显示嵌套实体:

@Projection(name = "inlineBusiness", types = { UserModel.class })
public interface InlineBusinessUserModelProjection {

    String getUsername();

    String getFirstName();

    String getLastName();

    Date getBirthdate();

    String getEmail();

    BusinessModel getBusiness();
}

还有服务存储库:

@RepositoryRestResource(collectionResourceRel = "users", path = "users",
       excerptProjection = InlineBusinessUserModelProjection.class)
public interface UserRepository extends BaseDAO<UserModel> {..}

对于/users,它能正常工作,业务字段与嵌套实体一起公开,但是当我调用/users/1时-没有任何响应,所有自定义方法也都是如此。似乎除了/users之外,投影在任何方法上都没有被涉及。

有什么想法吗?

2个回答

42

这是按设计实现的。当目标类型(在您的情况下为UserModel)的实例在_embedded子句内使用时,会使用摘录投影。因此,摘录是一种预览,在资源本身未呈现但被指向的任何地方都可以使用。通常集合资源或关联资源情况下会这样做。

从另一个角度来看,对于项目资源默认使用摘录投影并不太有意义:摘录投影是一些域对象的只读视图。如果默认返回该视图给项目资源,客户端如何知道要发送哪些数据以更新资源。为摘录投影创建的JSON文档不能简单地被获取、修改并用于发送PUT请求以更新资源 - 根据定义而言。

如果您想将投影应用于项目资源,请使用名称为投影的值填充projection URI模板变量。

编辑:如果您手动选择后投影没有应用,请确保InlineBusinessUserModelProjection实际上已注册供普遍使用。请确保该类型位于与UserModel完全相同的包或子包中。 或者通过RepositoryRestConfiguration.projectionConfiguration().addProjection(…)手动注册投影。手动配置使得在投影类型上使用@Projection变得过时。

Spring Data REST参考文档中了解更多有关此主题的信息。


谢谢,我现在明白了。但不知为何,即使我在/users/1中提供了?projection=inlineBusiness,它也不能正常工作...在/alps/users/内部也没有关于inlineBusiness的任何通知。 - nKognito
/users/1/projection=inlineBusiness 也没有返回任何结果。 - nKognito
我已经编辑了我的答案,并在通用用途的投影注册上进行了备注。 - Oliver Drotbohm
@OliverGierke,我遇到了一个相关问题。我已经成功地在单个uri调用中使用我的投影,例如:**/api/users/1?projection=withAddress**,但是如果我调用 /api/users?projection=withAddress 就无法工作。这是唯一的方法来使用摘录使其工作吗? - Tirias
1
根据最新的Spring Data REST文档,@Projection永远不会过时: 无论哪种情况,您的投影接口必须具有@Projection注释。 - theFriedC
显示剩余6条评论

2

我不打算和@Oliver Drotbohm争论,因为这确实是正确的答案,但是,如果你想要一个聪明的解决方法,只需为实体字段定义一个略有不同名称的getter函数(使用OP的示例):

BusinessModel getBusinessInline() { return this.businessModel; }

将会得到一个JSON负载:
{
    .
    .
    "businessInline": {"name":"stuff etc"}
    .
    .
}

假设您的消费服务能够接受这一点,那么这是一个选项。

虽然不高明,但它有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接