我有一个概念性的问题,我希望有人可能有答案。
我有一个RESTful服务,它为单一类型的实体提供类似CRUD的操作。实体(我们称之为订单)使用Jackson表示为JSON。 Jackson注释直接附加到实体类,没有明确的数据传输层。实体类包含许多属性,一对一和一对多关系。
技术上,它基于Wildfly 10,JAX-RS 2.0和JPA 2.1(使用Hibernate 5)。
现在支持的操作是:
orders/123
使用EntityManager.find
orders/123
使用EntityManager.persist
或EntityManager.merge
该实体的简化版本如下所示:
@Entity
@Table(name = "order")
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(Include.NON_EMPTY)
public class Order {
@Id
@SequenceGenerator(name = "order_id", sequenceName = "order_id_seq", allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="order_id")
@Column(name = "id")
private long id;
@Version
private long version;
@Column(name = "correlation_id", unique = true)
private long correlationId;
@OneToOne(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JsonManagedReference
private SubOrder subOrder;
}
@Entity
@Table(name = "suborder")
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(Include.NON_EMPTY)
public class SubOrder {
@Id
@SequenceGenerator(name = "suborder_id", sequenceName = "suborder_id_seq", allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="suborder_id")
@Column(name = "id")
private long id;
@Version
private long version;
@OneToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
@JoinColumn(name = "order_id", foreignKey = @ForeignKey(name = "suborder_order_FK1"))
@JsonBackReference
private Order order;
@Column(name = "field1", length = CommonConstants.LENGTH_4, nullable = true)
private String field1;
}
JSON表示如下所示:
{
"id": 6000000197444,
"version": 358,
"correlationId": 4711,
"suborder": {
"id": 1000000005025,
"version": 40,
"field1": "value"
}
}
现在,我想在实体Order
中添加字段 field2 。该服务有多个客户端 - Client1 和 Client2 。
Client1 执行实体更新,并为新字段提供值 newValue :
{
"id": 6000000197444,
"version": 358,
"correlationId": 4711,
"field2": "newValue",
"suborder": {
"id": 1000000005025,
"version": 40,
"field1": "value"
}
}
Client2 对新字段不感兴趣。因此,没有开发新版本的 Client2 。现在,它希望将field1
的值更改为值 anotherNewValue 。因为它不知道新字段field2
,所以它将以下JSON提供给服务:
{
"id": 6000000197444,
"version": 358,
"correlationId": 4711,
"suborder": {
"id": 1000000005025,
"version": 40,
"field1": "newValue"
}
}
或者, Client1 决定再次从field2
中删除该值。因为该值现在为空,并且根据Jackson注释,不包括空值,以下JSON正在被PUT:
{
"id": 6000000197444,
"version": 358,
"correlationId": 4711,
"suborder": {
"id": 1000000005025,
"version": 40,
"field1": "newValue"
}
}
此解决方案提供了一个严重的问题: 使用旧实体代表的客户将意外删除其未知的字段。
所以基本上它会破坏向前兼容性,这对我来说是个大问题!
我有一些可能的解决方案,但每个都有严重的缺点:
我认为这是一个非常常见的问题,所以我希望你们中的一些人已经做过类似的事情了。我有具体的问题: 1.有没有人知道允许在arbirtary对象树上创建和应用补丁的Java库(如解决方案2和3中所要求的那样)? 2.有没有人有更简单的解决方案?
很抱歉文本变得太长了,但我想要包含所有相关细节。非常感谢你的时间!