当前位置: 代码网 > it编程>编程语言>Java > Java实现MapStruct对象转换的示例代码

Java实现MapStruct对象转换的示例代码

2024年12月07日 Java 我要评论
一、基本使用1、maven 引入<properties> <lombok.version>1.18.30</lombok.version> <ma

一、基本使用

1、maven 引入

<properties>
    <lombok.version>1.18.30</lombok.version>
    <mapstruct.version>1.4.1.final</mapstruct.version>
</properties>

<dependencies>
    <dependency>
        <groupid>org.projectlombok</groupid>
        <artifactid>lombok</artifactid>
        <version>${lombok.version}</version>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupid>org.mapstruct</groupid>
        <artifactid>mapstruct</artifactid>
        <version>${mapstruct.version}</version>
    </dependency>

    <dependency>
        <groupid>org.mapstruct</groupid>
        <artifactid>mapstruct-processor</artifactid>
        <version>${mapstruct.version}</version>
    </dependency>
</dependencies>

2、基本使用

待转换的类

@data
@builder
public class userdto {
    private long id;
    private integer age;
    private string name;
}

转换目标类

@data
public class uservo {
    private long id;
    private integer age;
    private string name;
}

转换器

import org.mapstruct.mapper;
import org.mapstruct.factory.mappers;

@mapper
public interface converter {
    // 后续通过 instant 调用转换方法
    converter instant = mappers.getmapper(converter.class);

    uservo convert(userdto userdto);
}

使用示例

public class test {
    public static void main(string[] args) {
        userdto userdto = userdto.builder().id(1l).age(18).name("scj").build();
        uservo uservo = converter.instant.convert(userdto);
        system.out.println(uservo);
    }
}

输出结果

uservo(id=1, age=18, name=scj)

可以看到在 target 生成 转换器的实现类,并使用 get 和 set 进行转换,所以性能很高。

在这里插入图片描述

3、spring bean

mapstruct提供了依赖注入的机制,让我们能够在spring的环境下,更优雅的获得converter。

转换器

import org.mapstruct.mapper;
import org.mapstruct.factory.mappers;

@mapper(componentmodel = mappingconstants.componentmodel.spring)
public interface converter {
    uservo convert(userdto userdto);
}

使用示例

@restcontroller
public class testcontroller {
    
    // 直接注入使用
    @autowired
    private converter converter;

    @getmapping("/test")
    public void mapstructtest() {
        userdto userdto = userdto.builder().id(1l).age(18).name("scj").build();
        uservo uservo = converter.convert(userdto);
        system.out.println(uservo);
    }
}

输出结果

uservo(id=1, age=18, name=scj)

可以看到 target 中生成的实现类交给 spring容器 管理了

在这里插入图片描述

二、类型一致的场景

1、字段名不一致

字段名不同,通过 target 和 source 属性指定映射关系(字段名一致可以省略)

转换器

@mapper
public interface converter {
    converter instant = mappers.getmapper(converter.class);

    @mapping(target = "username", source = "name")
    uservo convert(userdto userdto);
}

输出结果

uservo(id=1, age=18, username=scj)

2、ignore

不需要映射的字段,可以设置 ignore = true

转换器

@mapper
public interface converter {
    converter instant = mappers.getmapper(converter.class);

    // 不需要映射的字段,指定 ignore = true
    @mapping(target = "name", ignore = true)
    @mapping(target = "age", ignore = true)
    uservo convert(userdto userdto);
}

输出结果

uservo(id=1, age=null, name=null)

3、defaultvalue

通过 defaultvalue 设置默认值(仅当源对象的该属性值为 null 时)

转换器

@mapper
public interface converter {
    converter instant = mappers.getmapper(converter.class);

    // 只有为 null 的才会生效
    @mapping(target = "id", defaultvalue = "1")
    @mapping(target = "age", defaultvalue = "66")
    @mapping(target = "name", defaultvalue = "zs")
    uservo convert(userdto userdto);
}

使用示例

public class test {
    public static void main(string[] args) {
        // id = null
        userdto userdto = userdto.builder().age(18).name("scj").build();
        uservo uservo = converter.instant.convert(userdto);
        system.out.println(uservo);
    }
}

输出结果

uservo(id=1, age=18, name=scj)

4、constant

通过 constant 为属性设置常量值,无论源对象的该属性值是否为 null

转换器

@mapper
public interface converter {
    converter instant = mappers.getmapper(converter.class);

    // 只有为 null 的才会生效
    @mapping(target = "id", constant = "6")
    @mapping(target = "age", constant = "66")
    @mapping(target = "name", constant = "zs")
    uservo convert(userdto userdto);
}

使用示例

public class test {
    public static void main(string[] args) {
        userdto userdto = userdto.builder().id(1).age(18).name("scj").build();
        uservo uservo = converter.instant.convert(userdto);
        system.out.println(uservo);
    }
}

输出结果

uservo(id=6, age=66, name=zs)

三、类型不一致的场景

1、默认转换

对于部分数据类型,如果属性类型不一致,会做默认的的转换并赋值。

包装类 相关:基本数据类型、字符串、其他包装类

// integer -> int
target.setintegervalue( source.getintegervalue() );

// integer -> long
target.setintegervalue( source.getintegervalue().longvalue() );

// integer -> double
target.setintegervalue( source.getintegervalue().doublevalue() );

// integer -> string
target.setintegervalue( string.valueof( source.getintegervalue() ) );

bigdecimal 相关:

// bigdecimal -> integer/int
target.setdecimalvalue( source.getdecimalvalue().intvalue() );

// bigdecimal -> double/double
target.setdecimalvalue( source.getdecimalvalue().doublevalue() );

// bigdecimal -> string
target.setdecimalvalue( source.getdecimalvalue().tostring() );

时间日期 相关

// date -> localdatetime
target.setdatevalue( localdatetime.ofinstant( source.getdatevalue().toinstant(), zoneid.of( "utc" ) ) );

// localdatetime -> date
target.setdatevalue( date.from( source.getdatevalue().toinstant( zoneoffset.utc ) ) );

// date -> string
target.setdatevalue( new simpledateformat().format( source.getdatevalue() ) );

// localdatetime -> string
target.setdatevalue( datetimeformatter.iso_local_date_time.format( source.getdatevalue() ) );

枚举 相关

// enum -> string
target.setenumvalue( source.getenumvalue().name() );

string 相关

// string -> long/long
target.setstringvalue( long.parselong( source.getstringvalue() ) );

// string -> bigdecimal
target.setstringvalue( new bigdecimal( source.getstringvalue() ) );

// string -> date
target.setstringvalue( new simpledateformat().parse( source.getstringvalue() ) );

// string -> localdatetime
target.setstringvalue( localdatetime.parse( source.getstringvalue() ) );

// string -> enum
target.setenumvalue( enum.valueof( source.customenum.class, source.getenumvalue() ) );

2、numberformat

数字类型 转换为 字符串 时,可以通过 numberformat 属性指定 格式

@mapper
public interface converter {
    converter instant = mappers.getmapper(converter.class);

    @mapping(target = "integervalue", source = "integervalue", numberformat = "#,##0")
    @mapping(target = "doublevalue", source = "doublevalue", numberformat = "#0.00")
    @mapping(target = "decimalvalue", source = "decimalvalue", numberformat = "#%")
    target convert(source source);
}
  • #,##0:表示数字使用千位分隔符。例如,1234567 将被格式化为 1,234,567
  • #0.00:表示数字保留两位小数。例如,666.666 将被格式化为 666.67
  • #%:表示将数字视为百分比。例如,0.75 将被格式化为 75%

3、dateformat

时间日期 转换为 字符串 时,可以通过 dateformat 属性指定 pattern

待转换的类

@data
public class source {
    private date datevalue = new date();
    private localdatetime localdatetimevalue = localdatetime.now();
}

转换目标类

@data
public class target {
    private string datevalue;
    private string localdatetimevalue;
}

转换器

@mapper
public interface converter {
    converter instant = mappers.getmapper(converter.class);

    @mapping(target = "datevalue", source = "datevalue", dateformat = "yyyy-mm-dd hh:mm:ss")
    @mapping(target = "localdatetimevalue", source = "localdatetimevalue", dateformat = "yyyy-mm-dd hh:mm:ss")
    target convert(source source);
}

输出结果

target(datevalue=2024-09-26 19:27:41, localdatetimevalue=2024-09-26 19:27:41)

4、枚举值处理

待转换的类

@data
public class source {
    private sexenum sexenum = sexenum.man;
}

转换目标类

@data
public class target {
    private string sex;
}

转换器

@mapper
public interface converter {
    converter instant = mappers.getmapper(converter.class);

    @mapping(target = "sex", source = "sexenum.desc")
    target convert(source source);
}

四、其他场景

1、对象嵌套(字段一致)

如果字段完全一致,会自动生成嵌套对象的 convert 方法。

待转换的类

@data
public class source {
    private long id = 1l;
    private sourceinnerclass1 inner = new sourceinnerclass1();
}

@data
class sourceinnerclass1 {
    private long id = 11l;
    private list<sourceinnerclass2> innerlist = collections.singletonlist(new sourceinnerclass2());
}

@data
class sourceinnerclass2 {
    private long id = 111l;
    private string value = "inner2";
}

转换目标类

@data
public class target {
    private long id;
    private targetinnerclass1 inner;
}

@data
class targetinnerclass1 {
    private long id;
    private list<targetinnerclass2> innerlist;
}

@data
class targetinnerclass2 {
    private long id;
    private string value;
}

转换器

@mapper
public interface converter {
    converter instant = mappers.getmapper(converter.class);

    target convert(source source);
}

输出

target(id=1, inner=targetinnerclass1(id=11, innerlist=[targetinnerclass2(id=111, value=inner2)]))

可以看到,所有嵌套对象的属性都做了自动映射

在这里插入图片描述

在这里插入图片描述

2、对象嵌套(字段不一致)

如果字段不一致,需要自己编写对应嵌套对象的 convert 方法,底层会自动调用。

待转换的类

@data
public class source {
    private long id;
    private sourceinnerclass1 inner;
}

@data
class sourceinnerclass1 {
    private long id;
    private list<sourceinnerclass2> innerlist;
}

@data
class sourceinnerclass2 {
    private long id;
    private string value;
}

转换目标类

@data
public class target {
    private long id0;
    private targetinnerclass1 inner0;
}

@data
class targetinnerclass1 {
    private long id1;
    private list<targetinnerclass2> innerlist1;
}

@data
class targetinnerclass2 {
    private long id2;
    private string value2;
}

转换器

@mapper
public interface converter {
    converter instant = mappers.getmapper(converter.class);

    @mapping(target = "id0", source = "id")
    @mapping(target = "inner0", source = "inner")
    target convert(source source);

    @mapping(target = "id1", source = "id")
    @mapping(target = "innerlist1", source = "innerlist")
    targetinnerclass1 convert(sourceinnerclass1 source);

    @mapping(target = "id2", source = "id")
    @mapping(target = "value2", source = "value")
    targetinnerclass2 convert(sourceinnerclass2 source);
}

使用示例

public class test {
    public static void main(string[] args) {
        final source source = new source(1l, 18l, "scj", new sourceinner(1l, 18));
        final target target = converter.instant.convert(source);
        system.out.println(target);
    }
}

输出

target(id0=1, inner0=targetinnerclass1(id1=11, innerlist1=[targetinnerclass2(id2=111, value2=inner2)]))

会按需调用对应对象的 convert 方法

在这里插入图片描述

3、自定义转换方法

使用 @named 自定义转换方法,通过 qualifiedbyname 属性指定,要和 @named 的 value 对应

待转换的类

@data
public class target {
    private userdto targetuserdto;
    private string targetuserjson;
}

转换目标类

@data
public class source {
    private string sourceuserjson;
    private userdto sourceuserdto;
}

转换器

@mapper
public interface convert {

    convert instance = mappers.getmapper(convert.class);

    @mapping(target = "targetuserdto", source = "sourceuserjson", qualifiedbyname = "json2dto")
    @mapping(target = "targetuserjson", source = "sourceuserdto", qualifiedbyname = "dto2json")
    target convert(source source);

    @named("json2dto")
    default userdto json2dto(string userjson) {
        return json.parseobject(userjson, userdto.class);
    }

    @named("dto2json")
    default string dto2json(userdto userdto) {
        return json.tojsonstring(userdto);
    }
}

转换结果

target(targetuserdto=userdto(name=scj, age=18), targetuserjson={"age":66,"name":"zs"})

4、expression

通过 expression 可以指定 java 表达式,可以直接调用对应的方法。

转换器

@mapper
public interface convert {

    convert instance = mappers.getmapper(convert.class);
    
    // 本类方法
    @mapping(target = "targetuserdto",  expression = "java(json2dto(source.getsourceuserjson()))")
    // 非本类方法(类全名调用即可)
    @mapping(target = "targetuserjson", expression = "java(com.alibaba.fastjson.json.tojsonstring(source.getsourceuserdto()))")
    // 枚举
    @mapping(target = "sex", expression = "java(source.getsexenum().getdesc())")
    target convert(source source);

    default userdto json2dto(string userjson) {
        return json.parseobject(userjson, userdto.class);
    }
}

转换结果

target(targetuserdto=userdto(name=scj, age=18), targetuserjson={"age":66,"name":"zs"}, sex=男)

convertimpl

public class convertimpl implements convert {
    @override
    public target convert(source source) {
        if ( source == null ) {
            return null;
        }

        target target = new target();

        target.settargetuserdto( json2dto(source.getsourceuserjson()) );
        target.settargetuserjson( com.alibaba.fastjson.json.tojsonstring(source.getsourceuserdto()) );
        target.setsex( source.getsexenum().getdesc() );

        return target;
    }
}

5、多个参数

待转换的类

@data
public class target {

    // source1

    private string strvalue1;
    private integer intvalue1;

    // source2

    private string strvalue2;
    private integer intvalue2;

    // field

    private string strvalue;
    private integer intvalue;

}

转换目标类

@data
public class source1 {
	private string strvalue = "s1";
    private integer intvalue = 1;
}

@data
public class source2 {
    private string strvalue = "s2";
    private integer intvalue = 2;
}

转换器

@mapper
public interface convert {

    convert instance = mappers.getmapper(convert.class);

    @mapping(target = "strvalue1", source = "s1.strvalue")
    @mapping(target = "intvalue1", source = "s1.intvalue")
    @mapping(target = "strvalue2", source = "s2.strvalue")
    @mapping(target = "intvalue2", source = "s2.intvalue")
    @mapping(target = "strvalue", source = "strvalue")
    @mapping(target = "intvalue", source = "intvalue")
    target convert(source1 s1, source2 s2, string strvalue, integer intvalue);
}

注意事项:如果字段名全部没有冲突,不需要 @mapping,会自动对应。

五、推荐的idea插件

idea 搜索 mapstruct support 安装即可,可以在使用mapstruct时获得更加丰富代码提示。

在这里插入图片描述

到此这篇关于java实现mapstruct对象转换的示例代码的文章就介绍到这了,更多相关java mapstruct对象转换内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网! 

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com