简体   繁体   English

Quarkus Panache OneToMany 关系未保存在数据库中

[英]Quarkus Panache OneToMany relation is not persisted in database

I'm currently tinkering with a simple HTTP resource.我目前正在修补一个简单的 HTTP 资源。 My model consists of "trees" with multiple "fruits".我的 model 由带有多个“果实”的“树”组成。 Both inherit from PanacheEntity.两者都继承自 PanacheEntity。

Tree:树:

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

Fruit水果

    @Entity
    public class Fruit extends PanacheEntity {

    public String name;
    public String color;
    public int cores;

    @ManyToOne
    @JsonbTransient
    public Tree tree;
    }

Resource:资源:

    import io.quarkus.hibernate.orm.rest.data.panache.PanacheEntityResource;

    public interface TreeResource extends PanacheEntityResource<Tree, Long> { }

This is my POST request that I send via Swagger这是我通过 Swagger 发送的 POST 请求

{
  "name": "Apple Tree",
  "fruits": [
    {
      "color": "green",
      "cores": 3,
      "name": "Apple2"
    },
    {
      "color": "red",
      "cores": 4,
      "name": "Apple"
    }
  ]
}

The response tells me, that Ids were created for all objects:响应告诉我,为所有对象创建了 ID:

{
  "id": 4,
  "fruits": [
    {
      "id": 5,
      "color": "green",
      "cores": 3,
      "name": "Apple2"
    },
    {
      "id": 6,
      "color": "red",
      "cores": 4,
      "name": "Apple"
    }
  ],
  "name": "Apple Tree"
}

BUT when I call the Get all under /trees I get the following response:但是当我在 /trees 下调用 Get all 时,我得到以下响应:

[
  {
    "id": 1,
    "fruits": [],
    "name": "Oak"
  },
  {
    "id": 4,
    "fruits": [],
    "name": "Apple Tree"
  }
]

Fruits are always empty.水果总是空的。 Checking the postgres database reveals that all "tree_id" columns in Fruit are null.检查 postgres 数据库显示 Fruit 中的所有“tree_id”列都是 null。 I'm pretty sure this is a beginners problem but after checking multiple samples I just cannot find what is wrong with my code.我很确定这是一个初学者的问题,但是在检查了多个示例后,我找不到我的代码有什么问题。

I had the same problem and solved it by setting parent objects to children.我有同样的问题并通过将父对象设置为子对象来解决它。 I had Job and JobArgs items to persist.我有 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);
    }

This is an example code from Vlad Mihalcea's blog : For bidirectional mappings:这是来自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();
    }
}

There are several things to note on the aforementioned mapping:上述映射有几点需要注意:

The @ManyToOne association uses FetchType.LAZY because, otherwise, we'd fall back to EAGER fetching which is bad for performance. @ManyToOne 关联使用 FetchType.LAZY,否则,我们会退回到 EAGER 获取,这对性能不利。

The parent entity, Post, features two utility methods (eg addComment and removeComment) which are used to synchronize both sides of the bidirectional association.父实体 Post 具有两个实用方法(例如 addComment 和 removeComment),用于同步双向关联的双方。 You should always provide these methods whenever you are working with a bidirectional association as, otherwise, you risk very subtle state propagation issues.当您使用双向关联时,您应该始终提供这些方法,否则,您将面临非常微妙的 state 传播问题。

The child entity, PostComment, implement the equals and hashCode methods.子实体 PostComment 实现 equals 和 hashCode 方法。 Since we cannot rely on a natural identifier for equality checks, we need to use the entity identifier instead for the equals method.由于我们不能依赖自然标识符进行相等检查,因此我们需要使用实体标识符来代替 equals 方法。 However, you need to do it properly so that equality is consistent across all entity state transitions, which is also the reason why the hashCode has to be a constant value.但是,您需要正确执行此操作,以便在所有实体 state 转换中保持一致,这也是 hashCode 必须为常量值的原因。 Because we rely on equality for the removeComment, it's good practice to override equals and hashCode for the child entity in a bidirectional association因为我们依赖于 removeComment 的相等性,所以最好在双向关联中覆盖子实体的 equals 和 hashCode

. .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM