【问题标题】:Spring RepositoryRestController with excerptProjectionSpring RepositoryRestController 与 excerptProjection
【发布时间】:2017-08-07 12:25:34
【问题描述】:

我已经为我的 Spring Data 实体定义了一个 @Projection,如 here 所述

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

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

我用@RepositoryRestController 创建了一个类,我可以在其中捕获POST 方法。如果我只是返回实体,它就没有链接。如果我将它作为资源返回,链接就在那里,但“地址”也是一个链接。如果我从控制器中删除 GET 方法,默认行为如上所述。

更新

我的实体与here ABSuperClass 描述的相同,但我的 @ManyToOne 中没有定义 fetch 我的控制器如下所示:

@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();
}

【问题讨论】:

    标签: spring spring-data entity spring-data-jpa hateoas


    【解决方案1】:

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

    @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

    【讨论】:

    • 嗯,我的存储库正在扩展 CRUDRepository。我收到一个错误:query specified join fetching, but the owner of the fetched association was not present in the select list...
    • @JamesLinux 将您的模型代码和 repo 添加到您的问题中 - 我更容易更正我的代码。尽管如此,主要的想法是在控制器方法中返回一个投影。
    • 和例子中的一样。我已经定义了一个@ManyToOne(optional = false, cascade = CascadeType.PERSIST)。我的投影也是一样的。
    • 在我之前的一个问题中,我将它们定义为here
    • @JamesLinux in reference Address 有一个 OneToOne 引用。更改您的代码,然后重试..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-27
    • 2018-08-28
    • 2018-06-14
    • 2015-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多