坚持"计算" JPA(加上杰克逊)在Spring Boot应用程序中的字段

时间:2017-09-07 23:37:24

标签: java hibernate jpa spring-boot jackson

我有一个看起来像这样的JPA实体:

public final class Item implements Serializable {
  @Column(name = "col1")
  private String col1;

  @Column(name = "col2")
  @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
  private String col2;

  @Column(name = "col3")
  private String col3;

  Item() { }

  public Item(String col1, String col2) {
    this.col1 = col1;
    this.col2 = col2;
    col3 = col1 + col2 + "some other stuff";
  }

  // getters, equals, hashCode and toString
}

我希望能够坚持col3。我通过POST发送请求,如下所示:

{
  "col1": "abc",
  "col2": "def"
}

......我收到这样的话:

[
    {
        "createdAt": "2017-09-07T19:18:17.04-04:00",
        "updatedAt": "2017-09-07T19:18:17.04-04:00",
        "id": "015e5ea3-0ad0-4703-af04-c0a3d46aa836",
        "col1": "abc",
        "col3": null
    }
]

最终,col3未在数据库中保留。我没有任何制定者。

有没有办法实现这个目标?

更新

接受的解决方案是“不那么干扰”#34;一。 Jarrod Roberson提出的建议也完美无瑕。最后,你可以通过在col2上使用setter并在那里设置col3的值来实现同样的目标 - 但我不喜欢这个...虽然是个人偏好。

3 个答案:

答案 0 :(得分:2)

之所以没有持久化,是因为您提供col2col3属性的构造函数从未被真正调用过。当spring从您发送到服务器的JSON进行映射(在jackson的帮助下)时,它使用默认构造函数来创建对象,然后调用setter(有时通过反射)来设置值。因此,存储在{{1}}的数据库中的值始终为null。请参阅Jarrod Roberson的答案如何解决它:)。

答案 1 :(得分:2)

您正在寻找的是@JsonCreator它的使用方式如下:

@JsonCreator()
public Item(@JsonProperty("col1") String col1, @JsonProperty("col2") String col2) {
  this.col1 = col1;
  this.col2 = col2;
  this.col3 = col1 + col2 + "some other stuff";
}

然后删除默认的no-args构造函数,Jackson会使用这个,你想要的将会发生 auto-magically

  

这是一个非常古老的   feature回来了   1.x时代。您还可以注释static 工厂方法   相反,并为您需要的案例制作构造函数private   使用更复杂的逻辑,比如用a构造的东西    Builder Pattern

以下是一个例子:

@JsonCreator()
public static Item construct(@JsonProperty("col1") String col1, @JsonProperty("col2") String col2) {
  return new Item(col1, col2, col1 + col2 + "some other stuff");
}

private Item(final String col1, final String col2, final String col3) {
  this.col1 = col1;
  this.col2 = col2;
  this.col3 = col3;
}

答案 2 :(得分:2)

虽然有一个已接受的答案,但似乎过于复杂,需要删除违反JPA规范的默认构造函数。

第2.1节

  

实体类必须具有无参数构造函数。实体类可以   还有其他建设者。 no-arg构造函数必须是公共的   或受保护。

没有必要让杰克逊参与其中。您可以简单地使用JPA预先持久化侦听器来确保在刷新操作之前设置col3

https://docs.jboss.org/hibernate/orm/4.0/hem/en-US/html/listeners.html

public final class Item implements Serializable {
  @Column(name = "col1")
  private String col1;

  @Column(name = "col2")
  @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
  private String col2;

  @Column(name = "col3")
  private String col3;

  Item() { }

  @PrePersist
  public void updateCol3(){
      col3 = col1 + col2;
  }
}