您好Hibernate和Jackson有问题。有两个POJO
@Entity
@Table(name = "USERS")
public class User implements Serializable {
static final long serialVersionUID = 4235637833262722256L;
@Id
@GeneratedValue
private int id;
@Column(name = "CREATION_DATE")
private Date creationDate;
@Column(name = "FIRST_NAME")
private String firstName;
@Column(name = "LAST_NAME")
private String lastName;
@Version
@Column(name = "VERSION")
private int version;
@Column(name = "E_MAIL")
private String email;
@Column(name = "ENABLED")
private boolean enabled;
@Column(name = "LOGIN")
private String login;
@Column(name = "PASSWORD")
private String password;
@JsonManagedReference("role")
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL,fetch = FetchType.EAGER)
private Set<UserRole> userRole;
用户及其为春季安全集成所做的角色。
@Entity
@Table(name = "USER_ROLES")
public class UserRole {
@Version
@Column(name = "VERSION")
int version;
@Id
@GeneratedValue
private int id;
@JsonBackReference("role")
@ManyToOne()
@JoinColumn(name = "USER_ID", referencedColumnName = "ID")
private User user;
@Column(name = "ROLE")
private String role;
并拥有一个由用户Json通过Jackson制作的控制器。用方法
@RequestMapping(value = "/login", method = RequestMethod.GET, produces = "application/json")
private @ResponseBody User checkLoginAvailability(@RequestParam String login) {
User user = appContext.getUserService().readUserByLogin(login);
if (user != null) {
return user;
}
return new User();
}
当此方法返回没有空字段的用户时,它会抛出:
26-Oct-2014 14:31:17.652 WARNING [http-nio-8080-exec-4]
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.doResolveException
Handling of [org.springframework.http.converter.HttpMessageNotWritableException]
resulted Exception java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
当我添加@OneToMany(mappedBy =&#34; user&#34;,cascade = CascadeType.ALL,fetch = FetchType.EAGER)时出现了问题,之前它只是fetch = FetchType.EAGER,但是我无法在这种情况下保存用户的用户表USER_ROLE为空。我在杰克逊的某个地方无限循环地解决了一些问题的解决方案,添加了一些anotation @JsonBackReference(&#34; role&#34;)和@JsonManagedReference(&#34; role&#34;)但没有任何改变。我怎么解决这个问题?谢谢!
答案 0 :(得分:4)
我建议在导致循环引用的属性上添加@jsonignore
。这将告诉杰克逊不要序列化该属性。
答案 1 :(得分:1)
在调用sendError时,使用IllegalStateException的异常断点来暂停执行,然后检查堆栈上的局部变量以获取无法报告的异常,并调用其printStackTrace方法以查看其堆栈跟踪。
希望异常的根本原因是明确的,并且随之而来的是如何解决问题所在。
答案 2 :(得分:1)
有时复合豆会导致这种问题。正如我看到您的关系@OneToMany是EAGER,这是正确的原因,如果您在将列表序列化为JSON时使用LAZY,则依赖项对象将丢失。你的问题是序列化问题,我毫不怀疑。
你可以尝试:
@Entity
@Table(name = "USERS")
//To suppress serializing properties with null values
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
//Ignoring new fields on JSON objects
@JsonIgnoreProperties(ignoreUnknown = true)
public class User implements Serializable {
...
但我建议您使用一种称为数据传输对象(DTO)的良好实践。 DTO是在持久性bean的中间层和表单中使用的bean。最常用于(N)层应用程序中的服务层或控制器,以在其自身和UI层之间传输数据。您可以在服务层创建DTO,也可以直接在控制器中创建(更好的服务)并将其发送到表单,它还允许您直接在控制器中将表单条目绑定到验证(基本上您需要添加参数BindingResult结果在控制器方法的签名中)。 DTO允许您创建进行验证的注释,如@ NotTmpty,@ PasswordsNotEqual,@ Size(max = 100),这些注释将在bean中进行,您也可以将这些注释放在持久性bean中,但不建议您使用创建一个非常复杂的bean。验证信息显示在以下表格中:
<form:errors id="error-password" path="password" cssClass="help-block"/>
相信我,DTO非常适合您的场景,因为它允许您以正确的方式验证表单条目。
最好的问候
答案 3 :(得分:0)
我找到的最佳解决方案是不直接返回实体。 在您的情况下,您将直接在登录控制器中返回“用户”实体。而只是返回user.id或user.firstname等。它会正常工作。当我们返回任何实体时,编译器进入无限递归循环。