使用mapstruct进行java bean映射的指南
简介
mapstruct 是一个用于 java bean 映射的注解处理器。它通过注解生成类型安全且性能优异的映射代码,避免手动编写重复的样板代码,适用于将一个 java bean 类型转换为另一个 java bean 类型。
mapstruct的主要特性
- 类型安全: 在编译时生成映射代码,避免运行时错误。
- 高性能: 生成的代码是纯 java 代码,没有反射机制,性能非常高。
- 简洁: 减少了大量样板代码,开发者只需定义接口,mapstruct 自动生成实现。
- 可定制性: 支持自定义映射、默认值、转换方法等。
依赖配置
使用 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的使用步骤
定义映射接口
创建一个接口,并使用 @mapper 注解标记它。
import org.mapstruct.mapper;
import org.mapstruct.mapping;
import org.mapstruct.reportingpolicy;
import org.mapstruct.factory.mappers;
/**
* carmapper 接口定义了 car 和 cardto 之间的映射关系。
* 使用 @mapper 注解标记接口,并设置 typeconversionpolicy 为 reportingpolicy.error,
* 以确保类型转换不正确时编译报错。
*/
@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; // 座位数
private engine engine; // 引擎
// getters 和 setters
}
/**
* cardto 数据传输对象
*/
public class cardto {
private string make; // 制造商
private int seatcount; // 座位数
private string enginetype; // 引擎类型
// getters 和 setters
}
/**
* engine 实体类
*/
public class engine {
private string type; // 引擎类型
// getters 和 setters
}生成映射代码
使用构建工具(如 maven 或 gradle)执行构建过程,mapstruct 将根据接口定义生成相应的映射实现类。
/**
* carmapper 的实现类,由 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;
}
}调用映射方法
/**
* 演示如何使用 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);
}
}深拷贝和浅拷贝
- 浅拷贝: 复制对象的基本数据类型属性和引用类型属性的引用,引用类型属性本身并没有被复制。
- 深拷贝: 复制对象的所有属性,包括引用类型属性所引用的对象本身。
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 之间的映射关系。
* 使用 @mapper 注解标记接口,并设置 typeconversionpolicy 为 reportingpolicy.error,
* 以确保类型转换不正确时编译报错。
*/
@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 属性来配置在类型转换过程中遇到错误时的行为,例如 reportingpolicy.error。
import org.mapstruct.mapper;
import org.mapstruct.mapping;
import org.mapstruct.reportingpolicy;
import org.mapstruct.factory.mappers;
/**
* carmapper 接口定义了 car 和 cardto 之间的映射关系。
* 使用 @mapper 注解标记接口,并设置 typeconversionpolicy 为 reportingpolicy.error,
* 以确保类型转换不正确时编译报错。
*/
@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);
}在上述示例中,如果类型转换不正确或者无法转换,编译时将会报错,从而确保所有类型转换都得到正确处理。
完整示例与文档生成
以下是一个完整的示例,包括源代码和生成的映射代码,以及如何生成文档。
源代码
源类和目标类:
/**
* car 实体类
*/
public class car {
private string make; // 制造商
private int numberofseats; // 座位数
private engine engine; // 引擎
// getters 和 setters
}
/**
* cardto 数据传输对象
*/
public class cardto {
private string make; // 制造商
private int seatcount; // 座位数
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 之间的映射关系。
* 使用 @mapper 注解标记接口,并设置 typeconversionpolicy 为 reportingpolicy.error,
* 以确保类型转换不正确时编译报错。
*/
@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 将自动生成如下实现类:
/**
* carmapper 的实现类,由 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
生成的文档将包含所有类和接口的详细说明,包括字段、方法和注释。
总结
通过本指南,你可以了解 mapstruct 的基本特性、如何配置依赖、使用步骤、深拷贝和浅拷贝的区别、集合类型的映射以及如何处理编译时错误。
mapstruct 能极大地提高代码的可维护性和性能,是进行 java bean 映射的有力工具。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论