Hibernate和JSON - 是否有一个循环依赖的明确解决方案? [英] Hibernate and JSON - is there a definitive solution to circular dependencies?

查看:107
本文介绍了Hibernate和JSON - 是否有一个循环依赖的明确解决方案?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现在,我在Hibernate实体和JSON中挣扎,尽管关于对象有很多问题,但我仍然无法在存在循环依赖的情况下进行序列化。我尝试了Gson和杰克逊,但我没有得到很多进展。
这是我的对象摘录。
这是父类类。

  @Entity 
public class User extends RecognizedServerEntities implements Java。 io.Serializable
{
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name =id,unique = true,nullable = false)
私人整数ID;

@OneToMany(fetch = FetchType.LAZY,mappedBy =user,orphanRemoval = false)
@Cascade({CascadeType.SAVE_UPDATE})
private Set< Thread> threads = new HashSet< Thread>(0);
//...其他属性,获取者和设置者
}

和这是儿童班

  @Entity 
@Table(name =thread)
public class Thread extends RecognizedServerEntities implements java.io.Serializable
{
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name =id,unique = true, nullable = false)
私人整数ID;
$ b @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name =author,nullable = true)
私人用户用户;
//...其他属性,获取者和设置者
}

I已经写了一个简单的课程来测试gson和jackson的功能;如上所述,它们都引发异常。

  public class MyJsonsTest 
{
private static User u;
public static void main(String [] args)
{
u = new User(mail,password,nickname,new Date());
u.setId(1); //添加编辑1
// testGson();
testJackson();


private static void testJackson()
{
Thread t = new Thread(Test,u,new Date(),new Date()) ;
t.setId(1); //添加编辑1
u.getThreads()。add(t);

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
尝试
{
mapper.writeValue(new File(result.json),u);
}
catch {/ [各种异常捕获,但抛出JsonMappingException]}
}

private static void testGson()
{
Gson gson = new Gson();
System.out.println(u.toString());
System.out.println(gson.toJson(u,User.class));

Thread t = new Thread(Test,u,new Date(),new Date());
u.getThreads()。add(t);

//这会引发异常溢出
System.out.println(gson.toJson(u,User.class));


$ / code>

为了解决这个问题,在杰克逊一方,我尝试过使用这个注释
$ b $ pre $ @ code @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property =id)
< /用户和线程类上的code>

。但是,它不能解决问题。
在gson方面,我阅读了GraphAdapterBuilder类,但我无法正确使用它。我没有找到任何jar,所以我从 here 。但是,在这一行有一个编译时错误

  private final ConstructorConstructor constructorConstructor = new ConstructorConstructor(); 

因为ConstructorConstructor()是未定义的;正确的语法应该是

  ConstructorConstructor(Map< Type> ;, InstanceCreator<> instanceCreators)

那么,这个问题有没有确定的解决方案?显然,我不能使用瞬变变量。



编辑1



我终于找到杰克逊的问题。在测试类中,我忘了初始化id字段(在实际情况下,它由数据库初始化),这是异常的原因。当我终于设定了身份证,所有的作品。这是输出

  {
id:1,
email:mail ,
password:password,
nick:昵称,
registeredDate:1414703168409,
threads:[{
id:1,
thread:null,
user:1,
title:Test,
lastModifiedDate:1414703168410,
createdDate:1414703168410,
messages:[],
threads:[]
}],
messages:[]
}


解决方案




杰克逊



如上所述,我能够使用



<$ p $解决问题 @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property =id,scope = MyEntity.class)`

为建议的每个实体 here
范围属性对于确保名称id在范围内是唯一的是必需的。实际上,如果没有范围属性,就可以看到这里,它会抛出一个异常说:

  com.fasterxml.jackson.databind .JsonMappingException:已经为ID为java.lang.String的POJO)[com.fasterxml.jackson.annotation.ObjectIdGenerator$IdKey@3372bb3f](通过引用链:ParentEntity [children]  - > java.util.ArrayList [0 ]  - > ChildEntity [id])
... stacktrace ...
引起:java.lang.IllegalStateException:已经有了POJO for id(java.lang.String)[com。更快的xml.jackson.annotation.ObjectIdGenerator$IdKey@3372bb3f]
... stacktrace ...



< hr>

Gson



我还没有找到一种清理循环依赖的方法。

I'm struggling with Hibernate entities and JSON in these days and, although there is a lot of questions regarding the object, I'm yet not capable to serialize in presence of circular dependencies. I tried with both Gson and jackson but I didn't get a lot of progresses. Here is an excerpt from my objects. This is the "parent" class.

@Entity
public class User extends RecognizedServerEntities implements java.io.Serializable
{
    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", orphanRemoval = false)
    @Cascade({CascadeType.SAVE_UPDATE})
    private Set<Thread> threads = new HashSet<Thread>(0);
    //...other attributes, getters and setters
}

and this is the "children" class

@Entity
@Table(name = "thread")
public class Thread extends RecognizedServerEntities implements java.io.Serializable
{
    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "author", nullable = true)
    private User user;
    //...other attributes, getters and setters
}

I've written a simple class to test both gson and jackson features; as said, they both raise an exception.

public class MyJsonsTest
{
    private static User u;
    public static void main(String[] args)
    {
        u = new User("mail", "password", "nickname", new Date());
        u.setId(1); // Added with EDIT 1
    //  testGson();
        testJackson();
    }

    private static void testJackson()
    {
        Thread t = new Thread("Test", u, new Date(), new Date());
        t.setId(1); // Added with EDIT 1
        u.getThreads().add(t);

        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        try
        {
            mapper.writeValue(new File("result.json"), u);
        }
        catch {/[various exceptions catched, but a JsonMappingException was thrown]}
    }

    private static void testGson()
    {
        Gson gson = new Gson();
        System.out.println(u.toString());
        System.out.println(gson.toJson(u, User.class));

        Thread t = new Thread("Test", u, new Date(), new Date());
        u.getThreads().add(t);

        //This raise an exception overflow
        System.out.println(gson.toJson(u, User.class));
    }
}

To solve the problem, on jackson side, I tried to use this annotation

@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")

on both User and Thread class. However, it doesn't solve the problem. On gson side, I read about the GraphAdapterBuilder class, but I wasn't able to properly use it. I don't find any jar, so I copy/pasted the source code from here. However, there is a compile time error at this line

 private final ConstructorConstructor constructorConstructor = new ConstructorConstructor();

because the ConstructorConstructor() is undefined; the right syntax should be

ConstructorConstructor(Map<Type>, InstanceCreator<?> instanceCreators)

So, is there a definitive solution to this problem? Obviously, I can't use transient variables.

EDIT 1

I finally found the issue with jackson. In the test class, I forgot to initialize the id field (in real scenarios it is initialized by the database) and this is the reason of the exception. When I finally set the id, all works. This is the output

{
  "id" : 1,
  "email" : "mail",
  "password" : "password",
  "nick" : "nickname",
  "registeredDate" : 1414703168409,
  "threads" : [ {
    "id" : 1,
    "thread" : null,
    "user" : 1,
    "title" : "Test",
    "lastModifiedDate" : 1414703168410,
    "createdDate" : 1414703168410,
    "messages" : [ ],
    "threads" : [ ]
  } ],
  "messages" : [ ]
}

解决方案


Jackson

As said, I was able to solve the problem using

@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=MyEntity.class)` 

for each entity as suggested here. The scope attribute was necessary to make sure that the name "id" is unique within the scope. Actually, without the scope attribute, as you can see here, it throws an exception saying

com.fasterxml.jackson.databind.JsonMappingException: Already had POJO for id java.lang.String) [com.fasterxml.jackson.annotation.ObjectIdGenerator$IdKey@3372bb3f] (through reference chain: ParentEntity["children"]->java.util.ArrayList[0]->ChildEntity["id"])
...stacktrace...
Caused by: java.lang.IllegalStateException: Already had POJO for id (java.lang.String) [com.fasterxml.jackson.annotation.ObjectIdGenerator$IdKey@3372bb3f]
...stacktrace...


Gson

I still haven't found a clean way to serialize circular dependencies.

这篇关于Hibernate和JSON - 是否有一个循环依赖的明确解决方案?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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