在将某些字段分组为子DTO对象后,Spring webflux将flux转换为DTO



我的rest api使用Spring Webflux。而从Postgres这是非规范化表抓取实体,我得到多行相同的对象。在转换为DTO时,我需要迭代同一用户的多个User对象,并制作他/她所属的所有部门的列表,然后将该列表添加到DTO。这样,我就可以向每个用户发送单行。如何在不阻塞的情况下实现这一点?

@Entity
public Class User {
private int id;
private String name;
private String department;
private String departmentArea;
}
public Class UserDTO {

private int id;
private String name;
private List<DepartmentDTO> departmentDTO;

}

如何将User对象转换为带有DepartmentDTO列表的UserDTO

当前在服务中的实现

userRepo.findAllUsersByIds().map(mapper::mapUserDTO));

我的母语不是英语。很抱歉我的英语不好。

我认为你可以在Flux上使用groupBy.
groupBy需要一个keyMapper。在您的示例中,它将是用户的idname

userRepo.findAllUsersByIds()
.groupBy(user -> new UserDto(user.getId(), user.getName()))

Flux分组后,您的流中有GroupedFlux
GroupedFlux有键和值。Key是通过上面的keyMapper传递的值。GroupedFlux本身是按键分组的值。所以GroupedFlux.collectList()会返回List<User>

.flatMap(groupedFlux -> 
Mono.zip(
groupedFlux.key(),
groupedFlux.collectList()
)
)

通过flatMap传递的值是一个包含UserDtoList<User>的元组。
因此将其强制转换为您想要响应的UserDto

.flatMap(tuple -> {
// tuple.getT2() would be the grouped user list. (List<User>)
// cast it into List<DepartmentDTO>
// ...
tuple.t1.setDepartmentDto(...);
// return UserDto
return Mono.just(
tuple.t1
);
})

整个代码应该是

userRepo.findAllUsersByIds()
.groupBy(user -> new UserDto(user.getId(), user.getName()))
.flatMap(groupedFlux -> 
Mono.zip(
groupedFlux.key(),
groupedFlux.collectList()
)
)
.flatMap(tuple -> {
// tuple.getT2() would be the grouped user list. (List<User>)
// cast it into List<DepartmentDTO>
// ...
tuple.t1.setDepartmentDto(...);
// return UserDto
return Mono.just(
tuple.t1
);
})

您可以使用groupBy运算符按id分组,然后将每组映射到UserDTO

Flux<UserDTO> res = userRepo.findAllUsersByIds()
.groupBy(user -> user.getId())
.flatMap(group ->
group.collectList()
.map(users -> {
var userDto = new UserDTO();
userDto.setId(group.key());
userDto.setName(users.get(0).getName());
userDto.setDepartmentDTO(
users.stream()
.map(user -> {
var deptDto = new DepartmentDTO();
deptDto.setName(user.getDepartment());
deptDto.setArea(user.getDepartmentArea());
return deptDto;
})
.toList()
);
return userDto;
})
);

最新更新