【问题标题】:Hibernate infinite recursion and bidirectional relationshipHibernate无限递归和双向关系
【发布时间】:2015-07-02 14:57:10
【问题描述】:

我有两个实体。我想要项目和任务之间的双向关系。

  • 一个项目有一个或多个任务
  • 一项任务仅与一个项目相关联

有我的实体:


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

@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

我想要每个ProjectEntity 中的任务列表,以及每个TaskEntity 中关联的项目。

在这里,我使用@JsonManagedReference@JsonBackReference 来停止它生成的无限递归,但是在我的ProjectEntity 中,我没有任务列表(因为@JsonBackReference)...

您能帮我取回ProjectEntity 中的任务列表吗?我听说过@JsonIdentifyInfo,但我没有设法处理。

希望我可以理解:)

【问题讨论】:

  • 这是很棒的迷你指南,其中包含有关您的案例以及如何使用的简单示例 @JsonIdentifyInfo baeldung.com/…
  • 我在问我的问题之前已经看过它,它并没有解决我的问题......:/无论如何谢谢
  • 在这种情况下,为什么不尝试为 Project.tasks 集合创建一个自定义序列化程序,将其关联 ID 的项目中的每个任务写出(而不仅仅是任务的 ID 列表)?你想在哪里停止序列化?
  • 你能详细说明你的想法吗? :)
  • 我把想法写在答案上,也许你可以根据自己的需要进行调整:9

标签: java hibernate jackson


【解决方案1】:

我知道的解决方案实际上是使用“@JsonIdentityInfo”而不是“@JsonBackReference”和“@JsonManagedReference”。 您必须删除“@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;
}

【讨论】:

    【解决方案2】:

    您可以选择为列表 ProjectEntity.tasks 实现自定义序列化程序。但是您必须在某个时候控制/停止序列化周期;这将取决于您的要求。 这是我的意思的一个例子。

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

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

    请注意,它基本上是mentioned mini guide 的示例,但它序列化了项目任务列表元素的信息,而不仅仅是任务的ID。

    【讨论】:

    • 2018-04-13 17:20:57.209 WARN 7340 --- [nio-9090-exec-9] .m.m.a.ExceptionHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Cannot override _serializer: had a ´com.project.serializer.SaleItemSerializer´,
    • trying to set to ´org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$NestedEntitySerializer´; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Cannot override _serializer: had a ´com.project.serializer.SaleItemSerializer´, trying to set to ´org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$NestedEntitySerializer´
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-23
    • 1970-01-01
    相关资源
    最近更新 更多