最小化json,用jpa/hibernate反序列化和持久化复杂的pojo

ef1yzkbh  于 2021-06-30  发布在  Java
关注(0)|答案(2)|浏览(351)

我有一个相当复杂的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 , C ,和 D 还有一些字段和对象(有些包含更多必需的对象和字段),根据数据库模式,这些字段和对象不能为null,我无法更改。我可以反序列化并坚持这一点没有问题,但这样做所需的json非常庞大。我只需要保存反序列化的 A 所以我真的需要 _id 来自的字段 B , C ,和 D .
现在我的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更新数据库中的那些字段。我认为真正棘手的部分是,我的应用程序中的其他类/方法将需要整个对象层次结构来读取数据库。我唯一能用的时间就是 _id 字段在json反序列化过程中。在这种情况下,我只需要更新最上面的对象( A 在我的例子中)和其他一些琐碎的字段。在一个完美的世界里,我可以在我的类中抛出一些注解来解决这个问题,但是我还没有找到任何能够这样做的东西。
这有可能吗?如果是的话,可以用jpa/jackson注解来完成吗?
谢谢!

6jjcrrmo

6jjcrrmo1#

您应该创建新的类,这些类只定义要反序列化的字段。例如,如果您只想反序列化 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]

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

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;
}

让我知道它是否适合你。

dpiehjr4

dpiehjr42#

如果直接将jsonMap到实体是akward,那么我只需通过一个中间对象将传入的json字符串显式地转换为实体(如果愿意,可以称之为dto)。
我也有一种直觉,如果只填充id保存关联的对象引用(@manytoones),hibernate实际上会正确地保存关联(根对象在这里表示a):

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

确保不要层叠b、c等字段的persist操作。

相关问题