mapstruct优雅bean转换

虾米姐 阅读:811 2021-04-01 11:04:45 评论:0

bean复制两个类字段一直时可以使用BeanUtils.copyProperties(source, target);如果字段不一致可以使用mapstruct框架转换
1.pom文件

	<dependency> 
		<groupId>org.mapstruct</groupId> 
		<!-- jdk8以下就使用mapstruct --> 
		<artifactId>mapstruct-jdk8</artifactId> 
		<version>1.2.0.Final</version> 
	</dependency> 
	<dependency> 
		<groupId>org.mapstruct</groupId> 
		<artifactId>mapstruct-processor</artifactId> 
		<version>1.2.0.Final</version> 
	</dependency> 

2.创建数据库PO:BasDevicePO类文件

@Data 
@EqualsAndHashCode(callSuper = false) 
@Accessors(chain = true) 
@TableName("bas_device") 
public class BasDevicePO extends BasePO implements Serializable { 
 
	private static final long serialVersionUID = 1L; 
 
	/** 
	 * 设备ID 
	 */ 
	@NotBlank(message="设备ID不能为空", groups = {AddGroup.class}) 
	@TableId(value = "device_id") 
	private String deviceId; 
 
	/** 
	 * 设备名称 
	 */ 
	private String name; 
	/** 
	 * 刷机批次 
	 */ 
	private Integer flashSn; 
 
	/** 
	 * 状态 ≤0=禁用,>0=正常 
	 */ 
	private Integer status; 
 
	/** 
	 * 原始ID 通信协议中的设备ID 
	 */ 
	@NotBlank(message="原始设备ID不能为空", groups = {AddGroup.class,UpdateGroup.class}) 
	private String oriDevId; 
 
	/** 
	 * 附近国控站 用于设备校准 
	 */ 
	@NotBlank(message="附近监测站ID不能为空", groups = {AddGroup.class}) 
	private String stationId; 
 
	/** 
	 * 经度坐标 
	 */ 
	private BigDecimal gpsX; 
 
	/** 
	 * 纬度坐标 
	 */ 
	private BigDecimal gpsY; 
 
	/** 校准参数;JSON格式。类似:{"pm25":[1,2,3,4,5],...} */ 
	private String calibParam; 
	 
    /** 线性参数;JSON格式,某个监测参数可能没有。值依次为系数、k1、b1、k2、b2。类似:{"pm25":[1000,1,0,0,0],...} */ 
    private String linearParam; 
 
	/** 
	 * 备注 
	 */ 
	private String memo; 
	private String address; 
	/** 
	 * 创建时间 
	 */ 
	private LocalDateTime createTime; 
 
} 
 

3.创建用于前端页面展示对象VO : DeviceVO类文件 (PO中name对应VO中deviceName)

@Data 
public class DeviceVO{ 
 
	private static final long serialVersionUID = 1L; 
 
	/** 
	 * 设备ID 
	 */ 
	@NotBlank(message="设备ID不能为空", groups = {AddGroup.class}) 
	@TableId(value = "device_id") 
	private String deviceId; 
 
	/** 
	 * 设备名称 
	 */ 
	private String deviceName; 
	/** 
	 * 刷机批次 
	 */ 
	private Integer flashSn; 
 
	/** 
	 * 状态 ≤0=禁用,>0=正常 
	 */ 
	private Integer status; 
 
	/** 
	 * 原始ID 通信协议中的设备ID 
	 */ 
	@NotBlank(message="原始设备ID不能为空", groups = {AddGroup.class,UpdateGroup.class}) 
	private String oriDevId; 
 
	/** 
	 * 附近国控站 用于设备校准 
	 */ 
	@NotBlank(message="附近监测站ID不能为空", groups = {AddGroup.class}) 
	private String stationId; 
 
	/** 
	 * 经度坐标 
	 */ 
	private BigDecimal gpsX; 
 
	/** 
	 * 纬度坐标 
	 */ 
	private BigDecimal gpsY; 
 
	/** 校准参数;JSON格式。类似:{"pm25":[1,2,3,4,5],...} */ 
	private String calibParam; 
	 
    /** 线性参数;JSON格式,某个监测参数可能没有。值依次为系数、k1、b1、k2、b2。类似:{"pm25":[1000,1,0,0,0],...} */ 
    private String linearParam; 
 
	/** 
	 * 备注 
	 */ 
	private String memo; 
	private String address; 
	/** 
	 * 创建时间 
	 */ 
	private LocalDateTime createTime; 
 
} 

4.创建转换接口

@Mapper 
public interface MyConvert { 
	MyConvert INSTANCE = Mappers.getMapper(MyConvert.class);	     
	@Mapping(source = "name", target = "deviceName") 
	//如果多个字段不同可以这样 
	//@Mappings({ 
	//	@Mapping(source = "name", target = "deviceName"), 
	//	@Mapping(source = "stationId", target = "statId") 
	//}) 
	DeviceVO toConvertVo(BasDevicePO source); 
} 

5.clean compile 编译 生成转换实现类位置在target/generated-sources/annotations下

@Generated( 
    value = "org.mapstruct.ap.MappingProcessor", 
    date = "2020-10-12T17:31:54+0800", 
    comments = "version: 1.2.0.Final, compiler: javac, environment: Java 1.8.0_31 (Oracle Corporation)" 
) 
public class MyConvertImpl implements MyConvert { 
 
    @Override 
    public DeviceVO toConvertVo(BasDevicePO source) { 
        if ( source == null ) { 
            return null; 
        } 
 
        DeviceVO deviceVO = new DeviceVO(); 
 
        deviceVO.setDeviceName( source.getName() ); 
        deviceVO.setDeviceId( source.getDeviceId() ); 
        deviceVO.setFlashSn( source.getFlashSn() ); 
        deviceVO.setStatus( source.getStatus() ); 
        deviceVO.setOriDevId( source.getOriDevId() ); 
        deviceVO.setStationId( source.getStationId() ); 
        deviceVO.setGpsX( source.getGpsX() ); 
        deviceVO.setGpsY( source.getGpsY() ); 
        deviceVO.setCalibParam( source.getCalibParam() ); 
        deviceVO.setLinearParam( source.getLinearParam() ); 
        deviceVO.setMemo( source.getMemo() ); 
        deviceVO.setAddress( source.getAddress() ); 
        deviceVO.setCreateTime( source.getCreateTime() ); 
 
        return deviceVO; 
    } 
} 

6.测试代码

	@GetMapping("/test") 
	@ApiOperation(value = "获取微站报警数据-设备信息及最后一条数据时间", notes = "") 
	public CommonResponse<Object> test( 
			@ApiParam(name="deviceId", value = "设备id逗号分隔", defaultValue="002", required=true) @RequestParam String deviceId) 
	{ 
		CommonResponse<Object> resp = new CommonResponse<>(); 
		BasDevicePO basDevicePO = basDeviceService.getById(deviceId); 
		DeviceVO convertVo = MyConvert.INSTANCE.toConvertVo(basDevicePO); 
		resp.setData(convertVo); 
		return resp; 
	} 

7.运行结果
在这里插入图片描述
8.如果集合对象转换只需在接口中添加方法

@Mapper 
public interface MyConvert { 
	MyConvert INSTANCE =  
			    Mappers.getMapper(MyConvert.class); 
	@Mapping(source = "name", target = "deviceName")		     
	DeviceVO toConvertVo(BasDevicePO source); 
	List<DeviceVO> toConvertVoList(List<BasDevicePO> source); 
} 

9.再次clean compile
发现toConvertVoList方法循环调用toConvertVo方法

@Generated( 
    value = "org.mapstruct.ap.MappingProcessor", 
    date = "2020-10-12T17:35:19+0800", 
    comments = "version: 1.2.0.Final, compiler: javac, environment: Java 1.8.0_31 (Oracle Corporation)" 
) 
public class MyConvertImpl implements MyConvert { 
 
    @Override 
    public DeviceVO toConvertVo(BasDevicePO source) { 
        if ( source == null ) { 
            return null; 
        } 
 
        DeviceVO deviceVO = new DeviceVO(); 
 
        deviceVO.setDeviceName( source.getName() ); 
        deviceVO.setDeviceId( source.getDeviceId() ); 
        deviceVO.setFlashSn( source.getFlashSn() ); 
        deviceVO.setStatus( source.getStatus() ); 
        deviceVO.setOriDevId( source.getOriDevId() ); 
        deviceVO.setStationId( source.getStationId() ); 
        deviceVO.setGpsX( source.getGpsX() ); 
        deviceVO.setGpsY( source.getGpsY() ); 
        deviceVO.setCalibParam( source.getCalibParam() ); 
        deviceVO.setLinearParam( source.getLinearParam() ); 
        deviceVO.setMemo( source.getMemo() ); 
        deviceVO.setAddress( source.getAddress() ); 
        deviceVO.setCreateTime( source.getCreateTime() ); 
 
        return deviceVO; 
    } 
 
    @Override 
    public List<DeviceVO> toConvertVoList(List<BasDevicePO> source) { 
        if ( source == null ) { 
            return null; 
        } 
 
        List<DeviceVO> list = new ArrayList<DeviceVO>( source.size() ); 
        for ( BasDevicePO basDevicePO : source ) { 
            list.add( toConvertVo( basDevicePO ) ); 
        } 
 
        return list; 
    } 
} 
 

10.测试代码

	@GetMapping("/test") 
	@ApiOperation(value = "获取微站报警数据-设备信息及最后一条数据时间", notes = "") 
	public CommonResponse<Object> test( 
			@ApiParam(name="deviceId", value = "设备id逗号分隔", defaultValue="002", required=true) @RequestParam String deviceId) 
	{ 
		CommonResponse<Object> resp = new CommonResponse<>(); 
		List<BasDevicePO> list = basDeviceService.list(); 
		List<DeviceVO> convertVoList = MyConvert.INSTANCE.toConvertVoList(list); 
		resp.setData(convertVoList); 
		return resp; 
	} 

11.运行结果
在这里插入图片描述
12.字段类型不一致
PO

private LocalDateTime createTime; 

VO

private String createTime; 

修改转换接口

@Mapping(target = "createTime", expression  = "java(bw.sjjz.svc.util.AppDateUtil.localDateTimeToStr(source.getCreateTime()))") 

时间转换方法

	public static String localDateTimeToStr(LocalDateTime time) 
	{ 
		DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");	 
		return ofPattern.format(time); 
	} 

运行结果
在这里插入图片描述

声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号