使用MapStruct進(jìn)行Java Bean映射的方式
使用MapStruct進(jìn)行Java Bean映射的指南
簡(jiǎn)介
MapStruct 是一個(gè)用于 Java Bean 映射的注解處理器。它通過注解生成類型安全且性能優(yōu)異的映射代碼,避免手動(dòng)編寫重復(fù)的樣板代碼,適用于將一個(gè) Java Bean 類型轉(zhuǎn)換為另一個(gè) Java Bean 類型。
MapStruct的主要特性
- 類型安全: 在編譯時(shí)生成映射代碼,避免運(yùn)行時(shí)錯(cuò)誤。
- 高性能: 生成的代碼是純 Java 代碼,沒有反射機(jī)制,性能非常高。
- 簡(jiǎn)潔: 減少了大量樣板代碼,開發(fā)者只需定義接口,MapStruct 自動(dòng)生成實(shí)現(xiàn)。
- 可定制性: 支持自定義映射、默認(rèn)值、轉(zhuǎn)換方法等。
依賴配置
使用 MapStruct 需要添加相應(yīng)的依賴。以 Maven 為例:
<dependencies> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.5.0.Final</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.5.0.Final</version> <scope>provided</scope> </dependency> </dependencies>
如果使用 Gradle:
dependencies { implementation 'org.mapstruct:mapstruct:1.5.0.Final' annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.0.Final' }
MapStruct的使用步驟
定義映射接口
創(chuàng)建一個(gè)接口,并使用 @Mapper
注解標(biāo)記它。
import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.ReportingPolicy; import org.mapstruct.factory.Mappers; /** * CarMapper 接口定義了 Car 和 CarDto 之間的映射關(guān)系。 * 使用 @Mapper 注解標(biāo)記接口,并設(shè)置 typeConversionPolicy 為 ReportingPolicy.ERROR, * 以確保類型轉(zhuǎn)換不正確時(shí)編譯報(bào)錯(cuò)。 */ @Mapper(typeConversionPolicy = ReportingPolicy.ERROR) public interface CarMapper { CarMapper INSTANCE = Mappers.getMapper(CarMapper.class); /** * 將 Car 實(shí)體映射為 CarDto。 * @param car 源 Car 對(duì)象 * @return 映射后的 CarDto 對(duì)象 */ @Mapping(source = "numberOfSeats", target = "seatCount") @Mapping(source = "engine.type", target = "engineType") CarDto carToCarDto(Car car); }
定義源類和目標(biāo)類
/** * Car 實(shí)體類 */ public class Car { private String make; // 制造商 private int numberOfSeats; // 座位數(shù) private Engine engine; // 引擎 // getters 和 setters } /** * CarDto 數(shù)據(jù)傳輸對(duì)象 */ public class CarDto { private String make; // 制造商 private int seatCount; // 座位數(shù) private String engineType; // 引擎類型 // getters 和 setters } /** * Engine 實(shí)體類 */ public class Engine { private String type; // 引擎類型 // getters 和 setters }
生成映射代碼
使用構(gòu)建工具(如 Maven 或 Gradle)執(zhí)行構(gòu)建過程,MapStruct 將根據(jù)接口定義生成相應(yīng)的映射實(shí)現(xiàn)類。
/** * CarMapper 的實(shí)現(xiàn)類,由 MapStruct 自動(dòng)生成。 */ public class CarMapperImpl implements CarMapper { @Override public CarDto carToCarDto(Car car) { if (car == null) { return null; } CarDto carDto = new CarDto(); carDto.setMake(car.getMake()); carDto.setSeatCount(car.getNumberOfSeats()); if (car.getEngine() != null) { carDto.setEngineType(car.getEngine().getType()); } return carDto; } }
調(diào)用映射方法
/** * 演示如何使用 CarMapper 將 Car 實(shí)體映射為 CarDto。 */ public class Main { public static void main(String[] args) { Car car = new Car(); car.setMake("Toyota"); car.setNumberOfSeats(5); Engine engine = new Engine(); engine.setType("V8"); car.setEngine(engine); CarDto carDto = CarMapper.INSTANCE.carToCarDto(car); System.out.println(carDto); } }
深拷貝和淺拷貝
- 淺拷貝: 復(fù)制對(duì)象的基本數(shù)據(jù)類型屬性和引用類型屬性的引用,引用類型屬性本身并沒有被復(fù)制。
- 深拷貝: 復(fù)制對(duì)象的所有屬性,包括引用類型屬性所引用的對(duì)象本身。
MapStruct 默認(rèn)進(jìn)行淺拷貝,即引用類型屬性在目標(biāo)對(duì)象中會(huì)引用源對(duì)象的相同實(shí)例。如果需要進(jìn)行深拷貝,可以手動(dòng)編寫自定義映射方法。
集合拷貝
MapStruct 可以自動(dòng)處理集合類型的映射。例如:
import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.ReportingPolicy; import org.mapstruct.factory.Mappers; import java.util.List; /** * CarMapper 接口定義了 Car 和 CarDto 之間的映射關(guān)系。 * 使用 @Mapper 注解標(biāo)記接口,并設(shè)置 typeConversionPolicy 為 ReportingPolicy.ERROR, * 以確保類型轉(zhuǎn)換不正確時(shí)編譯報(bào)錯(cuò)。 */ @Mapper(typeConversionPolicy = ReportingPolicy.ERROR) public interface CarMapper { CarMapper INSTANCE = Mappers.getMapper(CarMapper.class); /** * 將 Car 實(shí)體映射為 CarDto。 * @param car 源 Car 對(duì)象 * @return 映射后的 CarDto 對(duì)象 */ @Mapping(source = "numberOfSeats", target = "seatCount") @Mapping(source = "engine.type", target = "engineType") CarDto carToCarDto(Car car); /** * 將 Car 實(shí)體列表映射為 CarDto 列表。 * @param cars 源 Car 對(duì)象列表 * @return 映射后的 CarDto 對(duì)象列表 */ List<CarDto> carsToCarDtos(List<Car> cars); }
編譯時(shí)錯(cuò)誤處理
MapStruct 在編譯時(shí)進(jìn)行類型檢查,如果映射不正確,會(huì)拋出編譯錯(cuò)誤??梢允褂?@Mapper
注解的 typeConversionPolicy
屬性來配置在類型轉(zhuǎn)換過程中遇到錯(cuò)誤時(shí)的行為,例如 ReportingPolicy.ERROR
。
import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.ReportingPolicy; import org.mapstruct.factory.Mappers; /** * CarMapper 接口定義了 Car 和 CarDto 之間的映射關(guān)系。 * 使用 @Mapper 注解標(biāo)記接口,并設(shè)置 typeConversionPolicy 為 ReportingPolicy.ERROR, * 以確保類型轉(zhuǎn)換不正確時(shí)編譯報(bào)錯(cuò)。 */ @Mapper(typeConversionPolicy = ReportingPolicy.ERROR) public interface CarMapper { CarMapper INSTANCE = Mappers.getMapper(CarMapper.class); /** * 將 Car 實(shí)體映射為 CarDto。 * @param car 源 Car 對(duì)象 * @return 映射后的 CarDto 對(duì)象 */ @Mapping(source = "numberOfSeats", target = "seatCount") CarDto carToCarDto(Car car); }
在上述示例中,如果類型轉(zhuǎn)換不正確或者無法轉(zhuǎn)換,編譯時(shí)將會(huì)報(bào)錯(cuò),從而確保所有類型轉(zhuǎn)換都得到正確處理。
完整示例與文檔生成
以下是一個(gè)完整的示例,包括源代碼和生成的映射代碼,以及如何生成文檔。
源代碼
源類和目標(biāo)類:
/** * Car 實(shí)體類 */ public class Car { private String make; // 制造商 private int numberOfSeats; // 座位數(shù) private Engine engine; // 引擎 // getters 和 setters } /** * CarDto 數(shù)據(jù)傳輸對(duì)象 */ public class CarDto { private String make; // 制造商 private int seatCount; // 座位數(shù) private String engineType; // 引擎類型 // getters 和 setters } /** * Engine 實(shí)體類 */ public class Engine { private String type; // 引擎類型 // getters 和 setters }
映射接口:
import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.ReportingPolicy; import org.mapstruct.factory.Mappers; import java.util.List; /** * CarMapper 接口定義了 Car 和 CarDto 之間的映射關(guān)系。 * 使用 @Mapper 注解標(biāo)記接口,并設(shè)置 typeConversionPolicy 為 ReportingPolicy.ERROR, * 以確保類型轉(zhuǎn)換不正確時(shí)編譯報(bào)錯(cuò)。 */ @Mapper(typeConversionPolicy = ReportingPolicy.ERROR) public interface CarMapper { CarMapper INSTANCE = Mappers.getMapper(CarMapper.class); /** * 將 Car 實(shí) 體映射為 CarDto。 * @param car 源 Car 對(duì)象 * @return 映射后的 CarDto 對(duì)象 */ @Mapping(source = "numberOfSeats", target = "seatCount") @Mapping(source = "engine.type", target = "engineType") CarDto carToCarDto(Car car); /** * 將 Car 實(shí)體列表映射為 CarDto 列表。 * @param cars 源 Car 對(duì)象列表 * @return 映射后的 CarDto 對(duì)象列表 */ List<CarDto> carsToCarDtos(List<Car> cars); }
生成的映射代碼
MapStruct 將自動(dòng)生成如下實(shí)現(xiàn)類:
/** * CarMapper 的實(shí)現(xiàn)類,由 MapStruct 自動(dòng)生成。 */ public class CarMapperImpl implements CarMapper { @Override public CarDto carToCarDto(Car car) { if (car == null) { return null; } CarDto carDto = new CarDto(); carDto.setMake(car.getMake()); carDto.setSeatCount(car.getNumberOfSeats()); if (car.getEngine() != null) { carDto.setEngineType(car.getEngine().getType()); } return carDto; } @Override public List<CarDto> carsToCarDtos(List<Car> cars) { if (cars == null) { return null; } List<CarDto> list = new ArrayList<>(cars.size()); for (Car car : cars) { list.add(carToCarDto(car)); } return list; } }
生成文檔
可以使用 Javadoc 工具生成文檔,示例如下:
javadoc -d doc -sourcepath src/main/java -subpackages com.example
生成的文檔將包含所有類和接口的詳細(xì)說明,包括字段、方法和注釋。
總結(jié)
通過本指南,你可以了解 MapStruct 的基本特性、如何配置依賴、使用步驟、深拷貝和淺拷貝的區(qū)別、集合類型的映射以及如何處理編譯時(shí)錯(cuò)誤。
MapStruct 能極大地提高代碼的可維護(hù)性和性能,是進(jìn)行 Java Bean 映射的有力工具。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
JSON反序列化Long變Integer或Double的問題及解決
這篇文章主要介紹了JSON反序列化Long變Integer或Double的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01Java Flink窗口觸發(fā)器Trigger的用法詳解
Trigger(窗口觸發(fā)器)決定了窗口(由 WindowAssigner 產(chǎn)生)什么時(shí)候調(diào)用窗口處理函數(shù)??梢愿鶕?jù)指定的時(shí)間或數(shù)據(jù)元素條件來決定什么時(shí)候觸發(fā)。本文將詳細(xì)講講其用法,需要的可以參考一下2022-07-07Spring MVC學(xué)習(xí)教程之視圖深入解析
這篇文章主要給大家介紹了關(guān)于Spring MVC學(xué)習(xí)教程之視圖解析的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或使用spring mvc具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧2018-11-11Java利用LocalDate進(jìn)行日期處理的完全指南
這篇文章主要為大家詳細(xì)介紹了Java利用LocalDate進(jìn)行日期處理的詳細(xì)教程,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-03-03java 實(shí)現(xiàn)發(fā)短信功能---騰訊云短信
如今發(fā)短信功能已經(jīng)成為互聯(lián)網(wǎng)公司的標(biāo)配,接下來通過本文給大家介紹java 實(shí)現(xiàn)發(fā)短信功能---騰訊云短信 ,需要的朋友可以參考下2019-08-08java實(shí)現(xiàn)Dijkstra最短路徑算法
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)Dijkstra最短路徑算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01