I'm having a bidirectional many to many relationship in my entities. See the example below:
public class Collaboration {
@JsonManagedReference("COLLABORATION_TAG")
private Set<Tag> tags;
}
public class Tag {
@JsonBackReference("COLLABORATION_TAG")
private Set<Collaboration> collaborations;
}
When I try to serialize this to JSON, I'm getting the following exception: `
"java.lang.IllegalArgumentException: Can not handle managed/back reference 'COLLABORATION_TAG': back reference type (java.util.Set) not compatible with managed type (foo.Collaboration).
Actually, I know this makes sense because the javadoc explicitly states that you can't use @JsonBackReference on Collections. My question is, how should I address this problem? What I've done for now is remove the @JsonManagedReference annotation on the parent side, and added the @JsonIgnore on the child side. Could someone tell me what the side effects are of this approach? Are there any other suggestions?
Bidirectional @OneToMany Relationship – Employer/EmployeeWhen you traverse from the “Many” side to the “One” side, you only need to make reference to one object, which is why the Employee class holds a single reference to an Employer class via the private Employer employer instance variable.
You just need to reference the name of the association attribute of the many side as the value of the mappedBy attribute and Hibernate has all the information it needs. That's all you need to do to define a bidirectional many-to-one association.
In a bidirectional, many-to-many relationship, one entity owns the relationship and the other is mapped to the relationship. We use the mappedBy attribute of the @ManyToMany annotation to create this mapping.
The @JsonManagedReference annotation is a forward reference that includes during the serialization process whereas @JsonBackReference annotation is a backreference that omits during the serialization process.
I ended up implementing the following solution.
One end of the relationship is considered to be the parent. It does not need any Jackson related annotation.
public class Collaboration {
private Set<Tag> tags;
}
The other side of the relationship is implemented as follows.
public class Tag {
@JsonSerialize(using = SimpleCollaborationSerializer.class)
private Set<Collaboration> collaborations;
}
I'm using a custom serializer to will make sure that no cyclic references will occur. The serializer could be implemented like this:
public class SimpleCollaborationSerializer extends JsonSerializer<Set<Collaboration>> {
@Override
public void serialize(final Set<Collaboration> collaborations, final JsonGenerator generator,
final SerializerProvider provider) throws IOException, JsonProcessingException {
final Set<SimpleCollaboration> simpleCollaborations = Sets.newHashSet();
for (final Collaboration collaboration : collaborations) {
simpleCollaborations.add(new SimpleCollaboration(collaboration.getId(), collaboration.getName()));
}
generator.writeObject(simpleCollaborations);
}
static class SimpleCollaboration {
private Long id;
private String name;
// constructors, getters/setters
}
}
This serializer will only show a limited set of the properties of the Collaboration entity. Because the "tags" property is omited, no cyclic references will occur.
A good read about this topic can be found here. It explains all possibilities when you're having a similar scenario.
very handy interface implementation is provided in jackson 2 library as
@Entity
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class Collaboration { ....
in maven
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.0.2</version>
</dependency>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With