java/hibernate/spring

k75qkfdt  于 2021-06-30  发布在  Java
关注(0)|答案(2)|浏览(284)

我有以下示例实体:
机构

@Data
@Entity
@NoArgsConstructor
@EntityListeners(InstitutionAuditListener.class)
public class Institution extends Auditable<String> {

    @OneToMany(mappedBy = "institution", cascade = CascadeType.ALL)
    @JsonManagedReference
    private List<RegisteredProgram> registeredPrograms;

    private String name;
}

注册程序

@Data
@NoArgsConstructor
@Entity
@EntityListeners(RegisteredProgramAuditListener.class)
public class RegisteredProgram extends Auditable<String> {

   private String name;

   @ManyToOne
   @JoinColumn(name = "institution_id", nullable = false)
   @JsonBackReference
   private Institution institution;

   @Embedded
   private RegistrationRequirement registrationRequirement;

   @OneToMany(mappedBy = "registeredProgram", cascade = CascadeType.ALL)
   @JsonManagedReference
   private List<Official> officialList;
}

官方的

@Data
@Entity
@EntityListeners(OfficialAuditListener.class)
@NoArgsConstructor
public class Official extends Auditable<String> {

    private String name;
    private String position;

    @ManyToOne
    @JoinColumn(name = "REGISTERED_PROGRAM_ID", nullable = false)
    @JsonBackReference
    private RegisteredProgram registeredProgram;
}

审核日志

@Entity
@Data
@NoArgsConstructor
public class AuditLog extends AuditBase {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;

    private Long entityId;

    @Type(type = "yes_no")
    private Boolean isDeleted = false;

    @Column(columnDefinition = "json")
    @Convert(converter = JpaConverterJson.class)
    private String jsonObject;
}

当我试图将official的object tostring()值的示例保存到auditlog的jsonobject字段中时,遇到以下错误:

java.lang.StackOverflowError: null
    at java.base/java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:173) ~[na:na]
    at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:538) ~[na:na]
    at java.base/java.lang.StringBuilder.append(StringBuilder.java:174) ~[na:na]
    at com.tesda8.region8.program.registration.model.entities.RegisteredProgram.toString(RegisteredProgram.java:26) ~[classes/:na]
    at java.base/java.lang.String.valueOf(String.java:2951) ~[na:na]
    at java.base/java.lang.StringBuilder.append(StringBuilder.java:168) ~[na:na]
    at java.base/java.util.AbstractCollection.toString(AbstractCollection.java:473) ~[na:na]
    at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:622) ~[hibernate-core-5.4.21.Final.jar:5.4.21.Final]
    at java.base/java.lang.String.valueOf(String.java:2951) ~[na:na]
    at java.base/java.lang.StringBuilder.append(StringBuilder.java:168) ~[na:na]
    at com.tesda8.region8.program.registration.model.entities.Institution.toString(Institution.java:23) ~[classes/:na]
    at java.base/java.lang.String.valueOf(String.java:2951) ~[na:na]
    at java.base/java.lang.StringBuilder.append(StringBuilder.java:168) ~[na:na]
    at com.tesda8.region8.program.registration.model.entities.RegisteredProgram.toString(RegisteredProgram.java:26) ~[classes/:na]

我想知道spring/hibernate中是否有任何注解可以阻止此问题的发生,或者是否有其他方法可以在spring中将对象的(json)值保存到对象的列中?我是这么想的 @JsonManagedReference 以及 @JsonBackReference 应该阻止这件事发生。
更新
我已经通过lombok的 @Data 注解
我也试着用 String.valueOf(official)

bybem2ql

bybem2ql1#

问题是你用的是Lombok山的 @Data 注解以生成 equals , hashCode 以及 toString 方法。这将导致一些问题/奇怪之处(更多信息请参阅我写的这篇博文)。
试着用Jackson @JsonBackReference 当然不会解决 toString 方法,这只对使用jackson库创建json有帮助。
发生的是你的 toStringInstitution 会打电话给 toStringRegisteredProgram . 这就叫 toStringInstitution 再说一次,那就是 toStringRegisteredProgram 再说一遍(好吧,你可能明白了。
不要依赖于 equals , hashCode 以及 toString 方法 @Data 作为Lombok山的功能,正如在开始提到的,它将导致问题。你自己写吧 equals , hashCode 以及 toString 或者至少声明哪些需要成为这些方法的一部分(最终结果甚至可能是手工编写这些方法更容易)。
另一方面,不是存储 toString 一开始有点奇怪?

相关链接

https://deinum.biz/2019-02-13-lombok-data-ojects-arent-entities/
https://vladmihalcea.com/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/

ddarikpa

ddarikpa2#

为m干杯。戴纳姆对我问题的见解。https://stackoverflow.com/a/65388643/14806310
我的问题的根本原因确实是 toString() 由Lombok的 @Data 将实体的详细信息保存到一个字段中,这是一个问题。我确实试过推翻 toString() 方法 RegisteredProgram ,解决了stackoverflow错误,但我保存json对象的方法仍然很奇怪。
因此,与其将对象保存到 String json列通过 toString() ,我创建了一个新的hashmap字段 entityAttributes 让我的实体持久化一个json对象。
更新的审核日志实体

@Entity
@Data
@NoArgsConstructor
public class AuditLog extends AuditBase {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;

    private Long entityId;

    @Type(type = "yes_no")
    private Boolean isDeleted = false;

    @Convert(converter = HashMapConverter.class)
    private Map<String, Object> entityAttributes;
}

有关如何保存json对象的更多详细信息,请参见以下链接:https://www.baeldung.com/hibernate-persist-json-object
另外,向前看,我们确实建议您创建自己的 equals , hashCode 以及 toString 方法为您的实体和不依赖Lombok山等。

相关问题