这些天我一直在与 Hibernate 实体和 JSON 作斗争,尽管关于对象有很多问题,但我还不能在存在循环依赖项的情况下进行序列化。我尝试了 Gson 和 jackson,但没有取得太大进展。 这是我的对象的摘录。 这是“父”类。
@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
}
这是“ child ”类
@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
}
我写了一个简单的类来测试 gson 和 jackson 的特性;如前所述,他们都提出了一个异常(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));
}
}
为了解决这个问题,在jackson这边,我尝试使用这个注解
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
在 User 和 Thread 类上。但是,它并不能解决问题。 在 gson 方面,我阅读了有关 GraphAdapterBuilder 类的信息,但我无法正确使用它。我没有找到任何 jar,所以我从 here 复制/粘贴了源代码.然而,这一行有一个编译时错误
private final ConstructorConstructor constructorConstructor = new ConstructorConstructor();
因为 ConstructorConstructor() 未定义;正确的语法应该是
ConstructorConstructor(Map<Type>, InstanceCreator<?> instanceCreators)
那么,这个问题有没有确定的解决方案呢?显然,我不能使用 transient
变量。
编辑 1
我终于找到了 jackson 的问题。在测试类中忘记初始化id字段(实际场景中是数据库初始化的),这就是异常的原因。当我最终设置 id 时,一切正常。这是输出
{
"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" : [ ]
}
最佳答案
在处理循环依赖时,您需要构建父子 JSON 层次结构,因为编码必须从根级联到最内层的子级。
对于双向关联,当Parent有一对多的children集合,child有对Parent的多对一引用时,需要在多对一的一侧注解@JsonIgnore :
@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;
@org.codehaus.jackson.annotate.JsonIgnore
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "author", nullable = true)
private User user;
//...other attributes, getters and setters
}
这样你将不再有 Json 序列化时间循环依赖。
关于java - Hibernate 和 JSON - 循环依赖有明确的解决方案吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26657259/