使用 Mapstruct 將可迭代物件映射到包含可迭代物件的對象
一、簡介
在本教程中,我們將探討一個有趣的 Java 問題:使用MapStruct將Iterable
對應到包含Iterable
物件。
MapStruct 是一個 Java 函式庫,它簡化了不同物件模型之間的映射過程。然而,它也有其限制。本教學假設我們已經對 MapStruct 有基本的了解。如果沒有,我們建議從快速指南開始,以熟悉其基本用法。
2.了解用例
讓我們從一個簡單的例子開始來解釋這個場景。考慮一個Employee
物件清單和一個包含員工清單的Department
物件。我們將從創建這些類別開始:
public class Employee {
private String name;
private String phoneNumber;
// getters and setters
}
public class Department {
private List<Employee> employees;
// getters and setters
}
現在,假設我們想要將Employee
物件清單對應到Department
。我們將創建一個接口,將其標記為映射器,並創建一個使用@Mapping
註釋進行註釋的方法:
@Mapper
public interface DepartmentMapper {
@Mapping(target = "employees", source = "employees")
Department map(List<Employee> employees);
}
在上面的程式碼中,我們直觀地嘗試將來源定義為員工的輸入列表,將目標定義為Department
類別的員工。儘管這看起來是一種簡單的方法,但我們會遇到一個錯誤,導致程式碼無法編譯。為了解決這個問題,我們需要調整我們的方法以確保來源類型與目標類型一致。
3. 將Iterable
類型對應到不可Iterable
類型
讓我們透過查看 MapStruct 拋出的錯誤來了解此問題的根本原因:
java: Can't generate mapping method from iterable type from java stdlib to non-iterable type.
上面的錯誤表示我們正在嘗試映射可迭代類型(例如List
、 Set,
或標準 Java 庫中的任何Collection
)和不可迭代類型(單一物件或原始類型)。此類映射不受本機支持,需要額外的上下文或特定指令。
有幾個實際原因導致 JVM 和 MapStruct 函式庫無法獨立解決:
- 如何匹配來源和目標之間的元素
- 是否刪除或新增不符的元素
- 如何處理多個匹配
此外,我們還需要考慮如何保持元素的正確排序。
4、解決方案
當使用 MapStruct 將可迭代類型對應到不可迭代類型時,沒有簡單、通用的解決方案。然而,有一些實用的解決方法可以幫助我們實現預期的結果。
4.1.預設介面方法
第一種方法涉及在映射器中建立預設介面方法。此方法將透過取得可迭代物件並將其設定為目標物件中的欄位值來手動處理轉換。透過這樣做,我們確保映射按預期進行處理。
讓我們在實踐中看看這種方法:
default Department map(List<Employee> employees) {
Department department = new Department();
department.setEmployees(employees);
return department;
}
4.2.多種來源
另一種方法涉及透過添加附加參數來改變映射方法。當我們引入另一個參數時,MapStruct 會為我們想要完成的任務獲得更好的背景資訊。換句話說,擁有多個參數意味著我們有多個來源,因此可以更輕鬆地識別需要映射的內容。
首先,讓我們向Department
類別引入一個新屬性。此參數的類型為名為manager
Employee
:
public class Department {
private List<Employee> employees;
private Employee manager;
// omitted getters and setters
}
接下來,讓我們建立一個包含此參數作為來源的映射方法:
@Mapping(target = "employees", source = "employees")
@Mapping(target = "manager", source = "departmentManager")
Department mapWithManager(List<Employee> employees, Employee departmentManager);
由於我們不再嘗試將可迭代類型對應到不可迭代類型,因此映射按預期工作。 MapStruct 函式庫現在有足夠的上下文來產生映射器實現,這就是為什麼在程式碼編譯步驟期間不會拋出錯誤。
請注意,儘管這種方法乾淨且實用,但它是針對特定情況的。我們並不總是能夠添加新參數以支援映射。
5. 結論
在本文中,我們討論了使用 MapStruct 將可迭代物件對應到包含可迭代類型的物件所涉及的挑戰和解決方案。儘管 MapStruct 是一個強大的物件映射工具,但它也有局限性,需要其他方法。
我們探索了幾種處理這些場景的方法,包括添加預設介面方法,使我們能夠完全控制映射過程。此外,我們注意到,雖然多來源映射不會遇到本文中提到的問題,但它並不是對每個用例都有幫助的方法。
與往常一樣,完整的程式碼範例可以在 GitHub 上找到。