复合关系将父级引用分配给子级/反序列化

问题描述

我有一个像这样的课程:

@Setter
@Getter
public class Parent {
    private String name;
    private String lastName;
    private String address;

    @Setter(AccessLevel.PRIVATE)
    @JsonBackReference
    private Child child;

    public Parent() {
        this.child = new Child();
        child.setParent(this);
    }
}

还有一个像这样的复合关系中的孩子:

@Setter
@Getter
public class Child {
    private String nameChild;
    private String lastNameChild;

    @JsonManagedReference
    private Parent parent;
}

我想要什么:

导入com.fasterxml.jackson.core.JsonProcessingException;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;

public class Example {
    @Test
    public void test() throws JsonProcessingException {
        Parent parent = new Parent();
        parent.setAddress("Address");
        parent.setLastName("LastName");
        parent.setName("Name");

        parent.getChild().setNameChild("ChildName");
        parent.getChild().setLastNameChild("ChildLastName");

        Parent referencetoParent = parent.getChild().getParent();

        ObjectMapper objMapper = new ObjectMapper();
        String json = objMapper.writeValueAsstring(referencetoParent);

        Parent m = objMapper.readValue(json,Parent.class);
    }
}

我想在referencetoParent中以复合关系从子级获得对父级的引用。

  1. 如何构造对象?
  2. 如何处理子->父字段以进行反序列化?

反序列化的结果注意子元素不存在,这不是预期的行为:

{"name":"Name","lastName":"LastName","address":"Address"}

解决方法

您可以像下面那样覆盖setChildsetParent的生成的Setter方法

// Parent class
public void setChild(Child child) {
  this.child = child;
    if (child.getParent() == null) { // Prevent StackOverflowException
      child.setParent(this);
    }
}
//Child class
public void setParent(Parent parent) {
  this.parent = parent;
  if (parent.getChild() == null) { // Prevent StackOverflowException
    parent.setChild(this);
  }
}

@Test
public void test() {
  Parent parent = new Parent();
  parent.setAddress("Address");
  parent.setLastName("LastName");
  parent.setName("Name");

  Child child = new Child();
  child.setNameChild("ChildName");
  child.setLastNameChild("ChildLastName");

  parent.setChild(child);

  assertNotNull(parent.getChild().getParent());
}

您的通话parent.getChild().setLastNameChild("ChildLastName");的问题在于,此时没有孩子。因此,要么像在Child的构造器中创建一个Parent,要么像我一样传递Child对象。

---编辑

如果我理解您的评论正确,那么您可以将以下内容作为防止手动实例化的替代方法。

@Setter
@Getter
public class Parent implements Serializable {
    private String name;
    private String lastName;
    private String address;

    @Setter(AccessLevel.PRIVATE)
    private Child child;

    public Parent() {
        this.child = new Child();
        child.setParent(this);
    }
}

@Test
    public void test() {
        Parent parent = new Parent();
        parent.setAddress("Address");
        parent.setLastName("LastName");
        parent.setName("Name");

        parent.getChild().setNameChild("ChildName");
        parent.getChild().setLastNameChild("ChildLastName");

        assertNotNull(parent.getChild().getParent());
    }

专用的setChild()方法可防止覆盖子级。如果您想同时手动设置子项,则不必同时使用这两种方法。

公共setParent()可能很关键,因为一个人可以覆盖相关的父项。