在春季使用多对一映射时获得无限的Json响应

时间:2019-06-03 09:29:45

标签: java json spring spring-boot jpa

我正在尝试在春季在两个实体之间创建多对一映射。但是,当我尝试使用restController获取值时,会得到

  

Java.lang.IllegalStateException:在调用后无法调用sendError()   响应已提交

错误和无限的JSON响应。添加JSONignore可以解决此问题,但是我根本没有在响应中看到该列。我不知道该如何解决。请帮忙。预先感谢。

这是我的实体:

@Entity
@Table(name="tbl1")
public class Data {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "customer")
    private String customer;



    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name="data_id", insertable = true, nullable = false, updatable = false)
    private DataList dataList1;

}

@Entity
@Table(name="tbl2")
public class DataList {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="data_id")
    private Long dataId;



    @Column(name="user_name")
    private String userName;



    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER,mappedBy = "dataList1")
    private List<Data> data1;


}

存储库:

@Repository
@Transactional
public interface DataList extends JpaRepository<DataList,Long> {
}
@Repository
@Transactional
public interface Data extends JpaRepository<Data,Long> {
}

我的错误:Java.lang.IllegalStateException: Cannot call sendError() after the response has been committed

3 个答案:

答案 0 :(得分:0)

1)通常,不建议将fetch = FetchType.EAGER放在@OneToMany上。尝试将其设置为LAZY。

2)确保Data和DataList实体正确实现equals()hashCode()方法。

答案 1 :(得分:0)

发生这种情况是因为JSON序列化程序试图一次又一次地递归地序列化两个实体。

因此,在序列化Data时,其成员dataList1的类型为DataList,其中进一步包含List<Data>,此循环将是无限的。

理想情况下,在这种情况下,应将实体映射到其他一些用于序列化和响应的模型,或者需要@JsonIgnore避免其中的一种递归循环。

答案 2 :(得分:0)

  1. EAGER是不好的做法。使用LAZY,并在需要相关实体时,使用访存联接查询。
  2. 这里最有可能是双向关系中的问题。您使用DataList列表获取Data。列表Data中的每个ListData都再次引用。 序列化json时,很可能是堆栈溢出。因此,请记住一个规则:切勿让控制器进入休眠状态。编写一个映射器将此实体映射到Dto个对象。

您可能会认为将某些模型映射到另一个模型非常无聊。但是这里是另一种方式。休眠实体不应传递到前端。我的应用程序使用几种类型的对象:Entities(从数据库中获取),DTO(将实体映射到DTO并提供它们的服务组件时),Shared(将DTO映射到Shared时)并在微服务之间共享作为对控制器的响应)和Model(当从Response映射到Model并提供给模板引擎时,例如freemarker)。您可能不需要这种模型层次结构。

创建DTO:

@AllArgsConstructor
@NoArgsConstructor
@Getter
public class DataListDto {

    private Long dataId;
    private String userName;

    private List<DataDto> data1;


}

@AllArgsConstructor
@NoArgsConstructor
@Getter
public class DataDto {

    private long id;
    private String customer;

}

编写您的映射器:

 public class DataListMapper {

    public static DataListDto mapToDto(DataList dataList) {
        return new DataListDto(dataList.getDataId(), dataList.getUserName(), dataList.getData1().stream().map(x -> DataListMapper.mapToDto(x).collect(Collectors.toList)))
    }

    public static DataDto mapToDto(Data data) {
        return new DataDto(data.getId(), data.getCustomer());
    }
}

您的服务

public class DataListService {
            @Autowired
            private DataListRepository dataListRepository;


            public List<DataListDto> getAllData() {
                List<DataList> dataLists = this.dataListRepository.findAll();
                return dataLists.stream().map(x->DataListMapper.mapToDto(x)).collect(Collectors.toList());
            }
        }