【发布时间】:2014-12-26 17:53:49
【问题描述】:
这些天来,我一直在与 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
}
这是“儿童”类
@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 的特性;如前所述,它们都引发了异常。
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));
}
}
为了解决这个问题,在杰克逊方面,我尝试使用这个注释
@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
我终于找到了杰克逊的问题。在测试类中,忘记初始化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" : [ ]
}
【问题讨论】:
-
在我的例子中,我创建了特定的 DTO 来将存储在 Hibernate 对象中的数据传输到 JSON,并且在我的设计中避免了这种双向关系。或者,另一方面,我根本不使用带有 JSON 的 Hibernate。
-
为什么关系是“用户”映射的一种方式而“作者”映射的另一种方式?
-
@LuiggiMendoza 你用过哪种 DTO?
-
我创建了一个新的 Hibernate/JPA/Any-other-framework-less annotated 类,一个简单的 POJO,具有通信所需的字段。这是更多的工作,你甚至可以说是重复的努力,但这是你在尝试使用这些技术时假设的一种权衡。另一种解决方案是使用适当的设计,您的对象中不涉及循环引用。
-
@LuiggiMendoza 感谢您的帮助。实际上,我用其他简单的类做了一些测试,确实它似乎工作。另外,我想知道我的实体的问题是否与某种“内部参考”有关;我的意思是,我的
Thread实体链接到一组子线程。因此,我还进行了一些其他测试,将ParentEntity(我使用链接中提供的名称)字段List<ParentEntity> parentEntities和ParentEntity parentEntity添加到。再次,测试通过了。所以,我必须密切关注我的班级。
标签: java json hibernate jackson gson