My problem is similar to this one https://discourse.hibernate.org/t/hibernate-throws-org-hibernate-id-identifiergenerationexception-attempted-to-assign-id-from-null-one-to-one-property/1777 but I am getting a different exception after applying the answer from this thread.
My entities:
@Entity @Table(name = "location") public class Location { @Id private Long id; @Column(name = "country_code") private String countryCode; private Double longitude; private Double latitude; @OneToOne(fetch = FetchType.LAZY) @MapsId private Distributor distributor; public Distributor getDistributor() { return distributor; } // here I apply the advice from the linked thread above public void setDistributor(Distributor distributor) { this.distributor = distributor; this.id = distributor.getId(); } // other getters/setters }
@Entity @Table public class Distributor { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String site; @OneToOne( mappedBy = "distributor", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY, optional = false ) private Location location; // getters/setters/constructor @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Distributor )) return false; Distributor that = (Distributor ) o; return Objects.equals(id, that.id); } @Override public int hashCode() { return id != null ? id.hashCode() : 0; } }
Controller with corresponding Spring Data Repository:
@PostMapping public ResponseEntity<Distributor> test(@RequestBody Distributor distributor) { distributor.getLocation().setDistributor (distributor); return ResponseEntity.ok(repository.save(distributor)); }
With this payload:
{ "name" : "name1", "location" : { "countryCode" : "US", "longitude" : 34 , "latitude" : 12 } }
I am getting an endless nested response with proper fields(distributor -> location -> distributor -> location ..), which ends with SO Error:
java.lang.StackOverflowError: null at java.base/java.lang.ClassLoader.defineClass1(Native Method) ~[na:na] at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016) ~[na:na] at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174) ~[na:na] at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:800) ~[na:na] at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698) ~[na:na] at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621) ~[na:na] at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579) ~[na:na] at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:741) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:723) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:723) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:723) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:723) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:723) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:723) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:723) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:723) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:723) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:723) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:723) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:723) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:723) ~[jackson-databind-2.11.0.jar:2.11.0] at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:166) ~[jackson-databind-2.11.0.jar:2.11.0] ....
I can’t fathom why does this happen, I followed all available tutorials.
Advertisement
Answer
That’s because there is a cyclic dependency between Location
and Distributor
.
As both have reference to each other, they keep serializing inner reference.
You can avoid that using jackson
annotation @JsonBackReference
and @JsonManagedReference
.
JsonBackReference: skips serialization of annotated property
JsonManagedReference : forward reference and serializes annotated property
In your case, this should work.
//Distributor class @JsonManagedReference private Location location; //Location class @JsonBackReference private Distributor distributor;