使用MapStruct進行Java Bean映射的方式
使用MapStruct進行Java Bean映射的指南
簡介
MapStruct 是一個用于 Java Bean 映射的注解處理器。它通過注解生成類型安全且性能優(yōu)異的映射代碼,避免手動編寫重復的樣板代碼,適用于將一個 Java Bean 類型轉(zhuǎn)換為另一個 Java Bean 類型。
MapStruct的主要特性
- 類型安全: 在編譯時生成映射代碼,避免運行時錯誤。
- 高性能: 生成的代碼是純 Java 代碼,沒有反射機制,性能非常高。
- 簡潔: 減少了大量樣板代碼,開發(fā)者只需定義接口,MapStruct 自動生成實現(xiàn)。
- 可定制性: 支持自定義映射、默認值、轉(zhuǎn)換方法等。
依賴配置
使用 MapStruct 需要添加相應的依賴。以 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)建一個接口,并使用 @Mapper 注解標記它。
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.ReportingPolicy;
import org.mapstruct.factory.Mappers;
/**
* CarMapper 接口定義了 Car 和 CarDto 之間的映射關(guān)系。
* 使用 @Mapper 注解標記接口,并設(shè)置 typeConversionPolicy 為 ReportingPolicy.ERROR,
* 以確保類型轉(zhuǎn)換不正確時編譯報錯。
*/
@Mapper(typeConversionPolicy = ReportingPolicy.ERROR)
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
/**
* 將 Car 實體映射為 CarDto。
* @param car 源 Car 對象
* @return 映射后的 CarDto 對象
*/
@Mapping(source = "numberOfSeats", target = "seatCount")
@Mapping(source = "engine.type", target = "engineType")
CarDto carToCarDto(Car car);
}定義源類和目標類
/**
* Car 實體類
*/
public class Car {
private String make; // 制造商
private int numberOfSeats; // 座位數(shù)
private Engine engine; // 引擎
// getters 和 setters
}
/**
* CarDto 數(shù)據(jù)傳輸對象
*/
public class CarDto {
private String make; // 制造商
private int seatCount; // 座位數(shù)
private String engineType; // 引擎類型
// getters 和 setters
}
/**
* Engine 實體類
*/
public class Engine {
private String type; // 引擎類型
// getters 和 setters
}生成映射代碼
使用構(gòu)建工具(如 Maven 或 Gradle)執(zhí)行構(gòu)建過程,MapStruct 將根據(jù)接口定義生成相應的映射實現(xiàn)類。
/**
* CarMapper 的實現(xiàn)類,由 MapStruct 自動生成。
*/
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 實體映射為 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);
}
}深拷貝和淺拷貝
- 淺拷貝: 復制對象的基本數(shù)據(jù)類型屬性和引用類型屬性的引用,引用類型屬性本身并沒有被復制。
- 深拷貝: 復制對象的所有屬性,包括引用類型屬性所引用的對象本身。
MapStruct 默認進行淺拷貝,即引用類型屬性在目標對象中會引用源對象的相同實例。如果需要進行深拷貝,可以手動編寫自定義映射方法。
集合拷貝
MapStruct 可以自動處理集合類型的映射。例如:
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 注解標記接口,并設(shè)置 typeConversionPolicy 為 ReportingPolicy.ERROR,
* 以確保類型轉(zhuǎn)換不正確時編譯報錯。
*/
@Mapper(typeConversionPolicy = ReportingPolicy.ERROR)
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
/**
* 將 Car 實體映射為 CarDto。
* @param car 源 Car 對象
* @return 映射后的 CarDto 對象
*/
@Mapping(source = "numberOfSeats", target = "seatCount")
@Mapping(source = "engine.type", target = "engineType")
CarDto carToCarDto(Car car);
/**
* 將 Car 實體列表映射為 CarDto 列表。
* @param cars 源 Car 對象列表
* @return 映射后的 CarDto 對象列表
*/
List<CarDto> carsToCarDtos(List<Car> cars);
}編譯時錯誤處理
MapStruct 在編譯時進行類型檢查,如果映射不正確,會拋出編譯錯誤??梢允褂?@Mapper 注解的 typeConversionPolicy 屬性來配置在類型轉(zhuǎn)換過程中遇到錯誤時的行為,例如 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 注解標記接口,并設(shè)置 typeConversionPolicy 為 ReportingPolicy.ERROR,
* 以確保類型轉(zhuǎn)換不正確時編譯報錯。
*/
@Mapper(typeConversionPolicy = ReportingPolicy.ERROR)
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
/**
* 將 Car 實體映射為 CarDto。
* @param car 源 Car 對象
* @return 映射后的 CarDto 對象
*/
@Mapping(source = "numberOfSeats", target = "seatCount")
CarDto carToCarDto(Car car);
}在上述示例中,如果類型轉(zhuǎn)換不正確或者無法轉(zhuǎn)換,編譯時將會報錯,從而確保所有類型轉(zhuǎn)換都得到正確處理。
完整示例與文檔生成
以下是一個完整的示例,包括源代碼和生成的映射代碼,以及如何生成文檔。
源代碼
源類和目標類:
/**
* Car 實體類
*/
public class Car {
private String make; // 制造商
private int numberOfSeats; // 座位數(shù)
private Engine engine; // 引擎
// getters 和 setters
}
/**
* CarDto 數(shù)據(jù)傳輸對象
*/
public class CarDto {
private String make; // 制造商
private int seatCount; // 座位數(shù)
private String engineType; // 引擎類型
// getters 和 setters
}
/**
* Engine 實體類
*/
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 注解標記接口,并設(shè)置 typeConversionPolicy 為 ReportingPolicy.ERROR,
* 以確保類型轉(zhuǎn)換不正確時編譯報錯。
*/
@Mapper(typeConversionPolicy = ReportingPolicy.ERROR)
public interface CarMapper {
CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
/**
* 將 Car 實
體映射為 CarDto。
* @param car 源 Car 對象
* @return 映射后的 CarDto 對象
*/
@Mapping(source = "numberOfSeats", target = "seatCount")
@Mapping(source = "engine.type", target = "engineType")
CarDto carToCarDto(Car car);
/**
* 將 Car 實體列表映射為 CarDto 列表。
* @param cars 源 Car 對象列表
* @return 映射后的 CarDto 對象列表
*/
List<CarDto> carsToCarDtos(List<Car> cars);
}生成的映射代碼
MapStruct 將自動生成如下實現(xiàn)類:
/**
* CarMapper 的實現(xiàn)類,由 MapStruct 自動生成。
*/
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
生成的文檔將包含所有類和接口的詳細說明,包括字段、方法和注釋。
總結(jié)
通過本指南,你可以了解 MapStruct 的基本特性、如何配置依賴、使用步驟、深拷貝和淺拷貝的區(qū)別、集合類型的映射以及如何處理編譯時錯誤。
MapStruct 能極大地提高代碼的可維護性和性能,是進行 Java Bean 映射的有力工具。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)于java.io.EOFException產(chǎn)生的原因以及解決方案
文章總結(jié):EOFException異常通常發(fā)生在嘗試從空的ObjectInputStream對象中讀取數(shù)據(jù)時,解決方法是在finally語句中添加判斷,確保objectInputStream不為空后再進行關(guān)閉操作,在處理1.txt文件為空的情況時,捕獲EOFException可以避免程序終止,并且不會拋出空指針異常2025-01-01
SpringBoot配置logback.xml 多環(huán)境的操作步驟
最近在研究springboot的日志,所以記錄一下,做一下總結(jié),今天重點給大家介紹SpringBoot配置logback.xml 多環(huán)境的操作步驟,要實現(xiàn)多環(huán)境的配置,主要是依賴于springboot的application.yml文件去實現(xiàn),感興趣的朋友跟隨小編一起看看吧2021-05-05
SpringBoot+MyBatis-Plus進行分頁查詢與優(yōu)化
這篇文章主要為大家詳細介紹了SpringBoot如何整合MyBatis-Plus進行分頁查詢與優(yōu)化,文中的示例代碼講解詳細,感興趣的小伙伴可以參考一下2025-04-04
SpringBoot中@ConditionalOnProperty的使用及作用詳解
這篇文章主要介紹了SpringBoot中@ConditionalOnProperty的使用及作用詳解,@ConditionalOnProperty通過讀取本地配置文件中的值來判斷 某些 Bean 或者 配置類 是否加入spring 中,需要的朋友可以參考下2024-01-01

