DTO 序列化期间 Spring Boot 应用程序中出现 StackOverflowError 问题

问题描述 投票:0回答:1

当尝试序列化具有自引用关系的 DTO 类 (NodeAttributesDTO) 时,我在 Spring Boot 应用程序中遇到 StackOverflowError。错误发生在执行DTO类中的toString方法时。

NodeAttributes.java:


// Relevant parts of NodeAttributes.java
@OneToMany(mappedBy = "parent")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@JsonIgnoreProperties(value = { "children", "parent", "node" }, allowSetters = true)
private Set<NodeAttributes> children ;

@ManyToOne
@JsonIgnoreProperties(value = { "children", "parent", "node" }, allowSetters = true)
private NodeAttributes parent;

// Other fields, getters, setters, etc.

NodeAttributesDTO.java:

// Relevant parts of NodeAttributesDTO.java
private Set<NodeAttributesDTO> children;
private NodeAttributesDTO parent;

// Getters, setters, and other methods...

@Override
public String toString() {
    return "NodeAttributesDTO{" +
        "id=" + getId() +
        // Other fields...
        ", parent=" + getParent() +
        ", children=" + getChildren() +
        ", node=" + getNode() +
        "}";
}

PostMapping 请求正文:

{
  // Some other fields...
  "children": [
    {
      "key": "attribute412w",
      "value": "value3",
      "valueType": "Integer",
      "type": "RESPONSE",
      "required": false,
      "enabled": true,
      "node": {
        "id": 26030
      }
    }
  ],
  // Other fields...
}

错误:


{
    "type": "https://www.jhipster.tech/problem/problem-with-message",
    "title": "Internal Server Error",
    "status": 500,
    "detail": "Handler dispatch failed; nested exception is java.lang.StackOverflowError",
    "path": "/api/node-attributes",
    "message": "error.http.500"
}

问题:

  1. 如何修改 NodeAttributesDTO 类中的 toString 方法以避免序列化期间出现 StackOverflowError?
  2. 在处理 DTO 中的自引用关系时,我应该考虑使用特定的 Jackson 注释或配置吗?

环境: 春季启动版本:2.7.2 Java版本:17 数据库:Postgresql

我已经尝试过:

  • 不同的 Jackson 注释(@JsonManagedReference、@JsonBackReference)
java spring-boot stack-overflow self-join self-referencing-table
1个回答
0
投票

我相信您的困惑是 toString 不控制 Spring Boot 中的编组。

如果您要通过 System.err.println() 记录该对象以表示标准错误,它将使用 toString。

似乎您的 toString 本质上是试图成为数据的递归转储,但并不正确。我认为这只是基本的 Java/CS。

在toString中,您可以只打印当前节点的数据,然后对所有子节点调用toString(delagate)。应该可以做到这一点。我认为一般情况下您不需要反向引用(对于 toString),因为您将从“树”的顶部开始。

编组器检查对象并使用反射来组成序列化表示。正如您所注意到的,它将遵守某些注释。比如@JsonIgnore。

看到这个:如何忽略 json 响应中的字段?

这里有很多好信息:https://www.baeldung.com/jackson

它还可能有助于在代码生成工具(如 jhipster)之外创建一个简单的 Web 服务,以了解幕后发生的情况,从而更好地控制生成。

© www.soinside.com 2019 - 2024. All rights reserved.