MapStruct使用之基础

基础映射

创建需要映射的POJO

咱们使用两个基础对象做示范。

注意:代码中使用了lombok

@Data  
@Builder  
public class X {  
    private Long id;  
    private String name;  
    private String description;  
}
@Data  
@Builder  
public class Y {  
    private Long id;  
    private String name;  
    private String description;  
}

编写映射接口

@Mapper  
public interface XYMapper {  
  
    XYMapper INSTANCE = Mappers.getMapper(XYMapper.class);  
  
    Y source2Destination(X source);  
  
}

生成的接口实现

public class XYMapperImpl implements XYMapper {  
  
    @Override  
    public Y source2Destination(X source) {  
        if ( source == null ) {  
            return null;  
        }  
  
        Y.YBuilder y = Y.builder();  
  
        y.id( source.getId() );  
        y.name( source.getName() );  
        y.description( source.getDescription() );  
  
        return y.build();  
    }  
}

测试验证

public class Test {  
  
    public static void main(String[] args) {  
        X x = X.builder().id(1L).name("哈利路亚").description("哈哈").build();  
        System.out.println(x);  
        Y y = XYMapper.INSTANCE.source2Destination(x);  
        System.out.println(y);  
    }  
  
}
X(id=1, name=哈利路亚, description=哈哈)
Y(id=1, name=哈利路亚, description=哈哈)

字段名不同的映射

创建需要映射的POJO

@Data  
@Builder  
public class X {  
    private Long id;  
    private String name;  
    private String description;  
}
@Data  
@Builder  
public class Y {  
    private Long targetId;  
    private String placeName;  
    private String desc;  
}

编写映射接口

使用 @Mapping 注解配置映射的字段名称。

@Mapper  
public interface XYMapper {  
  
    XYMapper INSTANCE = Mappers.getMapper(XYMapper.class);  
  
    @Mapping(source = "id", target = "targetId")  
    @Mapping(source = "name", target = "placeName")  
    @Mapping(source = "description", target = "desc")  
    Y source2Destination(X source);  
  
}

生成的接口实现

public class XYMapperImpl implements XYMapper {

    @Override
    public Y source2Destination(X source) {
        if ( source == null ) {
            return null;
        }

        Y.YBuilder y = Y.builder();

        y.targetId( source.getId() );
        y.placeName( source.getName() );
        y.desc( source.getDescription() );

        return y.build();
    }
}

测试验证

public class Test {  
  
    public static void main(String[] args) {  
        X x = X.builder().id(1L).name("哈利路亚").description("哈哈").build();  
        System.out.println(x);  
        Y y = XYMapper.INSTANCE.source2Destination(x);  
        System.out.println(y);  
    }  
  
}
X(id=1, name=哈利路亚, description=哈哈)
Y(targetId=1, placeName=哈利路亚, desc=哈哈)

子对象的映射

创建需要映射的POJO

@Data  
@Builder  
public class Foo {  
    private String fooName;  
}
@Data  
@Builder  
public class Bar {  
    private String barName;  
}
@Data  
@Builder  
public class X {  
    private Long id;  
    private String name;  
    private String description;  
  
    private Foo foo;  
}
@Data  
@Builder  
public class Y {  
    private Long targetId;  
    private String placeName;  
    private String desc;  
  
    private Bar bar;  
}

编写映射接口

@Mapper  
public interface XYMapper {  
  
    XYMapper INSTANCE = Mappers.getMapper(XYMapper.class);  
  
    @Mapping(source = "id", target = "targetId")  
    @Mapping(source = "name", target = "placeName")  
    @Mapping(source = "description", target = "desc")  
    @Mapping(source = "foo", target = "bar")  
    Y source2Destination(X source);  
  
    @Mapping(source = "fooName", target = "barName")  
    Bar foo2Bar(Foo foo);  
}

生成的接口实现

public class XYMapperImpl implements XYMapper {  
  
    @Override  
    public Y source2Destination(X source) {  
        if ( source == null ) {  
            return null;  
        }  
  
        Y.YBuilder y = Y.builder();  
  
        y.targetId( source.getId() );  
        y.placeName( source.getName() );  
        y.desc( source.getDescription() );  
        y.bar( foo2Bar( source.getFoo() ) );  
  
        return y.build();  
    }  
  
    @Override  
    public Bar foo2Bar(Foo foo) {  
        if ( foo == null ) {  
            return null;  
        }  
  
        Bar.BarBuilder bar = Bar.builder();  
  
        bar.barName( foo.getFooName() );  
  
        return bar.build();  
    }  
}

验证测试

public class Test {  
  
    public static void main(String[] args) {  
        Foo foo = Foo.builder().fooName("FOO").build();  
        X x = X.builder().id(1L).name("哈利路亚").description("哈哈").foo(foo).build();  
        System.out.println(x);  
        Y y = XYMapper.INSTANCE.source2Destination(x);  
        System.out.println(y);  
    }  
  
}
X(id=1, name=哈利路亚, description=哈哈, foo=Foo(fooName=FOO))
Y(targetId=1, placeName=哈利路亚, desc=哈哈, bar=Bar(barName=FOO))

类型转换的映射

创建需要映射的POJO

@Data
@Builder
public class X {
    private Long id;
    private String name;
    private String description;

    private LocalDateTime localDateTime;
    private Double price;
}
@Data  
@Builder  
public class Y {  
    private Long targetId;  
    private String placeName;  
    private String desc;  
  
    private String time;  
    private String price;  
}

编写映射接口

@Mapper  
public interface XYMapper {  
  
    XYMapper INSTANCE = Mappers.getMapper(XYMapper.class);  
  
    @Mapping(source = "id", target = "targetId")  
    @Mapping(source = "name", target = "placeName")  
    @Mapping(source = "description", target = "desc")  
    @Mapping(source = "localDateTime", target = "time", dateFormat = "yyyy-MM-dd HH:mm:ss")  
    @Mapping(source = "price", target = "price", numberFormat = "¥#.00")  
    Y source2Destination(X source);  
  
}

生成的接口实现

public class XYMapperImpl implements XYMapper {  
  
    private final DateTimeFormatter dateTimeFormatter_yyyy_MM_dd_HH_mm_ss_11333195168 = DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss" );  
  
    @Override  
    public Y source2Destination(X source) {  
        if ( source == null ) {  
            return null;  
        }  
  
        Y.YBuilder y = Y.builder();  
  
        y.targetId( source.getId() );  
        y.placeName( source.getName() );  
        y.desc( source.getDescription() );  
        if ( source.getLocalDateTime() != null ) {  
            y.time( dateTimeFormatter_yyyy_MM_dd_HH_mm_ss_11333195168.format( source.getLocalDateTime() ) );  
        }  
        if ( source.getPrice() != null ) {  
            y.price( new DecimalFormat( "¥#.00" ).format( source.getPrice() ) );  
        }  
  
        return y.build();  
    }  
}

验证测试

public class Test {  
  
    public static void main(String[] args) {  
        Foo foo = Foo.builder().fooName("FOO").build();  
        X x = X.builder().id(1L).name("哈利路亚").description("哈哈")  
            .localDateTime(LocalDateTime.now())  
            .price(34531D)  
            .build();  
        System.out.println(x);  
        Y y = XYMapper.INSTANCE.source2Destination(x);  
        System.out.println(y);  
    }  
  
}
X(id=1, name=哈利路亚, description=哈哈, localDateTime=2023-08-10T10:19:02.003, price=34531.0)
Y(targetId=1, placeName=哈利路亚, desc=哈哈, time=2023-08-10 10:19:02, price=¥34531.00)

前置映射和后置映射

使用 @BeforeMapping 进行前置映射,使用 @AfterMapping 进行后置映射

创建需要映射的POJO

@Data  
@Builder  
public class X {  
    private String firstName;  
    private String lastName;  
}
@Data  
@Builder  
public class Y {  
    private String firstName;  
    private String lastName;  
    private String fullName;  
}

编写映射接口

注意:@Mapper 注解同lombok的 @Builder 使用时会出现问题,可以按照如下代码中的配置解决

@Mapper(builder = @Builder(disableBuilder = true))  
public interface XYMapper {  
  
    XYMapper INSTANCE = Mappers.getMapper(XYMapper.class);  
  
    Y source2Destination(X x);  
  
    @BeforeMapping  
    default void before(X x) {  
        x.setFirstName(x.getFirstName().toUpperCase());  
        x.setLastName(x.getLastName().toUpperCase());  
    }  
  
    @AfterMapping  
    default void after(@MappingTarget Y y) {  
        y.setFullName(y.getFirstName() + " " + y.getLastName());  
    }  
  
}

生成的接口实现

public class XYMapperImpl implements XYMapper {  
  
    @Override  
    public Y source2Destination(X x) {  
        before( x );  
  
        if ( x == null ) {  
            return null;  
        }  
  
        String firstName = null;  
        String lastName = null;  
  
        firstName = x.getFirstName();  
        lastName = x.getLastName();  
  
        String fullName = null;  
  
        Y y = new Y( firstName, lastName, fullName );  
  
        after( y );  
  
        return y;  
    }  
}

验证测试

public class Test {  
  
    public static void main(String[] args) {  
        X x = X.builder().firstName("gg").lastName("bond").build();  
        System.out.println(x);  
        Y y = XYMapper.INSTANCE.source2Destination(x);  
        System.out.println(y);  
    }  
  
}
X(firstName=gg, lastName=bond)
Y(firstName=GG, lastName=BOND, fullName=GG BOND)

表达式映射

创建需要映射的POJO

@Data  
@Builder  
public class X {  
    private String firstName;  
    private String lastName;  
}
@Data  
@Builder  
public class Y {  
    private String firstName;  
    private String lastName;  
    private String uuid;  
}

编写映射接口

@Mapper(builder = @Builder(disableBuilder = true))  
public interface XYMapper {  
  
    XYMapper INSTANCE = Mappers.getMapper(XYMapper.class);  
  
    @Mapping(target = "uuid", expression = "java(java.util.UUID.randomUUID().toString())")  
    Y source2Destination(X x);  
}

生成的接口实现

public class XYMapperImpl implements XYMapper {  
  
    @Override  
    public Y source2Destination(X x) {  
        if ( x == null ) {  
            return null;  
        }  
  
        String firstName = null;  
        String lastName = null;  
  
        firstName = x.getFirstName();  
        lastName = x.getLastName();  
  
        String uuid = java.util.UUID.randomUUID().toString();  
  
        Y y = new Y( firstName, lastName, uuid );  
  
        return y;  
    }  
}

验证测试

public class Test {  
  
    public static void main(String[] args) {  
        X x = X.builder().firstName("gg").lastName("bond").build();  
        System.out.println(x);  
        Y y = XYMapper.INSTANCE.source2Destination(x);  
        System.out.println(y);  
    }  
  
}
X(firstName=gg, lastName=bond)
Y(firstName=gg, lastName=bond, uuid=3ef6875a-85ce-4d8c-807d-2c0d4193cfd4)

最后修改于 2023-08-10