[英]Quarkus Panache OneToMany relation is not persisted in database
我目前正在修補一個簡單的 HTTP 資源。 我的 model 由帶有多個“果實”的“樹”組成。 兩者都繼承自 PanacheEntity。
樹:
@Entity
public class Tree extends PanacheEntity {
public String name;
@OneToMany(mappedBy = "tree", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
public List<Fruit> fruits = new ArrayList<>();
}
水果
@Entity
public class Fruit extends PanacheEntity {
public String name;
public String color;
public int cores;
@ManyToOne
@JsonbTransient
public Tree tree;
}
資源:
import io.quarkus.hibernate.orm.rest.data.panache.PanacheEntityResource;
public interface TreeResource extends PanacheEntityResource<Tree, Long> { }
這是我通過 Swagger 發送的 POST 請求
{
"name": "Apple Tree",
"fruits": [
{
"color": "green",
"cores": 3,
"name": "Apple2"
},
{
"color": "red",
"cores": 4,
"name": "Apple"
}
]
}
響應告訴我,為所有對象創建了 ID:
{
"id": 4,
"fruits": [
{
"id": 5,
"color": "green",
"cores": 3,
"name": "Apple2"
},
{
"id": 6,
"color": "red",
"cores": 4,
"name": "Apple"
}
],
"name": "Apple Tree"
}
但是當我在 /trees 下調用 Get all 時,我得到以下響應:
[
{
"id": 1,
"fruits": [],
"name": "Oak"
},
{
"id": 4,
"fruits": [],
"name": "Apple Tree"
}
]
水果總是空的。 檢查 postgres 數據庫顯示 Fruit 中的所有“tree_id”列都是 null。 我很確定這是一個初學者的問題,但是在檢查了多個示例后,我找不到我的代碼有什么問題。
我有同樣的問題並通過將父對象設置為子對象來解決它。 我有 Job 和 JobArgs 項目要堅持。
// ... somewhere in JobArg.java
@JsonbTransient
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "job_id", foreignKey = @ForeignKey(name = "job_id_fk"))
public Job job;
@OneToMany(mappedBy = "job", cascade = CascadeType.ALL, orphanRemoval = true)
public List<JobArg> arguments = new ArrayList<>();
// ... somewhere in Job.java
// I used reactive-pgclient so my method return Uni<T>
public void addArgument(final JobArg jobArg) {
arguments.add(jobArg);
jobArg.job = this;
}
public static Uni<Job> insert(final UUID userId, final JobDto newJob) {
final Job job = new Job();
//... map fields from dto ...
newJob.getArguments().stream().map(arg -> {
final JobArg jobArg = new JobArg();
//... map fields from dto ...
return jobArg;
}).forEach(job::addArgument);
final Uni<Void> jobInsert = job.persist();
final Uni<UserAction> userActionInsert = UserAction.insertAction(type, job.id, userId, null);
return Uni.combine().all().unis(jobInsert, userActionInsert).combinedWith(result -> job);
}
這是來自Vlad Mihalcea 博客的示例代碼:對於雙向映射:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
//Constructors, getters and setters removed for brevity
public void addComment(PostComment comment) {
comments.add(comment);
comment.setPost(this);
}
public void removeComment(PostComment comment) {
comments.remove(comment);
comment.setPost(null);
}
}
@Entity(name = "PostComment")
@Table(name = "post_comment")
public class PostComment {
@Id
@GeneratedValue
private Long id;
private String review;
@ManyToOne(fetch = FetchType.LAZY)
private Post post;
//Constructors, getters and setters removed for brevity
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PostComment )) return false;
return id != null && id.equals(((PostComment) o).getId());
}
@Override
public int hashCode() {
return getClass().hashCode();
}
}
上述映射有幾點需要注意:
@ManyToOne 關聯使用 FetchType.LAZY,否則,我們會退回到 EAGER 獲取,這對性能不利。
父實體 Post 具有兩個實用方法(例如 addComment 和 removeComment),用於同步雙向關聯的雙方。 當您使用雙向關聯時,您應該始終提供這些方法,否則,您將面臨非常微妙的 state 傳播問題。
子實體 PostComment 實現 equals 和 hashCode 方法。 由於我們不能依賴自然標識符進行相等檢查,因此我們需要使用實體標識符來代替 equals 方法。 但是,您需要正確執行此操作,以便在所有實體 state 轉換中保持一致,這也是 hashCode 必須為常量值的原因。 因為我們依賴於 removeComment 的相等性,所以最好在雙向關聯中覆蓋子實體的 equals 和 hashCode
.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.