You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Hibernate查询结果直接映射到CompanyStatusDTO对象?

当然可以直接把MySQL查询结果映射到你的CompanyStatusDTO对象里!作为Hibernate新手,我结合你的实体和DTO结构,给你介绍几种实用的实现方式:

方法1:JPQL查询 + 内存手动组装(最易理解)

这种方式适合新手先理解映射逻辑,通过JPQL查询出关联数据后,在内存中手动组装成嵌套的DTO结构。

步骤1:编写JPQL查询关联数据

String jpql = """
    SELECT cs.companyStatusId, cs.companyStatusLabel, 
           es.employeeStatusId, es.employeeStatusName
    FROM company_status cs
    JOIN company_status_employee_status cses 
        ON cs.companyStatusId = cses.companyStatusId
    JOIN employee_status es 
        ON cses.employeeStatusId = es.employeeStatusId
""";

步骤2:执行查询并组装DTO

EntityManager entityManager = // 获取你的EntityManager实例
List<Object[]> rawResults = entityManager.createQuery(jpql).getResultList();

// 用Map来分组同一个CompanyStatus下的EmployeeStatus
Map<Integer, CompanyStatusDTO> companyDtoMap = new HashMap<>();

for (Object[] row : rawResults) {
    Integer companyId = (Integer) row[0];
    String companyLabel = (String) row[1];
    Integer empId = (Integer) row[2];
    String empName = (String) row[3];

    // 从Map中获取或创建当前Company的DTO
    CompanyStatusDTO companyDto = companyDtoMap.getOrDefault(companyId, new CompanyStatusDTO());
    companyDto.setCompanyStatusId(companyId);
    companyDto.setCompanyStatusLabel(companyLabel);

    // 创建EmployeeStatusDTO并添加到列表
    EmployeeStatusDTO empDto = new EmployeeStatusDTO();
    empDto.setEmployeeStatusId(empId);
    empDto.setEmployeeStatusName(empName);

    if (companyDto.getEmployeeStatusDTOs() == null) {
        companyDto.setEmployeeStatusDTOs(new ArrayList<>());
    }
    companyDto.getEmployeeStatusDTOs().add(empDto);

    companyDtoMap.put(companyId, companyDto);
}

// 最终结果转换为List
List<CompanyStatusDTO> finalDtoList = new ArrayList<>(companyDtoMap.values());

方法2:使用Hibernate自定义ResultTransformer(封装性更好)

Hibernate提供了ResultTransformer接口,可以把查询结果直接转换为目标DTO,把组装逻辑封装到Transformer中,代码更简洁。

步骤1:自定义ResultTransformer

public class CompanyStatusDTOResultTransformer implements ResultTransformer {
    private final Map<Integer, CompanyStatusDTO> companyDtoMap = new HashMap<>();

    @Override
    public Object transformTuple(Object[] tuple, String[] aliases) {
        Integer companyId = (Integer) tuple[0];
        String companyLabel = (String) tuple[1];
        Integer empId = (Integer) tuple[2];
        String empName = (String) tuple[3];

        CompanyStatusDTO companyDto = companyDtoMap.getOrDefault(companyId, new CompanyStatusDTO());
        companyDto.setCompanyStatusId(companyId);
        companyDto.setCompanyStatusLabel(companyLabel);

        EmployeeStatusDTO empDto = new EmployeeStatusDTO();
        empDto.setEmployeeStatusId(empId);
        empDto.setEmployeeStatusName(empName);

        companyDto.setEmployeeStatusDTOs(Optional.ofNullable(companyDto.getEmployeeStatusDTOs())
                .orElseGet(ArrayList::new));
        companyDto.getEmployeeStatusDTOs().add(empDto);

        companyDtoMap.put(companyId, companyDto);
        return companyDto;
    }

    @Override
    public List transformList(List collection) {
        // 返回去重后的最终DTO列表
        return new ArrayList<>(companyDtoMap.values());
    }
}

步骤2:使用Transformer执行查询

EntityManager entityManager = // 获取你的EntityManager实例
List<CompanyStatusDTO> dtoList = entityManager.createQuery(jpql)
        .unwrap(org.hibernate.query.Query.class)
        .setResultTransformer(new CompanyStatusDTOResultTransformer())
        .getResultList();

方法3:实体关联 + ModelMapper/MapStruct转换(最优雅推荐)

如果允许修改实体类,建议先给CompanyStatus和EmployeeStatus建立多对多关联,然后用ModelMapper或MapStruct这类工具自动完成实体到DTO的转换,代码最简洁易维护。

步骤1:修改实体建立关联

@Entity(name = "company_status")
@Table(name = "company_status")
public class CompanyStatus implements Serializable {
    // 原有字段...

    @ManyToMany
    @JoinTable(
            name = "company_status_employee_status",
            joinColumns = @JoinColumn(name = "company_status_id"),
            inverseJoinColumns = @JoinColumn(name = "employee_status_id")
    )
    private List<EmployeeStatus> employeeStatuses;

    // getter和setter
}

步骤2:用ModelMapper自动转换

先引入ModelMapper依赖(Maven为例):

<dependency>
    <groupId>org.modelmapper</groupId>
    <artifactId>modelmapper</artifactId>
    <version>3.1.1</version>
</dependency>

然后编写转换代码:

// 初始化ModelMapper
ModelMapper modelMapper = new ModelMapper();
// 配置实体到DTO的映射规则(自动匹配字段名,这里可以省略,因为字段名一致)
modelMapper.typeMap(CompanyStatus.class, CompanyStatusDTO.class)
        .addMapping(CompanyStatus::getEmployeeStatuses, CompanyStatusDTO::setEmployeeStatusDTOs);

// 查询带关联的CompanyStatus数据
List<CompanyStatus> companies = entityManager.createQuery(
        "SELECT cs FROM company_status cs JOIN FETCH cs.employeeStatuses", 
        CompanyStatus.class
).getResultList();

// 自动转换为DTO列表
List<CompanyStatusDTO> dtoList = companies.stream()
        .map(company -> modelMapper.map(company, CompanyStatusDTO.class))
        .collect(Collectors.toList());

总结

  • 新手可以先从方法1入手,理解数据组装的逻辑;
  • 追求代码封装性可以用方法2;
  • 长期维护推荐方法3,实体关联+自动映射工具的方式最优雅,减少手动代码量。

内容的提问来源于stack exchange,提问作者java12399900

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 20:27:58