Spring 带有 excerptProjection 的 RepositoryRestController

Spring RepositoryRestController with excerptProjection

我已经按照 here

的描述为我的 Spring 数据实体定义了一个 @Projection

出于与此处所述相同的原因。当我执行 GET 请求时,一切都按预期 returned。但是当我发出 POST 请求时,投影将不起作用。按照上面提供的示例,"Address" 在链接下显示为 URL,并且不会像 GET 请求那样公开。

如何让它以同样的方式暴露出来?

我用 @RepositoryRestController 创建了一个 class,我可以在其中捕获 POST 方法。如果我只是 return 实体,则它没有 links。如果我 return 它作为资源,link 就在那里,但是 "Address" 也是一个 link。如果我从控制器中删除 GET 方法,则默认行为如上所述。

更新

我的实体与描述的相同 here ABSuperClass 除了我没有 fetch在我的 @ManyToOne 中定义 我的控制器看起来像这样:

@RepositoryRestController
public class BRepositoryRestController {

  private final BRepository bRepository;

  public BRepositoryRestController(BRepository bRepository) {
    this.bRepository = bRepository;
  }


  @RequestMapping(method = RequestMethod.POST, value = "/bs")
  public 
  ResponseEntity<?> post(@RequestBody Resource<B> bResource) {
    B b= bRepository.save(bResource.getContent());
    BProjection result = bRepository.findById(b.getId());
    return ResponseEntity.ok(new Resource<>(result));
  }
}

我的存储库如下所示:

@RepositoryRestResource(excerptProjection = BProjection.class)
public interface BRepository extends BaseRepository<B, Long> {
  @EntityGraph(attributePaths = {"a"})
  BProjection findById(Long id);
}

我的投影是这样的:

@Projection(types = B.class)
public interface BProjection extends SuperClassProjection {
  A getA();
  String getSomeData();
  String getOtherData();      
}

而 SuperClassProjection 看起来像这样:

@Projection(types = SuperClass.class)
public interface SuperClassProjection {
  Long getId();
}

在自定义@RepositoryRestController POST 方法中,您还应该 return 投影。例如:

@Projection(name = "inlineAddress", types = { Person.class }) 
public interface InlineAddress {
    String getFirstName();
    String getLastName();
    @Value("#{target.address}") 
    Address getAddress(); 
}

public interface PersonRepo extends JpaRepository<Person, Long> {
    InlineAddress findById(Long personId); 
}

@PostMapping
public ResponseEntity<?> post(...) {
    //... posting a person
    InlineAddress inlineAddress = bookRepo.findById(person.getId());
    return ResponseEntity.ok(new Resource<>(inlineAddress));
}

更新

我已经更正了上面的代码和问题中的代码:

@RepositoryRestResource(excerptProjection = BProjection.class)
public interface BRepository extends CrudRepository<B, Long> {   
  BProjection findById(Long id);
}

@Projection(types = B.class)
public interface BProjection {
    @Value("#{target.a}")
    A getA();
    String getSomeData();
    String getOtherData();
}

然后一切正常。

POST 请求正文:

{
    "name": "b1",
    "someData": "someData1",
    "otherData": "otherData",
    "a": {
        "name": "a1"
    }
}

响应正文:

{
    "a": {
        "name": "a1"
    },
    "someData": "someData1",
    "otherData": "otherData",
    "_links": {
        "self": {
            "href": "http://localhost:8080/api/bs/1{?projection}",
            "templated": true
        }
    }
}

查看工作 example