如何使用MapStruct或Java Stream将嵌套的实体转换为DTO?

huangapple go评论75阅读模式
英文:

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&lt;State&gt; states = new HashSet&lt;&gt;();

}


&lt;br/&gt;

***State:***

public class State {

private Long id;

private Long population;

@ManyToOne(...)
private Country country;

@OneToMany(...)
private Set&lt;Town&gt; towns = new HashSet&lt;&gt;();

}




&lt;br/&gt;


***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&#39;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&lt;StateResponse&gt; states;

private Long population;

private Set&lt;TownResponse&gt; 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());

huangapple
  • 本文由 发表于 2023年2月19日 03:14:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75495782.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定