休眠用户和朋友JsonReference [英] Hibernate User and Friends JsonReference

查看:108
本文介绍了休眠用户和朋友JsonReference的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两张表:用户和用户友人用于显示与添加字段的关系。

  CREATE TABLE public.users 

uuid VARCHAR(36)PRIMARY KEY NOT NULL,
username VARCHAR(45)UNIQUE NOT NULL,
first_name VARCHAR(255)NOT NULL,
last_name VARCHAR(255),
middle_name VARCHAR(255)
);



CREATE TABLE public.user_friends

uuid VARCHAR(36)PRIMARY KEY,
user_uuid VARCHAR(36)REFERENCES public。用户(uuid)NOT NULL,
friend_uuid VARCHAR(36)REFERENCES public.users(uuid)NOT NULL,
friendAddDATE TIMESTAMP NOT NULL,
friendTypeId INT NOT NULL,
CONSTRAINT friend_unique UNIQUE(user_uuid,friend_uuid)
);

具有hibernate注释的Java实体:

<$ p
$ b @Table(name =users)
public class User实现Serializable {

@Id
@GeneratedValue (generator =system-uuid,strategy = GenerationType.IDENTITY)
@GenericGenerator(name =system-uuid,strategy =uuid2)
@Column(name =uuid,unique = true)
保护字符串uuid;

@Column(name =username)
保护字符串用户名;

@JsonManagedReference
@OneToMany(fetch = FetchType.LAZY,mappedBy =user,cascade = CascadeType.ALL,orphanRemoval = true)
private设置< UserFriend> userFriends = new HashSet<>();

@JsonManagedReference
@OneToMany(fetch = FetchType.LAZY,mappedBy =friendUser,cascade = CascadeType.ALL,orphanRemoval = true)
private Set< UserFriend> userFriendOf = new HashSet<>();


$ b @Entity
@Table(name =user_friends)
@AssociationOverrides({
@AssociationOverride(name = user,
joinColumns = @JoinColumn(name =user_uuid)),
@AssociationOverride(name =friendUser,
joinColumns = @JoinColumn(name =friend_uuid))} )
public class UserFriend实现Serializable {
@Id
@GeneratedValue(generator =system-uuid)
@GenericGenerator(name =system-uuid,strategy = uuid2)
@Column(name =uuid,unique = true)
保护字符串uuid;

@JsonBackReference
@ManyToOne(可选= false)
@JoinColumn(name =user_uuid)
私人用户用户;

@JsonBackReference
@ManyToOne(可选= false)
@JoinColumn(name =user_uuid)
私人用户friendUser;

@Column(name =friendadddate)
保护日期friendAddDate;

@Column(name =friendtypeid)
protected int friendTypeId;



$ b我想解决递归问题,将@JsonManagedReference添加到用户类的userFriends和userFriendOf的集合,以及@JsonBackReference用于UserFriend类的用户和friendUser实体,现在在JSP上的JSON中我没有字段,也没有friendUser和用户。



但是在这种情况下 - 如果没有在JSON类中设置friendsOf用户,我可以使用UserFriend类的用户friendUser。

  @Entity 
@Table(name =users)
public class User实现Serializable {

@Id
@GeneratedValue(generator =system-uuid,strategy =
@GenericGenerator(name =system-uuid,strategy =uuid2)
@Column(name =uuid,unique = true)
protected String uuid;

@Column(name =username)
保护字符串用户名;

@JsonManagedReference
@OneToMany(fetch = FetchType.LAZY,mappedBy =user,cascade = CascadeType.ALL,orphanRemoval = true)
private设置< UserFriend> userFriends = new HashSet<>();


$ b @Entity
@Table(name =user_friends)
@AssociationOverrides({
@AssociationOverride(name = user,
joinColumns = @JoinColumn(name =user_uuid)),
@AssociationOverride(name =friendUser,
joinColumns = @JoinColumn(name =friend_uuid))} )
public class UserFriend实现Serializable {
@Id
@GeneratedValue(generator =system-uuid)
@GenericGenerator(name =system-uuid,strategy = uuid2)
@Column(name =uuid,unique = true)
保护字符串uuid;

@JsonBackReference
@ManyToOne(可选= false)
@JoinColumn(name =user_uuid)
私人用户用户;

@ManyToOne(可选= false)
@JoinColumn(name =user_uuid)
private User friendUser;

@Column(name =friendadddate)
保护日期friendAddDate;

@Column(name =friendtypeid)
protected int friendTypeId;





$ b

所以我的问题是我必须做些什么来获得friendUser和user设置用户类?



更新进度:
我在Google上搜索关于我的问题和连续两天的第一(第二)链接的信息 - this问题... ;-)
我仍​​然无法用jsonreference模式解决我的问题。我开始考虑改变数据库的架构。

解决方案

我做到了。再次。 StackOverFlow给了我更多的动力而不是问题:D

因此,经过3个漫长的思考我的问题的每一个小时后,我几乎将反序列化拒绝为json,并且决定不要用户json在这种情况下,但比我认为类的jsonidentity,这是我的解决方案。

使用JsonIdentityInfo,每当Jackson将您的对象序列化时,它会为其添加一个id(在我的情况下它是uuid),以便它不会再次扫描它总是有的。



更新ASNWER(我删除了答案的缩写答案的前一个版本):
不幸的是,解决方案在我发现的不同情况下,它仅适用于第一版json身份。所以第一次扫描完全像魅力工作,但第二次扫描我得到了jsonidentity的ID而不是对象。这给了我理解,我需要我自己的序列化逻辑,我可以控制递归深度。我写了它。我只能显示自定义json序列化程序的框架,因为序列化的逻辑很简单,并且依赖于类结构。

  public class JsonUserSerializer extends JsonSerializer< ;使用者> {
@Override
public void serialize(User o,JsonGenerator jsonGen,SerializerProvider serializerProvider)
throws IOException,JsonProcessingException {
// ... json生成逻辑
Field [] userClassFields = o.getClass()。getDeclaredFields();
// ... json生成的逻辑
}

@Override
public Class< User> handledType(){
return User.class;


$ / code $ / pre

我在工作时必须解决的主要问题代码是字段的命名。因为json结构是:name:value - 在我的例子中,它是fieldName。但硬编码不是我的方式。比我发现解决方案获得所有类的字段它是 o.getClass()。getDeclaredFields()并且比寻找需要按索引字段。我认为这不是最好的解决方案,但我没有找到其他的一个小时(如果你知道其他方式 - 写评论 - 我会赞扬作者)。



忘记显示如何使用为特定类指定的自定义JsonSerialiser:

  @Entity 
@Table (name =users)
@JsonSerialize(using = JsonUserSerializer.class)
public class User实现Serializable {
//很多字段和getter,setter
}


I have got two tables: Users and User_Friend for showing relations with addition fields.

CREATE TABLE public.users
(
  uuid              VARCHAR(36) PRIMARY KEY                     NOT NULL,
  username          VARCHAR(45) UNIQUE                          NOT NULL,
  first_name        VARCHAR(255)                                NOT NULL,
  last_name         VARCHAR(255),
  middle_name       VARCHAR(255)
);



CREATE TABLE public.user_friends
(
  uuid          VARCHAR(36) PRIMARY KEY,
  user_uuid     VARCHAR(36) REFERENCES public.users (uuid) NOT NULL,
  friend_uuid   VARCHAR(36) REFERENCES public.users (uuid) NOT NULL,
  friendAddDate TIMESTAMP                                  NOT NULL,
  friendTypeId  INT                                        NOT NULL,
  CONSTRAINT friend_unique UNIQUE (user_uuid, friend_uuid)
);

Java entities with hibernate annotations:

@Entity
@Table(name = "users")
public class User implements Serializable {

    @Id
    @GeneratedValue(generator = "system-uuid", strategy = GenerationType.IDENTITY)
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    @Column(name = "uuid", unique = true)
    protected String uuid;

    @Column(name = "username")
    protected String username;

    @JsonManagedReference
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<UserFriend> userFriends = new HashSet<>();

@JsonManagedReference
@OneToMany(fetch = FetchType.LAZY, mappedBy = "friendUser", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<UserFriend> userFriendOf = new HashSet<>();

}

@Entity
@Table(name = "user_friends")
@AssociationOverrides({
        @AssociationOverride(name = "user",
                joinColumns = @JoinColumn(name = "user_uuid")),
        @AssociationOverride(name = "friendUser",
                joinColumns = @JoinColumn(name = "friend_uuid")) })
public class UserFriend implements Serializable {
    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    @Column(name = "uuid", unique = true)
    protected String uuid;

    @JsonBackReference
    @ManyToOne(optional = false)
    @JoinColumn(name="user_uuid")
    private User user;

    @JsonBackReference
    @ManyToOne(optional = false)
    @JoinColumn(name="user_uuid")
    private User friendUser;

    @Column(name = "friendadddate")
    protected Date friendAddDate;

    @Column(name = "friendtypeid")
    protected int friendTypeId;
}

I'm trying to solve problem with recursion while deserialisation into JSON i've add @JsonManagedReference to Set of userFriends and userFriendOf of User class and @JsonBackReference to user and friendUser entities of UserFriend class and now in JSON on JSP i have not fields nor friendUser nor user.

But in this case - without Set friendsOf in class User in JSON i can user friendUser of UserFriend class.

@Entity
@Table(name = "users")
public class User implements Serializable {

    @Id
    @GeneratedValue(generator = "system-uuid", strategy = GenerationType.IDENTITY)
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    @Column(name = "uuid", unique = true)
    protected String uuid;

    @Column(name = "username")
    protected String username;

    @JsonManagedReference
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<UserFriend> userFriends = new HashSet<>();

}

@Entity
@Table(name = "user_friends")
@AssociationOverrides({
        @AssociationOverride(name = "user",
                joinColumns = @JoinColumn(name = "user_uuid")),
        @AssociationOverride(name = "friendUser",
                joinColumns = @JoinColumn(name = "friend_uuid")) })
public class UserFriend implements Serializable {
    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid2")
    @Column(name = "uuid", unique = true)
    protected String uuid;

    @JsonBackReference
    @ManyToOne(optional = false)
    @JoinColumn(name="user_uuid")
    private User user;

    @ManyToOne(optional = false)
    @JoinColumn(name="user_uuid")
    private User friendUser;

    @Column(name = "friendadddate")
    protected Date friendAddDate;

    @Column(name = "friendtypeid")
    protected int friendTypeId;
}

So my question is what i have to do to get friendUser and user in all Sets of User class?

Update progress: I'm googling information about my question and two days in a row first(second) link in google - this question... ;-) I still can not solve my problem with jsonreference modes. I start think about changing architecture of database.

解决方案

I did it. Again. StackOverFlow gives me more motivation than problem :D

So, after 3 long day of thinking every hour about my problem, i almost decline deserialization to json and take a decision do not user json in this case, but than i think about jsonidentity of class and this is my solution.

Using JsonIdentityInfo, every time Jackson serialises your object, it will add an id (in my case it is uuid) to it, so that it won't scan it again always.

UPDATE ASNWER (i removed code previous version of answer for shortener of answer): Unfortunately, when i test my solution in different cases i've found, that it is working for only first version of json identity. So first "scan" completely work like a charm, but instead second scan i got an ID of jsonidentity instead of object. This is gives me understanding, that i need my own serialization logic where i can controler depth of recursion. And i wrote it. I can show only skeleton of custom json serializator because logic of serialization is easy and depends on class structure.

public class JsonUserSerializer extends JsonSerializer<User> {
        @Override
        public void serialize(User o, JsonGenerator jsonGen, SerializerProvider serializerProvider)
                throws IOException, JsonProcessingException {
            // ... logic of json generation
            Field[] userClassFields = o.getClass().getDeclaredFields();
            // ... logic of json generation
        }

        @Override
        public Class<User> handledType() {
            return User.class;
        }
    }

The main problem which i have to solved while working on code it is naming of fields. Because json structure it is: "name":"value" - and in my case name - it is fieldName. But hardcode it is not my way. Than i've found solution to get ALL fields of class it is o.getClass().getDeclaredFields()and than looking needs field by index. I think it is not the best solution, but i did not find out other for a one hour (if you know other way - write a comment - i will commend author for it).

Forget to show how to use custom JsonSerialiser which specified for specific class:

@Entity
@Table(name = "users")
@JsonSerialize(using = JsonUserSerializer.class)
public class User implements Serializable {
    // a lot of fields and getter, and setters
}

这篇关于休眠用户和朋友JsonReference的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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