首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Spring中将Optional<Entity>转换为Optional<EntityDTO>?

如何在Spring中将Optional<Entity>转换为Optional<EntityDTO>?
EN

Stack Overflow用户
提问于 2021-06-15 06:31:54
回答 2查看 2.3K关注 0票数 1

我是Spring的新手,虽然我可以将域实体转换为List<Entity>,但我不能为Optional<Entity>正确地转换它们。我在存储库和服务中有以下方法:

EmployeeRepository:

代码语言:javascript
复制
@Query(value = "SELECT ...")
Optional<Employee> findByUuid(@Param(value = "uuid") final UUID uuid);

EmployeeService:

代码语言:javascript
复制
@Override
@LogExecution
@Transactional(readOnly = true)
public Optional<EmployeeDTO> findByUuid(UUID uuid) {
    Optional<Employee> employee = employeeRepository.findByUuid(uuid);
        return employee
                .stream()
                .map(EmployeeDTO::new)
                // .orElse(null);
                //.findFirst(); /// ??? 
    }

我的问题:

1.如何正确地将Optional<Employee>转换为Optional<EmployeeDTO>

2.是否收集SELECT子句中的字段,并通过匹配它们的名称将服务方法中的字段映射到相应的DTO?如果是这样的话,它是否维护数据库表和域模型类中的命名(例如employee_nameemployeeName )?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-06-15 06:46:29

employeeRepository#findByUuid的输出Optional<Employee>和方法输出类型Optional<EmployeeDTO>之间的映射是1:1,因此这里不涉及Stream (调用stream())。

您只需要正确地将Employee字段映射到EmployeeDTO中。处理OptionalemployeeRepository#findByUuid返回的情况实际上是空的,可以将其留在可选的后续链上。不需要orElsefindFirst调用。

使用all-args构造函数和getter假设以下类:

代码语言:javascript
复制
class Employee {
    private final long id;
    private final String firstName;
    private final String lastName;
}
代码语言:javascript
复制
class EmployeeDTO {
    private final long id;
    private final String name;
    private final String surname;
}

..。你可以做这个。除了从Employee的字段中找到创建Employee的方法之外,什么都不需要。如果从employeeRepository返回的Optional被返回,则不会发生映射,并且返回一个空的Optional

代码语言:javascript
复制
@Override
@LogExecution
@Transactional(readOnly = true)
public Optional<EmployeeDTO> findByUuid(UUID uuid) {
    return employeeRepository
        .findByUuid(uuid)                             // Optional<Employee>
        .map(emp -> new EmployeeDTO(                  // Optional<EmployeeDTO>
                 emp.getId(),                         // .. id -> id
                 emp.getFirstName(),                  // .. firstName -> name
                 emp.getLastName()));                 // .. lastName -> surname
}

注意:对于Employee -> EmployeeDTO映射,我建议选择其中之一:

  • EmployeeDTO中创建一个接受EmployeeDTO的构造函数,允许与.map(EmployeeDTO::new)映射(缺点:创建依赖项)。
  • 只需使用getter/setter映射即可。
  • 使用映射框架(如MapStruct或任何其他框架)。
票数 2
EN

Stack Overflow用户

发布于 2021-06-15 06:49:03

有多个选项可以将实体映射到DTO。

  1. 使用投影:存储库可以通过使用投影直接返回DTO。如果您根本不需要实体,这可能是最好的选择。你可以在这里找到所有关于投影的信息,https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections
  2. 使用像地图结构模型映射器这样的库来生成映射代码
  3. 将构造函数或静态工厂方法添加到DTO中。有点像
代码语言:javascript
复制
class EmployeeDTO {
   // fields here ...
   public static EmployeeDTO ofEntity(Employee entity) {
     var dto = new EmployeeDTO();
     // set fields
     return dto;
   }
}

并在您的服务中调用employee.map(EmployeeDTO::ofEntity)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67981095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档