java - Spring 数据休息: Return One-To-Many-To-One as Many-To-Many relation

标签 java spring spring-boot spring-data-rest

我想使用 Spring Boot 和 Spring Data REST 构建一个简单的 HATEOAS API。

因此,我创建了2个不同的实体A和B。两者之间存在多对多关系。由于该关系还需要 2 个属性,因此我添加了一个具有这些属性的新关系 R。

对于API,只有A和B应该是可见的,R只是内部的并且没有存储库。我想用指向 B 集合的链接来表示 A。

应该可以创建 A、创建 B、将 A 链接到 B 或将 B 链接到 A,而无需提供和返回 R 的内部属性。

我猜这是一个设计问题?

可能的解决方案:

我尝试创建一个自定义方法 findByR_Bid() 但我无法向该方法提供自己的 id,因此“/a/b”是不可能的,它始终是“/a/search/...”。

接下来,我使用 ResponseEntities.linkToCollection(B.class) 添加了一个自定义链接,但这将表示指向“/b​​”的链接,而不引用 A 自己的 id。

接下来,我在 A 中实现了一种从 R 返回列表的方法。但是该列表作为属性包含在内部,而不是创建链接。

一点代码:

@Entity
public class A {
  @Id
  private Long id;

  @OneToMany(mappedBy = "a")
  private List<R> r;

  // getters
}

@Entity
public class B {
  @Id
  private Long id;

  @OneToMany(mappedBy = "b")
  private List<R> r;

  // getters
}

@Entity
public class R {
  @Id
  private Long id;

  @ManyToOne(optional = false)
  private A a;

  @ManyToOne(optional = false)
  private B b;

  // internal properties

  @JsonIgnore
  private String foo;

  @JsonIgnore
  private String bar;

  // getters
}

对于 JSON 响应,我想要这样的内容:

获取/a/1

"_links" : {
    "self": {
        "href": "http://localhost:8080/a/1"
    },
    "a": {
        "href": "http://localhost:8080/a/1"
    },
    "bs": {
        "href": "http://localhost:8080/a/1/b{?page,size,sort}",
        "templated": true
    }
}

最佳答案

这很棘手,但并非不可能!

您可以使用同一个表以多对多关系将 B 添加到 A(反之亦然):

@Entity
public class A {
  @Id
  private Long id;

  @OneToMany(mappedBy = "a")
  private List<R> r;

  @ManyToMany
  @JoinTable(name = "table_r", inverseJoinColumns = { @JoinColumn(name = "b_id") })
  private list<B> b;

  // getters
}

通过这种方式,您可以强制 hibernate 对支持 R 实体的一对多关系使用相同的表。 Spring Data Rest 还将这种多对多关系映射到端点,因此 /a/1/bs 将起作用。

但是,访问关系的额外属性仍然很棘手。 (您需要使用/search 端点。)

如果您为 R (从 A+B)创建复合键而不是标准 id,则还有另一种解决方案。 (实际上已经存在,因为多对多关系的支持表具有基于a_id + b_id的复合键) 如果您为复合键创建转换器,那么您可以访问关系属性,例如: /R/23-34(a-23和b-34之间的关系)

虽然不太好,但是可以用。

关于java - Spring 数据休息: Return One-To-Many-To-One as Many-To-Many relation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57143693/

相关文章:

java - 如何从java中的属性值中删除反斜杠

java - Spring Boot + Spring Security Restful 登录

java - 在某些条件下在同步和异步模式之间切换

java - 文件未完全写入

Java 模式 REGEX 不匹配的地方

Spring Boot csrf使用

spring - 添加 expire 到 Spring Security remember me cookie

php - 在 Symfony 中使用注解注入(inject)依赖

java - 为什么 Gradle 'build' 任务不是最新的,即使源代码没有变化?

docker - 部署到 Docker 时外部化 Spring Boot 属性