Search code examples
javaoracle-databasespring-bootjpaspring-data-jpa

Jpa bidirectional many to one mapping going into infinite loop even with @JsonManagedReference


I am using JPA with oracle databases and need to implement a bidirectional one to many and many to one mapping for the tables scheme_code_template and multilingual_template_v2 respectively.

MultilingualTemplateV2 Entity

@Entity
@Table(name = "multilingual_template_v2")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class MultilingualTemplateV2 {

    
    @NotNull()
    String language;
    
    
    @NotNull()
    @Nationalized
    String template;
    
    @Id
    @Column(name="template_code")
    @NotNull()
    String templateCode;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "associated_schemecode")
    @JsonManagedReference
    SchemeCode schemeCode;
}

SchemeCode Entity

@Entity
@Table(name = "scheme_code_templates")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class SchemeCode {

    
    @Column(name="associated_pushcode")
    Integer associatedPushcode;
    
    @NotNull
    String description;
        
    @Id
    @NotNull()
    String schemeCode;
    
    
    @OneToMany(mappedBy = "schemeCode", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JsonBackReference
    List<MultilingualTemplateV2> multilingualTemplates;
}

database:

below is scheme_code_templates. It has the scheme_code as primary key which is used as the foreign key in multilingual_template_v2 table

Name                Null?    Type          
------------------- -------- ------------- 
ASSOCIATED_PUSHCODE          NUMBER        
SCHEME_CODE         NOT NULL VARCHAR2(6)   
DESCRIPTION         NOT NULL VARCHAR2(200)

below is multilingual_template_v2 . It has the ASSOCIATED_SCHEMECODE as foreign key referencing the scheme_code in scheme_code_templates. Template_code is the primary key.

Name                  Null?    Type         
--------------------- -------- ------------ 
ASSOCIATED_SCHEMECODE          VARCHAR2(6)  
TEMPLATE_CODE         NOT NULL VARCHAR2(9)  
LANGUAGE              NOT NULL VARCHAR2(30) 
TEMPLATE              NOT NULL NCLOB 

Used the below query to set foreign key in multilingual_template_v2

ALTER TABLE multilingual_template_v2
ADD CONSTRAINT fk_scheme_code_templates
  FOREIGN KEY (associated_schemecode)
  REFERENCES scheme_code_templates(scheme_code);

I have created a JpaRepository for scheme_code called SchemeCodeRepository through which I am using findAll(). Currently I am getting below error when getMultilingualTemplates() is called.

for (SchemeCode schemeCode : schemeRepo.findAll()) {
            System.out.println(schemeCode.getMultilingualTemplates());
        }

Error

at org.hibernate.collection.spi.PersistentBag.toString(PersistentBag.java:585) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.SchemeCode.toString(SchemeCode.java:34) ~[classes/:?]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.MultilingualTemplateV2.toString(MultilingualTemplateV2.java:30) ~[classes/:?]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at java.util.AbstractCollection.toString(AbstractCollection.java:457) ~[?:?]
    at org.hibernate.collection.spi.PersistentBag.toString(PersistentBag.java:585) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.SchemeCode.toString(SchemeCode.java:34) ~[classes/:?]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.MultilingualTemplateV2.toString(MultilingualTemplateV2.java:30) ~[classes/:?]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at java.util.AbstractCollection.toString(AbstractCollection.java:457) ~[?:?]
    at org.hibernate.collection.spi.PersistentBag.toString(PersistentBag.java:585) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.SchemeCode.toString(SchemeCode.java:34) ~[classes/:?]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.MultilingualTemplateV2.toString(MultilingualTemplateV2.java:30) ~[classes/:?]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at java.util.AbstractCollection.toString(AbstractCollection.java:457) ~[?:?]
    at org.hibernate.collection.spi.PersistentBag.toString(PersistentBag.java:585) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.SchemeCode.toString(SchemeCode.java:34) ~[classes/:?]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.MultilingualTemplateV2.toString(MultilingualTemplateV2.java:30) ~[classes/:?]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at java.util.AbstractCollection.toString(AbstractCollection.java:457) ~[?:?]
    at org.hibernate.collection.spi.PersistentBag.toString(PersistentBag.java:585) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.SchemeCode.toString(SchemeCode.java:34) ~[classes/:?]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.MultilingualTemplateV2.toString(MultilingualTemplateV2.java:30) ~[classes/:?]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at java.util.AbstractCollection.toString(AbstractCollection.java:457) ~[?:?]
    at org.hibernate.collection.spi.PersistentBag.toString(PersistentBag.java:585) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.SchemeCode.toString(SchemeCode.java:34) ~[classes/:?]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.MultilingualTemplateV2.toString(MultilingualTemplateV2.java:30) ~[classes/:?]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at java.util.AbstractCollection.toString(AbstractCollection.java:457) ~[?:?]
    at org.hibernate.collection.spi.PersistentBag.toString(PersistentBag.java:585) ~[hibernate-core-6.1.7.Final.jar:6.1.7.Final]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]
    at java.lang.StringBuilder.append(StringBuilder.java:173) ~[?:?]
    at com.dcb.smsbatch.dataLayer.entities.SchemeCode.toString(SchemeCode.java:34) ~[classes/:?]
    at java.lang.String.valueOf(String.java:4218) ~[?:?]

Any help or suggestion is greatly appreciated.


Solution

  • The recursion is caused by @ToString lombok annotation and the two way reference. The generated toString methods are unaware of any @JsonManagedReference (which is for jackson serialization)

    There is no such equivalent as @JsonBackReference, but you could annotate the field with @ToString.Exclude

    @OneToMany(mappedBy = "schemeCode", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JsonBackReference
    @ToString.Exclude
    List<MultilingualTemplateV2> multilingualTemplates;