我有两个POJO。
一个配置文件类,带有:id,name,messages(消息列表),映射为一对多关系。
带有:id,message,profile(与ManyToOne映射)的消息类
配置文件类
@XmlRootElement
@Entity
@Table(name="Profile")
public class Profile {
@Id
@GeneratedValue
@Column(name="profile_id")
private int id;
private String name;
@OneToMany(mappedBy="profile")
private List<Message> messages = new ArrayList<Message>();
消息类
@XmlRootElement
@Entity
@Table(name="Message")
public class Message {
@Id
@GeneratedValue
private int id;
private String message;
@ManyToOne
@JoinColumn(name="profile_id")
private Profile profile;
后方法
@POST
@Path("/test")
@Produces(MediaType.APPLICATION_JSON)
public Profile test(){
Profile profile = new Profile(1,"John");
Message message = new Message("Hello World!");
Session session = sessionFactory.openSession();
session.beginTransaction();
profile.getMessages().add(message);
session.save(profile);
message.setProfile(profile);
session.save(message);
session.getTransaction().commit();
session.close();
return profile;
}
当我在Chrome中通过Postman发出请求时,我会收到一个"500内部服务器错误"。
奇怪的是,它在我的数据库中进行插入。它做得很正确(它使用外键将消息映射到配置文件),但似乎无法以Json的形式返回响应。
如果我不保存消息(使用session.save(消息)),它会返回正确的响应,但不再映射它。
如何使用一对多关系获得Json响应?
我发现这500个服务器错误通常是由JSON编组过程中的电路引起的。
例如,Jersey开始将Profile对象编组为JSON。它处理id、名称,然后开始编组messages属性。
它从数组中取出第一个Message对象并开始对其进行编组。第一个Message物体有一个id、名称和对Profile对象的引用。此时,它将跟随Profile对象,并开始重新对其进行编组。
您可以看到,您已经进入了一个未终止的递归过程。最终停止递归编组的是当堆栈耗尽时您遇到的500Server错误。
要停止这种情况,您可以对对象进行自定义编组,也可以简单地在Message类的profile属性上放置@JsonIgnore属性。
如果您发现需要更多的控制,请查找com.fasterxml.jackson.databind.JsonSerializer.
我在这个问题上挠头了整整一天。同样的行为,我也无法在控制台上看到任何日志。甚至连@jsonIgnorreperties都帮不了我。
所以我继续,在返回响应之前,我遍历了我的响应对象,并将空值设置为子对象中的父参数。
List<Message> messages=Profile.getMessage();
for (Message msg:messages){
msg.setProfile(null);
}
这对我很有效,因为我不需要子对象中的父对象。