【问题标题】:Selectively expand associations in Spring Data Rest response在 Spring Data Rest 响应中选择性地扩展关联
【发布时间】: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 以这种方式处理响应?

【问题讨论】:

标签: java spring rest spring-data spring-data-rest


【解决方案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 中实现这一点的最佳方法。

【讨论】:

    猜你喜欢
    • 2018-10-08
    • 2014-07-29
    • 2019-07-23
    • 1970-01-01
    • 2015-04-26
    • 2023-03-09
    • 1970-01-01
    • 2014-04-23
    • 2017-06-21
    相关资源
    最近更新 更多