我想使用 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/