杰克逊:将对象引用为属性 [英] Jackson: referencing an object as a property

查看:125
本文介绍了杰克逊:将对象引用为属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的java spring应用程序中,我正在使用hibernate和jpa,并且我使用jackson在DB中填充数据.

In my java spring application, I am working with hibernate and jpa, and i use jackson to populate data in DB.

这是User类:

@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文件来存储数据:

In the class Roles i have a property of User and then i made a json file to store the data:

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

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

Unfortunately, when i run the app it complains with:

.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"}

当我删除上述行时,该应用程序运行良好.

and when i remove the above line the app works well.

我认为,它抱怨是因为它不能成为用户实例. 所以,我该如何解决?

I think, it complains because it cannot make an instance of user. So, how can i fix it?

推荐答案

帮个忙,停止使用实体作为DTO!

Do yourself a favor and stop using your Entities as DTOs!

JPA实体具有双向关系,而JSON对象则没有,我还认为Entity的职责与DTO完全不同,尽管将这些职责合并到单个Java类中是可能的,但根据我的经验,非常糟糕的主意.

JPA entities have bidirectional relations, JSON objects don't, I also believe that the responsibilities of an Entity is very different from a DTO, and although joining these responsibilities into a single Java class is possible, in my experience it is a very bad idea.

以下是两个原因

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

开发人员在使用JPA时会遇到很多问题,特别是在合并方面,这是因为在对JSON进行反序列化之后,他们会收到一个分离的实体.但是,此实体通常不具有OneToMany关系(如果确实如此,则是父对象与JSON中的子对象有关系,但是在JPA中,是子对象对父对象的引用构成了该关系).在大多数情况下,您始终需要从数据库中加载实体的现有版本,然后将更改从DTO复制到实体中.

A lot of the problems developers have with JPA, specifically with regards to merging comes from the fact that they receive a detached entity after their json has been deserialized. But this entity typically doesn't have the OneToMany relations (and if it does, it's the parent which has a relation to the child in JSON, but in JPA it is the child's reference to the parent which constitutes the relationship). In most cases you will always need to load the existing version of the entity from the database, and then copy the changes from your DTO into the entity.

自2009年以来,我一直与JPA进行过广泛的合作,并且我知道大多数分离和合并的极端情况,并且使用Entity作为DTO并没有问题,但是当您处理此类问题时,我已经看到了混乱和错误类型将代码转交给对JPA不太熟悉的人. DTO所需的几行内容(特别是因为您已经使用Lombok)如此简单,并且比试图保存一些文件并打破关注点分离的灵活性更大.

I have worked extensively with JPA since 2009, and I know most corner cases of detachment and merging, and have no problem using an Entity as a DTO, but I have seen the confusion and types of errors that occur when you hand such code over to some one who is not intimately familiar with JPA. The few lines you need for a DTO (especially since you already use Lombok), are so simple and allows you much more flexibility, than trying to save a few files and breaking the separation of concerns.

这篇关于杰克逊:将对象引用为属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆