使用MapStruct和Lombok轉換資料物件

banq發表於2024-06-16

Project Lombok是一個有助於樣板程式碼的庫,使我們能夠更加專注於核心應用程式邏輯。

類似地,當我們需要兩個 Java bean 之間的對映時,MapStruct是另一個可以幫助提供樣板的庫。

在本教程中,我們將研究如何有效地結合使用這兩個庫:
使用@Builder和@Data Lombok 註釋。前者允許透過Builder 模式建立物件,而後者透過 setter 提供基於建構函式的物件建立。

設定
我們將mapstruct、lombok和lombok-mapstruct-binding依賴項新增到我們的pom.xml中:

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.6.0.Beta2</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.32</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok-mapstruct-binding</artifactId>
    <version>0.2.0</version>
</dependency>

MapStruct 與 Lombok 整合
我們將在設定中使用@Builder和@Data Lombok 註釋。前者允許透過Builder 模式建立物件,而後者透過 setter 提供基於建構函式的物件建立。

1. Java POJO 設定
現在,讓我們首先為對映器定義一個簡單的源類:

@Data
public class SimpleSource {
    private String name;
    private String description;
}

接下來,我們為對映器定義一個簡單的目標類:

@Data
public class SimpleDestination {
    private String name;
    private String description;
}

最後,我們還將定義另一個目標類,但使用@Builder Lombok 註釋:

@Builder
@Getter
public class LombokDestination {
    private String name;
    private String description;
}

2. 使用@Mapper註解
當我們使用@Mapper註釋時,MapStruct會自動建立對映器實現。

讓我們定義對映器介面:

@Mapper
public interface LombokMapper {
    SimpleDestination sourceToDestination(SimpleSource source);
    LombokDestination sourceToLombokDestination(SimpleSource source);
}

當我們執行mvn clean install命令時,會在/target/generated-sources/annotations/資料夾下建立mapper實現類。

我們來看一下生成的實現類:

public class LombokMapperImpl implements LombokMapper {
    @Override
    public SimpleDestination sourceToDestination(SimpleSource source) {
        if ( source == null ) {
            return null;
        }
        SimpleDestination simpleDestination = new SimpleDestination();
        simpleDestination.setName( source.getName() );
        simpleDestination.setDescription( source.getDescription() );
        return simpleDestination;
    }
    @Override
    public LombokDestination sourceToLombokDestination(SimpleSource source) {
        if ( source == null ) {
            return null;
        }
        LombokDestination.LombokDestinationBuilder lombokDestination = LombokDestination.builder();
        lombokDestination.name( source.getName() );
        lombokDestination.description( source.getDescription() );
        return lombokDestination.build();
    }
}

正如我們在這裡看到的,實現有兩種方法可以將源物件對映到不同的目標。然而,主要的區別在於目標物件的構建方式。

該實現使用LombokDestination類的builder()方法。另一方面,它使用建構函式建立SimpleDestination物件並使用 setter 對映變數。

3. 測試用例
現在,讓我們看一個簡單的測試用例來檢視對映器的實際實現:

@Test
void whenDestinationIsMapped_thenIsSuccessful() {
    SimpleSource simpleSource = new SimpleSource();
    simpleSource.setName(<font>"file");
    simpleSource.setDescription(
"A text file.");
    SimpleDestination simpleDestination = lombokMapper.sourceToDestination(simpleSource);
    Assertions.assertNotNull(simpleDestination);
    Assertions.assertEquals(simpleSource.getName(), simpleDestination.getName());
    Assertions.assertEquals(simpleSource.getDescription(), simpleDestination.getDescription());
    LombokDestination lombokDestination = lombokMapper.sourceToLombokDestination(simpleSource);
    Assertions.assertNotNull(lombokDestination);
    Assertions.assertEquals(simpleSource.getName(), lombokDestination.getName());
    Assertions.assertEquals(simpleSource.getDescription(), lombokDestination.getDescription());
}

正如我們可以在上面的測試用例中驗證的那樣,對映器實現成功地將源 POJO 對映到兩個目標 POJO。

結論
在本文中,我們研究瞭如何結合使用 MapStruct 和 Lombok 來幫助我們減少樣板程式碼的編寫,從而增強程式碼的可讀性並提高開發過程的效率。

相關文章