在 Spring Data Rest 响应中选择性地扩展关联

Posted

技术标签:

【中文标题】在 Spring Data Rest 响应中选择性地扩展关联【英文标题】:Selectively expand associations in Spring Data Rest response 【发布时间】:2014-05-28 04:14:32 【问题描述】:

我有一个标准的 Spring 数据 JPA 和 Spring 数据 Rest 设置,它们正确地返回关联作为指向正确资源的链接。


    "id": 1,
    "version": 2,
    "date": "2011-11-22",
    "description": "XPTO",
    "_links": 
        "self": 
            "href": "http://localhost:8000/api/domain/1"
        ,
        "otherDomain": 
            "href": "http://localhost:8000/api/domain/1/otherDomain"
        
    
   

但是,在 一些 请求中,我希望扩展与“otherDomain”的关联(因此客户端不必执行 N+1 次请求即可获取完整数据)。

是否可以配置 Spring Data Rest 以这种方式处理响应?

【问题讨论】:

spring-data-rest, can you provide full details of entity instead of (or with) link 的可能重复项 【参考方案1】:

默认响应必须保持不变,以确保 PUT 请求的负载与 GETs 返回的负载对称。但是,Spring Data REST 引入了一个称为投影的功能(有关详细信息,请参阅JIRA ticket),其工作原理如下:

您创建一个专用接口并添加您想要包含在响应中的所有属性:

public interface MyProjection 

  String getMyProperty();

  MyRelatedObject getOtherDomain();

你可以

使用@Projection 对接口进行注释,并将其放在与域类型或其子包完全相同的包中 或者您使用RepositoryRestConfiguration 手动注册投影并手动调用projectionConfiguration().addProjection(…)(通过扩展RepositoryRestMvcConfiguration 并覆盖configureRepositoryRestConfiguration(…))。

这将导致为域类型公开的资源接受带有投影名称的projection 参数(名称也可配置ProjectionConfiguration)。如果给定,我们将跳过默认渲染(包括渲染相关实体的链接而不是嵌入它们)并让 Jackson 渲染支持给定接口的代理。

在Spring RESTBucks 项目中也可以找到一个例子。接口定义见OrderProjection

【讨论】:

是否可以通过投影进一步向下扩展层次结构?例如,如果otherDomain 后面的对象本身与oneMoreDomain 有关联,是否也可以将其添加到原始响应中? 我认为如果您的MyProjectiongetOtherDomain() 方法将投影返回到oneMoreDomain,那么这是可能的。 @Oliver Gierke,你救了我一些培根!这真的应该在官方文档中,我想知道为什么不是:(docs.spring.io/spring-data/rest/docs/2.2.1.RELEASE/reference/…我实际上想为默认投影扩展一些EAGER关联,但我似乎不能这样做:(你知道怎么做吗? ? 所以现在,@Projection 工作......归档jira.spring.io/browse/DATAREST-419 Oliver,我认为参考文档没有提到相同包或子包的要求。 @WillieWheeler - 很好,我为此创建了DATAREST-508。【参考方案2】:

我的解决方案适用于所有个请求,但有些人可能会觉得它相关。

我有一个类似的情况,我在 User json 响应中嵌套了 userPersons 关联,如下所示:


"_embedded":
  "users":[
     
        "userName":"Albert"
        "userPersons":[
           
              "personId":2356,
              "activeBoolean":1
           ,
           
              "personId":123617783,
              "activeBoolean":1
           
        ],
        "_links":
           "self":
              "href":"http://localhost:8080/api/users/1"
           
        
     
  ]

我的基础实体是这样的:

@Entity
public class User 


...

@Getter @Setter
private String userName;

@Getter @Setter
@OneToMany(mappedBy = "user")
private Set<Userperson> userPersons;

还有一个存储库:

@RepositoryRestResource
public interface UserRepo extends JpaRepository<User, Integer> 

我的解决办法是这样的:

通过简单地暴露一个用户@RepositoryRestResource,Spring Data Rest 将嵌入你的关联。

如果你为嵌套类型定义了一个@RepositoryRestResource,Spring Data Rest 会渲染一个指向资源的链接而不是嵌入它。

如果您需要内部业务逻辑的嵌套类型存储库,请将其设置为 @RepositoryRestResource(exported = false),以具有相同的行为。

为了避免 1+N 的问题,您可以为预先加载配置关联,也许使用 @EntityGraph 像 this guy - 虽然我还没有找到在 Spring Data Rest 中实现这一点的最佳方法。

【讨论】:

以上是关于在 Spring Data Rest 响应中选择性地扩展关联的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Data rest json Response 中动态过滤实体字段

Spring:在 REST 调用响应中插入 cookie

Spring Data REST 是不是支持响应式 crud 存储库?

混合 Spring MVC + Spring Data Rest 会导致奇怪的 MVC 响应

如何将 spring-data-rest 与 spring websocket 混合到一个实现中

@ManyToOne关系在Spring Data REST中插入空对象