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

使用SpringBoot与Lombok实现实体类到DTO的序列化

How to Map Cobranca Entity to CobrancaDTO with Different Structural Hierarchies

When dealing with converting entities to DTOs where the structure doesn’t match one-to-one, you have a few solid options—let’s break them down with pros, cons, and examples tailored to your Spring Boot + Lombok setup:

1. Manual Mapping (Custom Conversion Methods)

This is the most straightforward approach if you want full control over transformation logic, especially for small, simple mappings. You can implement the conversion in one of three clean ways:

  • A static method in the DTO
  • A method in the entity class
  • A dedicated mapper class (best for separation of concerns)

Example Code:

Suppose your Cobranca entity (using Lombok) looks like this:

@Getter @Setter
public class Cobranca {
    private Long id;
    private String clienteNome;
    private BigDecimal valorTotal;
    private LocalDate vencimento;
    // Other entity-specific fields
}

And your CobrancaDTO has a nested structure:

@Getter @Setter
public class CobrancaDTO {
    private Long cobrancaId;
    private ClienteDTO cliente;
    private ValorInfo valorInfo;
    
    @Getter @Setter
    public static class ClienteDTO {
        private String nome;
    }
    
    @Getter @Setter
    public static class ValorInfo {
        private BigDecimal valor;
        private LocalDate dataVencimento;
    }
}

A dedicated mapper class would look like this:

@Component // Make it a Spring bean for easy injection
public class CobrancaMapper {
    public CobrancaDTO toDTO(Cobranca cobranca) {
        if (cobranca == null) return null;
        
        CobrancaDTO dto = new CobrancaDTO();
        dto.setCobrancaId(cobranca.getId());
        
        CobrancaDTO.ClienteDTO clienteDTO = new CobrancaDTO.ClienteDTO();
        clienteDTO.setNome(cobranca.getClienteNome());
        dto.setCliente(clienteDTO);
        
        CobrancaDTO.ValorInfo valorInfo = new CobrancaDTO.ValorInfo();
        valorInfo.setValor(cobranca.getValorTotal());
        valorInfo.setDataVencimento(cobranca.getVencimento());
        dto.setValorInfo(valorInfo);
        
        return dto;
    }
}

Pros:

  • Full control: Handle any complex logic (like date formatting or value calculations) easily.
  • No extra dependencies: Works with your existing Spring Boot + Lombok setup.
  • Simple debugging: No magic—you can trace every property mapping step.

Cons:

  • Boilerplate code: Gets tedious if you have many fields or multiple mappings.
  • Maintenance overhead: You need to update the mapper every time you add/remove fields from the entity or DTO.

2. Use a Mapping Library (MapStruct)

For most real-world scenarios, MapStruct is the best balance between reducing boilerplate and maintaining control. It generates type-safe mapping code at compile time, so you avoid runtime reflection issues and get immediate feedback if mappings break.

Setup:

Add the MapStruct dependencies to your pom.xml (or build.gradle):

<!-- MapStruct Core -->
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.5.5.Final</version>
</dependency>
<!-- MapStruct Processor (for code generation) -->
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.5.5.Final</version>
    <scope>provided</scope>
</dependency>

Example Mapping Interface:

@Mapper(componentModel = "spring") // Generates a Spring bean
public interface CobrancaMapper {
    @Mapping(source = "id", target = "cobrancaId")
    @Mapping(source = "clienteNome", target = "cliente.nome")
    @Mapping(source = "valorTotal", target = "valorInfo.valor")
    @Mapping(source = "vencimento", target = "valorInfo.dataVencimento")
    CobrancaDTO toDTO(Cobranca cobranca);
}

MapStruct automatically generates the implementation class at compile time, handling all nested mappings for you. You can inject this mapper into your service or controller just like any other Spring bean.

Pros:

  • Minimal boilerplate: Just define mapping rules, and MapStruct does the rest.
  • Compile-time safety: If you rename a field and forget to update the mapping, you’ll get a compile error instead of a runtime bug.
  • Customizable: Add custom methods for complex transformations or use expressions for one-off mappings.
  • Performance: Generated code is as fast as manual mapping (no reflection overhead).

Cons:

  • Minor setup: Adding the dependency and configuring the processor (though it’s straightforward).
  • Small learning curve: You’ll need to learn MapStruct’s annotations for more complex mappings, but the basics are easy to pick up.

While you could use a custom ObjectMapper with serializers/deserializers to convert directly from the entity to the DTO JSON structure, this approach is generally not ideal:

  • Custom serializers are tightly coupled to JSON structure, making it hard to reuse mapping logic elsewhere.
  • They add unnecessary complexity to your serialization layer, making debugging harder compared to explicit mapping.
  • It’s better to first map the entity to the DTO using one of the above methods, then let the default ObjectMapper serialize the DTO to JSON (which it handles perfectly since the DTO matches the desired structure).

Recommendation

  • For small, simple mappings that rarely change: Go with manual mapping.
  • For most production applications with multiple mappings or frequent changes: Use MapStruct—it’s the industry standard for this problem in Spring Boot.
  • Avoid custom ObjectMapper serializers for structural transformations unless you have a very specific edge case that can’t be handled with the other approaches.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 17:02:27