在專案開發當中,很多軟體架構都會做一些物件上的資料轉換

最常見的是,往往我們會需要把 Entity 的物件轉換成對應的 DTO 物件給前端

最簡單也最常見的寫法就是依序把 Entity 的 value 用 get method 取出來用再用 DTO 物件的 set method 把資料塞進去

但其實有時候寫著寫著也是覺得很麻煩,也挺累的,有時候寫起來程式也臭臭長長的看了就討厭

所以今天要介紹的是使用 MapStruct 這個工具來幫我們快速地進行資料上的轉換,以加快我們的開發速度

 

首先必須在 Sprint Boot 的專案當中加入對應的依賴

如果是Maven專案的話 pom.xml 可以參考以下設定

因為我們專案當中也使用到了 lombok,所以我們必須透過一些設定確保 lombok 和 mapStruct 是可以同時使用的

 

那如果使用 Gradle 的話設定就相對單純,可以參考如下

 

Entity 和 DTO 的欄位一模一樣

首先我們針對一個最常見,也最簡單的情境來示範 MapStruct 的轉換

我們有一個 People 的 Entity 物件,如下

然後我們有一個 PeopleDto 物件

我們如果要把 People 轉換成 PeopleDto,我們就建立一個 Mapper 如下

因為 People 和 PeopleDto 的欄位成員變數名稱全部都一樣,所以這樣寫就能夠做轉換了

那接著我們就寫一個單元測試來驗證這件事情

這樣執行測試後,就能pass這個測試案例了

 

DTO的欄位需要客製化轉換

接下來第二種情境也很常見,當我們要將 Entity 物件轉換成 DTO 時,可能需要做一些處理才能符合DTO要的格式或需求

以下範例 People 物件有一個 updateTime 是 OffsetDateTime 的型別,而 PeopleDto 的 updateTime 型別是 Long

也就是說這邊的需求是要將時間格式轉換成毫秒的形式提供Client使用

那我們就可以把Mapper調整成如下

targer指的是目標轉換欄位名稱,以我們這邊的案例就是 PeopleDto 物件的 updateTime欄位

source指的是來源欄位名稱,我們就是要用來源資料做加工處理,以我們這邊的案例就是 People 物件的 updateTime欄位

透過我們自定義的方法來實作客製化的轉換邏輯,以上面例子,就是透過 formatUpdateTime 來做轉換

接著一樣撰寫一個測試來驗證

DTO欄位資料透過其他物件組合

上面的範例都還是使用帶入的來源原始資料直接進行加工處理,

但有時候DTO物件的欄位是需要透過額外的物件來一起做資料處理組合出最終的結果

舉例來說,假設我們有一個 Map<Integer, String>,這個 Map 的 Key 是 People 的 id,而 value 則是我們要對應到 PeopleDto 的 name 的字串

所以狀況是,我們需要將 Map<Integer, String> 帶進去 toDto method,透過 id 去 Map 查詢對應的字串,對應的字串就是最後 PeopleDto 的 name

所以將PeopleMapper調整如下程式碼:

targer是 PeopleDto 物件的 name欄位

source是People 物件的 id 欄位

會透過我們自定義的 peopleName 使用 source (people.id) 和帶進來的 @Context 進行處理

對應的測試如下

這種情境比較常是拿著自己本身的id去關聯別的物件來做轉換

 

目標欄位由2個以上來源的欄位組合

當我們需要將來源物件兩個以上的資料帶進去我們自定義的轉換介面時,可以參考如下範例作法

承上面範例,我們這次一樣會帶入Map<Integer, String>,而最後的 PeopleDto 的 name 是由 People 的 name 去 append 使用 People 的 id 去Map查到對應的 value

這時候我們的 peopleName 這個方法就必須帶入兩個參數,People 的 id 和 name,程式寫法參考如下

測試如下,可以看到 peopleDto.getName() 取出來的資料應該要是 "John Doe 第一筆資料"

結語

以上示範了幾種常見的 MapStruct 常見的用法,大多情境都可以根據自己的狀況再去調整

arrow
arrow
    創作者介紹
    創作者 Mark Zhang 的頭像
    Mark Zhang

    讀處

    Mark Zhang 發表在 痞客邦 留言(0) 人氣()