最小化JSON,用JPA/Hibernate来反序列化和持久化复杂的POJO



我有一个相当复杂的POJO,我需要从JSON字符串反序列化并持久保存在MySQL数据库中。下面是一个非常简化的示例类:

@Entity
@Table(name="a")
public class A{
    private Long id;
    private B b;
    private C c;
    private D d;
}
@ManyToOne
@JoinColumn(name="b_id")
public B getB(){
    return this.b;
}
public void setB(B b){ this.b = b; }
@ManyToOne
@JoinColumn(name="c_id")
public C getC(){ 
    return this.c;
}
public void setC(C c){ this.c = c; }
@ManyToOne
@JoinColumn(name="d_id")
public D getD(){ 
    return this.d;
}
public void setD(D d){ this.d = d; }

每个类B, CD也有许多字段和对象(有些甚至有更多需要的对象和字段),根据数据库模式不能为空,这是我无法更改的。我可以反序列化并持久化它,但这样做所需的JSON非常庞大。我只需要持久化反序列化的A,所以我实际上只需要BCD中的_id字段。

现在我的JSON是这样的:
{
  "id":1, 
  "b":{"id":2, ...}, 
  "c":{"id":3, ...}, 
  "d":{"id":4, ...}
}

,我必须填写所有不可空的数据库字段。我要做的是读取一个JSON字符串,如:

{
  "id":1,
  "b_id":2,
  "c_id":3,
  "d_id":4
}

并让Hibernate/JPA更新数据库中的这些字段。我认为真正棘手的部分是,我的应用程序中的其他类/方法将需要整个对象层次结构从数据库读取。我只能在JSON反序列化期间使用_id字段。在这种情况下,我只需要更新最上面的对象(在我的例子中是A)和其他一些琐碎的字段。在理想的情况下,我可以在类上添加一些注释来解决这个问题,但是我还没有找到任何能够做到这一点的东西。

这可能吗?如果是这样,它可以用JPA/Jackson注释完成吗?

谢谢!

如果将JSON直接映射到您的实体是尴尬的,我会简单地通过一个中间对象(如果您愿意,可以称之为DTO)将传入的JSON字符串显式地转换为您的实体。

我也有一种直觉,如果你保存关联的对象引用(@ManyToOnes),只填充id, Hibernate实际上会正确保存关联(根对象在这里代表a):

{
    "id" : 1,
    "b" : {
        "id" : 2
    },
    ...
}

确保不要级联b、c等字段的持久化操作

您应该创建新的类,这些类只定义您想要反序列化的字段。例如,如果你只想反序列化ID,你的类可以像这样:

class JsonEntity {
    private Long id;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    @JsonAnySetter
    public void setUnknownProperties(String name, String value) {
        //do nothing
    }
    @Override
    public String toString() {
        return String.valueOf(id);
    }
}

在这个例子中,注释JsonAnySetter完成了这个任务。现在,您必须创建一些类来模拟您的A类。例如:

class DtoA extends JsonEntity {
    private JsonEntity b;
    private JsonEntity c;
    private JsonEntity d;
    public JsonEntity getB() {
        return b;
    }
    public void setB(JsonEntity b) {
        this.b = b;
    }
    public JsonEntity getC() {
        return c;
    }
    public void setC(JsonEntity c) {
        this.c = c;
    }
    public JsonEntity getD() {
        return d;
    }
    public void setD(JsonEntity d) {
        this.d = d;
    }
    @Override
    public String toString() {
        return "A [id=" + getId() + ", b=" + b + ", c=" + c + ", d=" + d + "]";
    }
}

现在,当我们有新的JSON数据模型,我们可以测试它。例如,我们可以在JSON下面解析:

{
  "id":1, 
  "b":{"id":2, "p1":"v1", "p2":"v2"}, 
  "c":{"id":3, "p3":"v3", "p4":"v4", "p5":"v5"}, 
  "d":{"id":4, "p6":"v6"}
}

反序列化的例子:

ObjectMapper objectMapper = new ObjectMapper();
DtoA a = objectMapper.readValue(json, DtoA.class);
System.out.println(a);

上面的程序打印:

A [id=1, b=2, c=3, d=4]

现在,你必须在DtoA类中实现toA()方法,它看起来像这样:

public A toA() {
    A a = new A(getId());
    a.setB(new B(getB().getId()));
    a.setC(new C(getC().getId()));
    a.setD(new D(getD().getId()));
    return a;
}
让我知道它是否适合你。

最新更新