从数据库加载数据时发生 StackOverflowError

kbo*_*kbo 0 java json entity-framework spring-data-jpa

我有使用 jpa 框架连接到数据库的 java 应用程序。对象UserInformation包含AdditionData对象,当我userInformationRepository.findByUserId(id)收到错误时。作为回应,我看到带有许多内部对象的 json

userInformation->additionData->userInformation->userInformation->additionData->userInformation->....
Run Code Online (Sandbox Code Playgroud)

例外:

>java.lang.StackOverflowError: null
 Method threw 'java.lang.StackOverflowError' exception. Cannot evaluate com.entity.UserInformation.toString()


java.lang.StackOverflowError: null
    at javax.servlet.ServletResponseWrapper.getBufferSize(ServletResponseWrapper.java:167) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at javax.servlet.ServletResponseWrapper.getBufferSize(ServletResponseWrapper.java:167) ~[tomcat-embed-core-8.5.6.jar:8.5.6]
    at org.springframework.security.web.util.OnCommittedResponseWrapper.checkContentLength(OnCommittedResponseWrapper.java:232) ~[spring-security-web-4.1.3.RELEASE.jar:4.1.3.RELEASE]
    at org.springframework.security.web.util.OnCommittedResponseWrapper.access$200(OnCommittedResponseWrapper.java:33) ~[spring-security-web-4.1.3.RELEASE.jar:4.1.3.RELEASE]
    at org.springframework.security.web.util.OnCommittedResponseWrapper$SaveContextServletOutputStream.write(OnCommittedResponseWrapper.java:637) ~[spring-security-web-4.1.3.RELEASE.jar:4.1.3.RELEASE]
    at com.fasterxml.jackson.core.json.UTF8JsonGenerator._flushBuffer(UTF8JsonGenerator.java:2033) ~[jackson-core-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.core.json.UTF8JsonGenerator.writeRaw(UTF8JsonGenerator.java:632) ~[jackson-core-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.core.json.UTF8JsonGenerator.writeRaw(UTF8JsonGenerator.java:555) ~[jackson-core-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.core.json.UTF8JsonGenerator.writeNumber(UTF8JsonGenerator.java:931) ~[jackson-core-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.std.NumberSerializers$FloatSerializer.serialize(NumberSerializers.java:194) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:704) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:704) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:704) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:704) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:704) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:704) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:704) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690) ~[jackson-databind-2.8.4.jar:2.8.4]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.8.4.jar:2.8.4]
Run Code Online (Sandbox Code Playgroud)

用户信息实体

@Data
@Entity(name = "user_information")
public class UserInformation {
    @Id
    @Column(name = "uuid")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Column(name = "user_id")
    private Long userId;
    @Column(name = "title", length = 64)
    private String title;
    @Column(name = "message", length = 128)
    private String message;
    @OneToOne(mappedBy = "userInformation")
    private AdditionData additionData;
}
Run Code Online (Sandbox Code Playgroud)

添加数据实体

@Setter @Getter
@Entity(name = "addition_data")
public class AdditionData {
    @Id
    @Column(name = "uuid")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @OneToOne(cascade = CascadeType.MERGE)
    @JoinColumn(name = "parent_id")
    private UserInformation userInformation;
}
Run Code Online (Sandbox Code Playgroud)

UserInformation实体的存储库

@Repository
public interface UserInformationRepository extends CrudRepository<UserInformation, Long> {
    List<UserInformation> findByIdIn(List<Long> ids);
    UserInformation findByUserId(Long userId);
}
Run Code Online (Sandbox Code Playgroud)

为什么会出现错误?实体中的关系配置有误吗?

Col*_*inD 5

一般jackson JSON序列化成循环链接的问题。就像你的两个实体之间UserInformationAdditionData那个(有一个具有相同的UserInformation等等)。

添加@JsonIgnore成员之一以停止循环。为了更好地衡量,我会在您的 lombok@Data注释中添加一个 exclude以防止在toString()调用时出现问题。

@JsonIgnore当输出生成为 JSON 时,使用将阻止 spring 的 Jackson JSON 序列化程序通过引用运行。由于该过程是递归的(成员也被序列化为 json),因此防止深入这些引用也将防止StackOverflowException抛出 。