簡體   English   中英

Quarkus Panache OneToMany 關系未保存在數據庫中

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM