Jackson:将对象引用为属性

2024-05-15

在我的 java spring 应用程序中,我正在使用 hibernate 和 jpa,并使用 jackson 来填充数据库中的数据。

这是用户类:

@Data
@Entity
public class User{

    @Id
    @GeneratedValue
    Long id;

    String username;
    String password;
    boolean activated;

    public User(){}
}

第二类是:

@Entity
@Data
public class Roles {

    @Id
    @GeneratedValue
    Long id;

    @OneToOne
    User user;

    String role;

    public Roles(){}


}

在角色类中,我有一个用户属性然后我制作了一个json文件来存储数据:

[ {"_class" : "com.example.domains.User", "id": 1, "username": "Admin", "password": "123Admin123","activated":true}
,
  {"_class" : "com.example.domains.Roles", "id": 1,"user":1, "role": "Admin"}]

不幸的是,当我运行该应用程序时,它抱怨:

.RuntimeException: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.example.domains.User: no int/Int-argument constructor/factory method to deserialize from Number value (1)
 at [Source: N/A; line: -1, column: -1] (through reference chain: com.example.domains.Roles["user"])

问题来自于

{"_class" : "com.example.domains.Roles", "id": 1,"user":1, "role": "Admin"}

当我删除上面的行时,应用程序运行良好。

我认为,它抱怨是因为它无法创建用户实例。 所以,我该如何修复它?


帮自己一个忙,停止使用您的实体作为 DTO!

JPA 实体具有双向关系,而 JSON 对象则没有,我还相信实体的职责与 DTO 有很大不同,尽管将这些职责加入到单个 Java 类中是可能的,但根据我的经验,这是一个非常糟糕的主意。

有几个原因

  • 您几乎总是需要 DTO 层具有更大的灵活性,因为它通常与 UI 相关。
  • 您应该避免将数据库中的主键暴露给外部,包括您自己的 UI。我们总是为每个公开暴露的实体生成一个额外的 uniqueId (UUID),主键保留在数据库中并且仅用于连接。
  • 您经常需要同一实体的多个视图。或者多个实体的单一视图。
  • 如果您需要将新实体添加到与现有实体的关系中,则需要在数据库中找到现有实体,因此将新旧对象发布为单个 JSON 结构没有任何优势。您只需要现有的 uniqueId,然后是新的。

开发人员在使用 JPA 时遇到的许多问题,特别是在合并方面,都源于这样一个事实:在 json 反序列化后,他们收到了一个分离的实体。但这个实体通常没有 OneToMany 关系(如果有,则在 JSON 中是父级与子级有关系,但在 JPA 中是子级对父级的引用构成了关系)。在大多数情况下,您始终需要从数据库加载实体的现有版本,然后将更改从 DTO 复制到实体中。

自 2009 年以来,我广泛使用 JPA,我知道分离和合并的大多数极端情况,并且使用实体作为 DTO 没有问题,但我看到了当您将此类代码交给一些对 JPA 不太熟悉的人。 DTO 所需的几行代码(特别是因为您已经使用了 Lombok)非常简单,并且比尝试保存几个文件并破坏关注点分离更灵活,并且可以为您提供更大的灵活性。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Jackson:将对象引用为属性 的相关文章

随机推荐