双向多对多关系中的循环引用

问题描述:

我的实体中有多对多的双向关系。请参阅以下示例:

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;

}

当我尝试将其序列化为JSON时,我是得到以下异常:`

When I try to serialize this to JSON, I'm getting the following exception: `


java.lang.IllegalArgumentException:无法处理托管/返回
引用'COLLABORATION_TAG':返回引用类型(java.util.Set)而不是
与托管类型(foo.Collaboration)兼容。

"java.lang.IllegalArgumentException: Can not handle managed/back reference 'COLLABORATION_TAG': back reference type (java.util.Set) not compatible with managed type (foo.Collaboration).

实际上,我知道这是有道理的,因为javadoc明确声明你不能在集合上使用@JsonBackReference。我的问题是,我该如何解决这个问题?我现在所做的是删除父节点上的@JsonManagedReference注释,并在儿童方面添加了@JsonIgnore。有人能告诉我这种方法的副作用是什么?还有其他建议吗?

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?

我最终实现了以下解决方案。

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

    }

}

此序列化程序仅显示Collaboration实体的一组有限属性。因为省略了tags属性,所以不会发生循环引用。

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.