使用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 映射的有力工具。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论