我有一个相当复杂的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
也有许多字段和对象(有些甚至有更多需要的对象和字段),根据数据库模式不能为空,这是我无法更改的。我可以反序列化并持久化它,但这样做所需的JSON非常庞大。我只需要持久化反序列化的A
,所以我实际上只需要B
、C
和D
中的_id
字段。
{
"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;
}