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 A
、B
和 SuperClass
除了我没有 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
我已经按照 here
的描述为我的 Spring 数据实体定义了一个 @Projection出于与此处所述相同的原因。当我执行 GET
请求时,一切都按预期 returned。但是当我发出 POST
请求时,投影将不起作用。按照上面提供的示例,"Address" 在链接下显示为 URL,并且不会像 GET
请求那样公开。
如何让它以同样的方式暴露出来?
我用 @RepositoryRestController
创建了一个 class,我可以在其中捕获 POST
方法。如果我只是 return 实体,则它没有 links。如果我 return 它作为资源,link 就在那里,但是 "Address" 也是一个 link。如果我从控制器中删除 GET
方法,则默认行为如上所述。
更新
我的实体与描述的相同 here A
、B
和 SuperClass
除了我没有 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