在 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
请求的负载与 GET
s 返回的负载对称。但是,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
有关联,是否也可以将其添加到原始响应中?
我认为如果您的MyProjection
的getOtherDomain()
方法将投影返回到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 Data REST 是不是支持响应式 crud 存储库?
混合 Spring MVC + Spring Data Rest 会导致奇怪的 MVC 响应