MapStruct的基本用法

目录

优点:

数据类型转换:

自定义映射:

list映射:

Map映射:

枚举映射:

使用表达式或默认值:

注意:

MapStruct 是一个 Java 注释处理器,用于生成类型安全的 bean 映射类。

优点:

  1. 与手动编写映射代码相比,MapStruct 通过生成编写繁琐且容易出错的代码来节省时间。
  2. 编译时类型安全:只能映射相互映射的对象和属性,不能将订单实体意外映射到客户 DTO 等。
  3. 当出现以下情况,程序在编译期间就会给出提示。

       映射不完整(并非所有目标属性都被映射)
       映射不正确(找不到合适的映射方法或类型转换)

数据类型转换:

基本数据类型的转换例如:int、long、String等会自动完成,不需要写Mapping映射关系。

指定格式的数据类型转换:

@Mapper
public interface DataFormatMapper {

    DataFormatMapper INSTANCE = Mappers.getMapper(DataFormatMapper.class);

    /**
     * numberFormat 指定基本数据类型与String之间的转换
     * dateFormat 指定Date和String之间的转换
     */
    @Mappings({
        	// 这里 # 表示多个数字,  0 表示一个数字(0-9)
            @Mapping(source = "price", target = "price", numberFormat = "#.00元"),
            @Mapping(source = "stock", target = "stock", numberFormat = "#个"),
            @Mapping(target = "saleTime", dateFormat = "yyyy-MM-dd HH:mm:ss"),
            @Mapping(target = "validTime", dateFormat = "yyyy-MM-dd HH:mm")
    })
    ProductDTO toDto(Product product);;
	
}

类中包含其他类的映射:

  1. 如果是类型相同的两个类,写映射关系后,是简单的浅拷贝(只拷贝引用),不会新建对象。
  2. 类型不同的话,如下
    分别是:User ---UserRoleDTO --- Role --- RoleDTO
    将User 转换成 UerRoleDTO:除了写一个User转UerRoleDTO的转换方法外,还要额外写一个 Role转成RoleDTO的转换方法,当执行User转UerRoleDTO时,会自动的调用这个Role转成RoleDTO的方法来生成对象

     // 这两个方法写在一起也行,分别写在两个接口里也行,执行时,都会自动调用
    	@Mapping(source = "userId", target = "id") // 把user中的userId绑定到目标对象的id属性中
        UserRoleDTO toUserRoleDto(User user);
    
    	// 当上面那个toUserRoleDto方法调用时,会自动调用这个方法来完成 User类中的Role 到 UserRoleDTO类中的RoleDTO  的转换
        @Mapping(source = "roleId", target = "id")
        RoleDTO toRoleDto(Role role);

自定义映射:

// 自定义的映射方法:转换boolen为String时,做一些判断然后返回对应的值。
@Named("DoneFormater")
public class DoneFormater {

    @Named("DoneFormater")
    public String toStr(Boolean isDone) {
        if (isDone) {
            return "已完成";
        } else {
            return "未完成";
        }
    }

    @Named("DoneDetailFormater")
    public String toDetail(Boolean isDone) {
        if (isDone) {
            return "该产品已完成";
        } else {
            return "该产品未完成";
        }
    }

    public Boolean toBoolean(String str) {
        if (str.equals("已完成")) {
            return true;
        } else {
            return false;
        }
    }

}

// 通过uses 来导入上面我们写的 自定义映射方法
@Mapper( uses = {DoneFormater.class})
public interface ObjectQualiferMapper {

    ObjectQualiferMapper INSTANCE = Mappers.getMapper(ObjectQualiferMapper.class);
	
    // 当有多个方法 拥有一样的参数和返回类型时,需要指定使用其中的哪一个,使用qualifiedByName指定
    @Mapping(source = "isDone", target = "isDone", qualifiedByName = "DoneDetailFormater")
    ProductDTO toDto(Product product);
}

list映射:

@Mapper(componentModel = "spring")
public interface UserMapping {

    /**
     * Student 转化为 User
     * @param Student
     * @return
     */
     User studentToUser(Student student);
     
    // 	当执行 下面这个List的转换时,会遍历list: students,
   	//  然后自动调用上面的Student转User的转换方法,来进行转换
     /**
     * Students 转化为 Users
     * @param Students
     * @return
     */
     List<user> studentsToUsers(List<student> students);
}

Map映射:

可以使用@MapMapping实现对keyvalue的分别映射

@Mapper(componentModel = "spring")
public interface UserMapping {

    /**
     * Student 转化为 User
     * @param Student
     * @return
     */
     User studentToUser(Student student);
     
    // 	当执行 下面这个List的转换时,会遍历list: students,
   	//  然后自动调用上面的Student转User的转换方法,来进行转换
     /**
     * Students 转化为 Users
     * @param Students
     * @return
     */
     List<user> studentsToUsers(List<student> students);
}

枚举映射:

映射方法:使用@ValueMappings@ValueMapping ,可以理解成是用if判断枚举值,然后返回对应结果

public enum E1 {
    E1_1,
    E1_2,
    E1_3
}

public enum E2 {
    E2_1,
    E2_2,
    E2_3
}

@Mapper
public interface DataEnumMapper {
    DataEnumMapper INSTANCE = Mappers.getMapper(DataEnumMapper.class);

    @ValueMappings({
            @ValueMapping(target = "E1_1", source = "E2_1"),
            @ValueMapping(target = "E1_2", source = "E2_2"),
            @ValueMapping(target = MappingConstants.NULL, source = "E2_3") //转换成null
    })
    E1 toDTO(E2 e2);
}

使用表达式或默认值:

// 使用外部的类,需要通过这种形式导入
@Mapper(imports = MathUtils.class)
public interface ObjectExpressionMapper {

    ObjectExpressionMapper INSTANCE = Mappers.getMapper(ObjectExpressionMapper.class);
	
    //expression中可以直接写Java代码
    @Mappings({
        
        	// 设置默认值
         	@Mapping(target = "productId", source = "productId", defaultValue = "123"), //当product的productId为null,设置为0
        	// 表达式
            @Mapping(target = "price", expression = "java(product.getPrice1() + product.getPrice2())"),//直接相加
            @Mapping(target = "price2", expression = "java(MathUtils.addAndReturn0(product.getPrice1(), product.getPrice2()))") //使用工具类处理
    		// 常量
        	@Mapping(target = "stock", constant = "100"), //固定设置为100, 常量
    })
    ProductDTO toDTO(Product product);

}

注意:

1. 不管有多少入参,当目标类中的属性名和入参类型中的属性名一致时,都不用写Mapping,会自动映射,除非多个参数的类型中有同名的属性,这种情况需要指定一个source,通过类似user.name的方式(user 是参数名)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值