Java 为什么RESTcontroller在JSON中多次返回相同的结果?

Java 为什么RESTcontroller在JSON中多次返回相同的结果?,java,spring,hibernate,jpa,Java,Spring,Hibernate,Jpa,我的rest控制器为对象用户有限次返回相同的对象。其他不需要用户对象的对象可以正常工作。怎么了? 如果我删除一些getter/setter,它可以正常工作,但我实际上需要这里的所有东西。。。 Spring抛出异常-StackOverFlow exc和Java.lang.IllegalStateException:在提交响应后无法调用sendError() 编辑:我发现问题出在“getRoles()”——不幸的是,这对我来说非常重要,我需要将它包含在JSON中。。。如何让它工作 @Entity p

我的rest控制器为对象用户有限次返回相同的对象。其他不需要用户对象的对象可以正常工作。怎么了? 如果我删除一些getter/setter,它可以正常工作,但我实际上需要这里的所有东西。。。 Spring抛出异常-StackOverFlow exc和Java.lang.IllegalStateException:在提交响应后无法调用sendError()

编辑:我发现问题出在“getRoles()”——不幸的是,这对我来说非常重要,我需要将它包含在JSON中。。。如何让它工作

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name = "first_name")
    private String firstName;
    private String surname;
    private String email;
    private String password;

    @ManyToMany
    @JoinTable(
            name = "users_roles",
            joinColumns = @JoinColumn(
                    name = "user_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(
                    name = "role_id", referencedColumnName = "id"))
    private List<Role> roles;

    @JsonIgnore
    @ManyToMany
    @JoinTable(
            name="users_documents",
            joinColumns = @JoinColumn(
                    name = "user_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(
                    name="document_id", referencedColumnName = "id"))
    private List<Document> usersDocuments;


    @OneToMany(mappedBy="user")
    private List<Document> sharedDocuments;


    public User() {

    }

    public User(String firstName, String surname, String email, String password) {
        this.firstName = firstName;
        this.surname = surname;
        this.email = email;
        this.password = password;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public String getEmail() {
        return email;
    }

    public String getPassword() {
        return password;
    }


    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        User user = (User) o;
        return getId() == user.getId();
    }

    @Override
    public int hashCode() {
        return Objects.hash(getId());
    }

    @Override
    public String toString() {
        return "User{" +
                "firstName='" + firstName + '\'' +
                ", surname='" + surname + '\'' +
                ", email='" + email + '\'' +
                ", roles=" + roles +
                '}';
    }
}
@实体
公共类用户{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
@列(name=“first_name”)
私有字符串名;
私家姓;
私人字符串电子邮件;
私有字符串密码;
@许多
@可接合(
name=“用户\角色”,
joinColumns=@JoinColumn(
name=“user\u id”,referencedColumnName=“id”),
inverseJoinColumns=@JoinColumn(
name=“role\u id”,referencedColumnName=“id”))
私有列表角色;
@杰索尼奥雷
@许多
@可接合(
name=“用户\文档”,
joinColumns=@JoinColumn(
name=“user\u id”,referencedColumnName=“id”),
inverseJoinColumns=@JoinColumn(
name=“document\u id”,referencedColumnName=“id”))
私有列表用户文档;
@OneToMany(mappedBy=“用户”)
私人名单共享文件;
公共用户(){
}
公共用户(字符串名字、字符串姓氏、字符串电子邮件、字符串密码){
this.firstName=firstName;
this.姓氏=姓氏;
this.email=电子邮件;
this.password=密码;
}
公共长getId(){
返回id;
}
公共无效集合id(长id){
this.id=id;
}
公共字符串getFirstName(){
返回名字;
}
public void setFirstName(字符串firstName){
this.firstName=firstName;
}
公共字符串getNames(){
返回姓氏;
}
public void setSurname(字符串姓氏){
this.姓氏=姓氏;
}
公用电子邮件(字符串电子邮件){
this.email=电子邮件;
}
public void setPassword(字符串密码){
this.password=密码;
}
公共列表getRoles(){
返回角色;
}
公共字符串getEmail(){
回复邮件;
}
公共字符串getPassword(){
返回密码;
}
public void setRoles(列出角色){
this.roles=角色;
}
@凌驾
公共布尔等于(对象o){
如果(this==o)返回true;
如果(!(o instanceof User))返回false;
用户=(用户)o;
返回getId()==user.getId();
}
@凌驾
公共int hashCode(){
返回Objects.hash(getId());
}
@凌驾
公共字符串toString(){
返回“用户{”+
“firstName=”+firstName+“\”+
“,姓氏=”“+姓氏+”\”+
“,email='”+email+'\''+
“,roles=“+角色+
'}';
}
}

不确定是否可以专门针对您的数据,但我能够通过使用集合(而不是列表)来解决问题,仅针对我遇到问题的映射集合

我注意到杰克逊在这个问题上受到了很多指责。不过,在我的例子中,我注意到将FetchType设置为Lazy解决了这个问题,而无需修改集合类型

我猜这对您的情况没有帮助,因为您无论如何都需要实例化所有这些字段,在这种情况下,延迟加载将是一种浪费

尽管如此,您可能希望查看代码中实例化与其他实体关联的对象的所有位置,并检查是否有额外的对象在意外情况下被急切地实例化

您的equals()方法似乎完全符合最佳实践。不过,我实际上不确定您是否在那里创建了用户对象,在这种情况下,作为一种副作用,用户的关联对象将被急切地实例化


这一点我可能大错特错(抱歉,目前无法检查),但如果您遇到问题,既不能使用延迟加载,也不能选择集合而不是列表,您可能需要密切关注类似的情况。

不确定是否可以针对您的数据,但是,我能够通过使用集合而不是列表来解决这个问题,只针对我遇到问题的映射集合

我注意到杰克逊在这个问题上受到了很多指责。不过,在我的例子中,我注意到将FetchType设置为Lazy解决了这个问题,而无需修改集合类型

我猜这对您的情况没有帮助,因为您无论如何都需要实例化所有这些字段,在这种情况下,延迟加载将是一种浪费

尽管如此,您可能希望查看代码中实例化与其他实体关联的对象的所有位置,并检查是否有额外的对象在意外情况下被急切地实例化

您的equals()方法似乎完全符合最佳实践。不过,我实际上不确定您是否在那里创建了用户对象,在这种情况下,作为一种副作用,用户的关联对象将被急切地实例化


这一点我可能大错特错(抱歉,目前无法检查),但如果您遇到问题,既不能使用延迟加载,也不能选择集合而不是列表,您可能需要密切关注类似的场景。

这可能与此相关:您的角色中是否有用户?如果是这样,则将角色内部的用户列表设置为临时用户,或者添加一个jsonignore注释,包括