Spring Data REST中通过父实体子资源端点添加子实体的可行性
可以实现!不过需要做一点配置调整
当然可以通过POST http://localhost:8080/appContext/a/12/childs/的方式创建B实体并自动关联到id为12的A,不用在请求体里写parent属性。不过默认情况下Spring Data Rest不会自动帮你完成这个关联绑定——它不会从URL路径里提取父实体的信息并设置到新创建的子实体上,需要我们加一点配置来实现这个逻辑。
下面是具体的实现步骤:
1. 配置Spring Data Rest确保关联端点正常工作
首先我们需要配置RepositoryRestConfigurer,确保实体的关联关系被正确暴露,同时可以按需暴露实体ID方便调试:
@Configuration public class SpringDataRestCustomConfig implements RepositoryRestConfigurer { @Override public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { // 暴露A和B的ID(可选,方便调试时查看) config.exposeIdsFor(A.class, B.class); // 确保B的仓库被Spring Data Rest正确识别 config.getRepositoryConfigurationFor(BRepository.class) .ifPresent(repoConfig -> repoConfig.setRepositoryDetectionStrategy(RepositoryDetectionStrategy.RepositoryDetectionStrategies.ANNOTATED)); } }
2. 添加事件监听器自动填充父实体关联
接下来我们需要一个事件监听器,监听B实体的创建事件,当请求来自/a/{id}/childs/路径时,自动从URL中提取A的ID,查询对应的A实例并设置为B的parent属性:
@Component public class BEntityCreationListener extends AbstractRepositoryEventListener<B> { private final ARepository aRepository; public BEntityCreationListener(ARepository aRepository) { this.aRepository = aRepository; } @Override protected void onBeforeCreate(B newBEntity) { // 获取当前请求的上下文信息 ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (requestAttributes == null) { return; } String requestUri = requestAttributes.getRequest().getRequestURI(); // 正则匹配URL中的A实体ID Matcher aIdMatcher = Pattern.compile("/a/(\\d+)/childs/?").matcher(requestUri); if (aIdMatcher.find()) { Integer aId = Integer.parseInt(aIdMatcher.group(1)); // 查询对应的A实体并设置为B的parent A parentA = aRepository.findById(aId) .orElseThrow(() -> new EntityNotFoundException("A实体不存在,ID:" + aId)); newBEntity.setParent(parentA); } } }
测试效果
现在你就可以发送POST请求到http://localhost:8080/appContext/a/12/childs/,请求体只需要包含B的其他属性(不需要parent字段),比如:
{}
或者如果B有其他字段的话:
{"someOtherField": "test value"}
Spring Data Rest会自动创建B实体,并且监听器会把它关联到id为12的A实体上,和你之前用POST /b/加parent字段的效果完全一致。
补充说明
默认情况下,如果你直接POST到/a/12/childs/而不加这个监听器,Spring Data Rest会创建B实体,但parent字段会是null——因为它不会主动从URL路径中提取父实体信息来填充关联。这个监听器的作用就是补上这个自动填充的逻辑。
内容的提问来源于stack exchange,提问作者Mssm
相关产品推荐
相关产品推荐

