我正在尝试在春季在两个实体之间创建多对一映射。但是,当我尝试使用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
答案 0 :(得分:0)
1)通常,不建议将fetch = FetchType.EAGER
放在@OneToMany
上。尝试将其设置为LAZY。
2)确保Data和DataList实体正确实现equals()
和hashCode()
方法。
答案 1 :(得分:0)
发生这种情况是因为JSON序列化程序试图一次又一次地递归地序列化两个实体。
因此,在序列化Data
时,其成员dataList1
的类型为DataList
,其中进一步包含List<Data>
,此循环将是无限的。
理想情况下,在这种情况下,应将实体映射到其他一些用于序列化和响应的模型,或者需要@JsonIgnore
避免其中的一种递归循环。
答案 2 :(得分:0)
EAGER
是不好的做法。使用LAZY
,并在需要相关实体时,使用访存联接查询。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());
}
}