英文:
How to convert nested Entity to DTO using MapStruct or Java Stream?
问题
在我的Spring Boot应用中,通常我使用投影来返回连接表的结果。然而,我尝试使用Java Stream来映射和返回嵌套实体到相应的DTO。以下是我通常遇到的一个例子:
**注意:** 我使用Hibernate设置实体关系那部分完全没问题。因此,为简洁起见,我省略了相关的代码。只需专注于将实体映射到嵌套DTO。
国家有许多州,州有许多城镇...
***Country:***
```java
public class Country {
private Long id;
private String name;
@OneToMany(...)
private Set<State> states = new HashSet<>();
}
State:
public class State {
private Long id;
private Long population;
@ManyToOne(...)
private Country country;
@OneToMany(...)
private Set<Town> towns = new HashSet<>();
}
Town:
public class Town {
private Long id;
private String name;
@ManyToOne()
private State state;
}
我想要获取国家列表,其中包括国家名称、属于该国家的州人口总和以及属于该国家的城镇列表。
为此,我创建了以下DTO,但不确定是否正确,以及如何一次性地将必要的数据映射到这个DTO(我不想访问数据库3次,而是希望将国家列表映射到相应的字段(由于我使用Hibernate正确构建了关系,列表中包含所有这些数据))。
@Data
public class CountryResponse {
private Long id;
private String name;
private Set<StateResponse> states;
private Long population;
private Set<TownResponse> towns;
public CountryResponse(Country country) {
this.id = country.getId();
this.name = country.getName();
// ???
this.states = country.getStates().stream().map(StateResponse::new)
.collect(Collectors.toSet());
this.towns = this.states.stream().flatMap(stateResponse -> stateResponse.getTowns().stream())
.collect(Collectors.toSet());
}
}
我该如何做呢?如果对于这种情况使用MapStruct是否更好?
<details>
<summary>英文:</summary>
In my Spring Boot apps, I generally use projection in order to return joined table results. However, I am trying to use Java Stream to map and return nested entities to the corresponding DTOs. Here is an example that I generally encountered:
**Note:** I setup entity relationship using Hibernate and that part is completely ok. For this reason, I omitted the related code for brevity. Just concentrate on mapping entities to the nested DTOs.
Country has many States, States has many Towns...
***Country:***
public class Country {
private Long id;
private String name;
@OneToMany(...)
private Set<State> states = new HashSet<>();
}
<br/>
***State:***
public class State {
private Long id;
private Long population;
@ManyToOne(...)
private Country country;
@OneToMany(...)
private Set<Town> towns = new HashSet<>();
}
<br/>
***Town:***
public class Town {
private Long id;
private String name;
@ManyToOne()
private State state;
}
I want to get Country list with Country Name, Sum of state population belonging to this country and Town list belonging to the country.
For this purpose, I created the following DTOs, but not sure if it is ok and how can I map the necessary data to this DTO in one step (I don't want to go to database 3 times, instead, I just want to map the country list to the corresponding fields (the list has all of these data as I built the relations properly using Hibernate).
@Data
public class CountryResponse {
private Long id;
private String name;
private Set<StateResponse> states;
private Long population;
private Set<TownResponse> towns;
public CountryResponse(Country country) {
this.id = country.getId();
this.name = country.getName();
// ???
this.states = country.getStates.stream().map(StateResponse::new)
.collect(Collectors.toSet());
this.towns = this.states.stream().map(TownResponse::new)
.collect(Collectors.toSet());
}
}
How can I do this? I would also consider using MapStruct if it is better for this scenario?
</details>
# 答案1
**得分**: 1
获取各州人口总和的代码:
```java
country.getStates().stream().map(State::getPopulation).sum();
获取城镇列表的代码:
country.getStates().stream().map(State::getTowns).flatMap(Set::stream).collect(Collectors.toList());
英文:
To get the sum of state populations, you can use the following stream code
country.getStates().stream().map(State::getPopulation).sum();
and the list of towns can be fetched as follows
country.getStates().stream().map(State::getTowns).flatMap(Set::stream).collect(Collectors.toList());
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论