简体   繁体   English

Hibernate无限递归和双向关系

[英]Hibernate infinite recursion and bidirectional relationship

I have two entities. 我有两个实体。 I want a bidirectional relationship between projects and tasks. 我想要项目和任务之间的双向关系。

  • A project has one or more tasks 一个项目有一个或多个任务
  • A task is associated to only one project 一项任务仅与一个项目关联

There are my entities: 有我的实体:


ProjectEntity.java ProjectEntity.java

@Entity
@Table(name = "projects")
public class ProjectEntity {
    @Id
    @GeneratedValue
    @Column(name = "pr_id")
    private long id;

    @Column(name = "pr_name", nullable = false)
    private String name;

    @OneToMany(cascade=CascadeType.ALL, mappedBy="project",orphanRemoval=true)
    @JsonBackReference
    private Set<TaskEntity> tasks = new HashSet<TaskEntity>();

   // Getters, constructors, setters

TaskEntity.java TaskEntity.java

@Entity
@Table(name = "tasks")
public class TaskEntity {
    @Id
    @GeneratedValue
    @Column(name = "ta_id")
    private long id;

    @Column(name = "ta_name")
    private String name;

    @ManyToOne
    @JoinColumn(name="pr_id")
    @JsonManagedReference
    private ProjectEntity project;

    // Getters, constructors, setters

I would like to have the list of tasks in each ProjectEntity , and in each TaskEntity the project associated. 我想在每个任务列表ProjectEntity ,并在每个TaskEntity项目有关。

Here, I'm using @JsonManagedReference and @JsonBackReference to stop the infinite recursion it generated, but in my ProjectEntity , I don't have the tasks list (because of the @JsonBackReference ) ... 在这里,我正在使用@JsonManagedReference@JsonBackReference停止它生成的无限递归,但是在我的ProjectEntity ,我没有任务列表(由于@JsonBackReference )...

Could you help me to get back tasks list in ProjectEntity ? 您能帮我找回ProjectEntity任务列表吗? I heard about @JsonIdentifyInfo , but I have not managed to do with. 我听说过@JsonIdentifyInfo ,但是我没有做到。

Hope I'm understandable :) 希望我可以理解:)

You could opt for implement a custom serializer for the list ProjectEntity.tasks. 您可以选择为列表ProjectEntity.tasks实现自定义序列化程序。 But you must controll/stop the serialization cycle at some point; 但是您必须在某个时候控制/停止序列化周期; this will depend on your requirements. 这将取决于您的要求。 Here is an example of what I mean. 这是我的意思的一个例子。

@Entity
@Table(name = "projects")
public class ProjectEntity {
    ...
    @OneToMany(cascade=CascadeType.ALL, mappedBy="project", orphanRemoval=true)
    @JsonSerialize(using = CustomListSerializer.class)
    private Set<TaskEntity> tasks = new HashSet<TaskEntity>();
}

And the CustomListSerializer could be something like this, 而且CustomListSerializer可能是这样的,

public class CustomListSerializer extends JsonSerializer<List<TaskEntity>>{

    @Override
    public void serialize(List<TaskEntity> tasks, JsonGenerator generator, SerializerProvider provider)
          throws IOException, JsonProcessingException {

        generator.writeStartArray();

        for (TaskEntity task : tasks) {
            generator.writeStartObject("taskEntity")
                .write("id", task.id)
                .write("name", task.name)
                .write("project", task.project.id) //<- here you stop the cycle 
            .writeEnd();
        }
        generator.writeEnd();
    }
}

Note that it is basically the example of the mentioned mini guide but it serialize information of the elements of project's tasks list instead of the tasks' id only. 请注意,它基本上是上述迷你指南的示例,但是它序列化了项目任务列表元素的信息,而不是仅序列化任务ID。

The solution that I know is really using '@JsonIdentityInfo' in instead of '@JsonBackReference' and '@JsonManagedReference'. 我知道的解决方案实际上是在使用'@JsonIdentityInfo'代替'@JsonBackReference'和'@JsonManagedReference'。 You have to remove the '@JsonBackReference' and '@JsonManagedReference' to use '@JsonIdentityInfo'. 您必须删除“ @JsonBackReference”和“ @JsonManagedReference”才能使用“ @JsonIdentityInfo”。

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property="id")
@Entity
@Table(name = "projects")
public class ProjectEntity {
    @Id
    @GeneratedValue
    @Column(name = "pr_id")
    private long id;

    @Column(name = "pr_name", nullable = false)
    private String name;

    @OneToMany(cascade=CascadeType.ALL, mappedBy="project",orphanRemoval=true)
    private Set<TaskEntity> tasks = new HashSet<TaskEntity>();
}


@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property="id")
@Entity
@Table(name = "tasks")
public class TaskEntity {
    @Id
    @GeneratedValue
    @Column(name = "ta_id")
    private long id;

    @Column(name = "ta_name")
    private String name;

    @ManyToOne
    @JoinColumn(name="pr_id")
    private ProjectEntity project;
}

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

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