MapStruct的一些常规用法

每天坚持写一篇原创文章。

使用过MapStruct之后,再也没用过BeanCopy来复制对象了。确实是非常好用的工具库。

MapStruct是一个代码生成器,简化了不同的Java Bean之间映射的处理,所以映射指的就是从一个实体变化成一个实体。例如我们在实际开发中,DAO层的实体和一些数据传输对象(DTO),大部分属性都是相同的,只有少部分的不同,通过mapStruct,可以让不同实体之间的转换变的简单。我们只需要按照约定的方式进行配置即可。

大家的命名都不一样,我个人是习惯把数据库的DO对象叫Entity实体。

返回前端的叫VO。

把Entity复制到VO并做一些操作或者转换,再返回前端,都会用到。

安装

1、引用

唯一需要注意的就是如果配合Lombok,需要在编译源码的插件上做好配置。

复制代码
<properties>
        <mapstruct.version>1.3.0.Final</mapstruct.version>
</properties>

<!-- MapStruct核心,包含了一些必要的注解-->
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${mapstruct.version}</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven.compiler-plugin.version}</version>
            <configuration>
                <source>${java.version}</source>
                <target>${java.version}</target>
                <compilerVersion>${java.version}</compilerVersion>
                <fork>true</fork>
                <encoding>${project.build.sourceEncoding}</encoding>
                <verbose>true</verbose>
                <annotationProcessorPaths>
                    <!-- 同时用Lombok,需要将Lombok放前面 -->
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                        <version>${lombok.version}</version>
                    </path>
                    <!-- MapStruct编译,注解处理器,根据注解自动生成Mapper的实现 -->
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${mapstruct.version}</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

2、定义转换接口

复制代码
@Mapper
public interface OrderConvertor {

    OrderConvertor INSTANCE = Mappers.getMapper(OrderConvertor.class);
 
    @Mapping(source = "student.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss") // 指定时间格式
    @Mapping(target = "name", source = "student.name", defaultValue = "张三") //默认值
    OrderVo toVo(OrderEntity order);
}

target表示目标属性名,source表示源属性名,一般在目标属性和源属性不同时使用,相同的属性名会自动进行映射。

MapStruct会自动生成对应接口的实现,并自动完成属性映射关系,List会自动进行批量处理。

3、使用时

复制代码
@Service
public class OrderService {
    public List<OrderVo> getOrderList() {
        // 获取数据库数据
        List<OrderEntity> result = selectOrderList();
        // 参数转换
        return OrderConvertor.INSTANCE.toVo(result);
    }
}

下面是我常用的一些功能记录

1、添加为Spring的Component组件

复制代码
@Mapper(componentModel = "spring")

2、List转换为String

类注解加上引用

复制代码
@Mapper(imports = {Collectors.class, TelegramGroupEntity.class})

代码里面:使用表达式,转换为字符串

复制代码
@Mapping(target = "groupStr", expression = "java(source.getBindGroups()!= null? source.getBindGroups().stream().map(TelegramGroupEntity::getName).collect(Collectors.joining(\", \")) : null)")
AcceptanceBankVo convert(AcceptanceBankEntity source);

直接转换List为换行的String

复制代码
@Mapping(target = "groupStr", expression = "java(source.getBindGroups()!= null? source.getBindGroups().stream().map(TelegramGroupEntity::getName).collect(Collectors.joining(\"\\n\")) : null)")

直接调用方法

复制代码
@Mapper(imports = {Collectors.class, TelegramGroupEntity.class, IndiaDateUtil.class})
public interface TransferBankConvert {
TransferBankConvert INSTANCE = Mappers.getMapper(TransferBankConvert.class);

@Mapping(target = "timeAgo", expression = "java(source.getLastActiveTime()!= null? IndiaDateUtil.getTimeAgo(source.getLastActiveTime(),\"Asia/Kolkata\") : null)")
TransferBankVo convert(TransferBankEntity source);
}

3、获取时间

复制代码
@Mapping(target = "recordTime",expression = "java(new java.util.Date())")

4、空检查

复制代码
@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)

5、枚举映射String和string到枚举

int转枚举的value

复制代码
@Mapper(imports = {AccptanceRoleTypeEnum.class}) // 加到类上引用进来

@Mapping(target = "roleText", expression = "java(AccptanceRoleTypeEnum.getItemValue(source.getRole()))")

枚举上加上:

复制代码
/**
 * 根据Value取描述
 * @param value
 * @return
 */
public static String getItemValue(Integer value) {
    AccptanceRoleTypeEnum match = Stream.of(values()).filter(item -> item.value.equals(value)).findAny().orElse(null);
    return match == null ? null : match.getDesc();
}

6、Fill同对象填充新对象,把source填充到target里面,和以前的beancopy一样的。

复制代码
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE,
        nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
@Mappings({
        @Mapping(target = "id", ignore = true),
        @Mapping(target = "createTime", ignore = true),
        @Mapping(target = "updateTime", ignore = true)
})
void fill(TelegramGroupRoleEntity source, @MappingTarget TelegramGroupRoleEntity target);

要忽略空值填充

复制代码
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
void update(DTO dto, @MappingTarget Bean bean);

7、Map提取,还是用表达式最简单

复制代码
@Mappings({
        @Mapping(expression = "java(mapConfig.getOrDefault(\"INPAY_RATES\",""))", target = "inpayRates"),
        @Mapping(expression = "java(mapConfig.getOrDefault(\"AUTO_CREDIT\",""))", target = "autoCredit")
})
TelegramGroupWithConfigVo convert(TelegramGroupEntity entity);

8、空值判断

复制代码
@Mapping(target = "targetField", expression = "java( sourceField == null || sourceField.isEmpty() ? null : sourceField )") 来将空字符串映射为 null

更多内容请关注我的公众号:青塬科技。

相关推荐
李少兄2 小时前
Unirest:优雅的Java HTTP客户端库
java·开发语言·http
此木|西贝2 小时前
【设计模式】原型模式
java·设计模式·原型模式
可乐加.糖2 小时前
一篇关于Netty相关的梳理总结
java·后端·网络协议·netty·信息与通信
s9123601012 小时前
rust 同时处理多个异步任务
java·数据库·rust
9号达人2 小时前
java9新特性详解与实践
java·后端·面试
cg50172 小时前
Spring Boot 的配置文件
java·linux·spring boot
啊喜拔牙2 小时前
1. hadoop 集群的常用命令
java·大数据·开发语言·python·scala
anlogic3 小时前
Java基础 4.3
java·开发语言
非ban必选3 小时前
spring-ai-alibaba第七章阿里dashscope集成RedisChatMemory实现对话记忆
java·后端·spring
A旧城以西3 小时前
数据结构(JAVA)单向,双向链表
java·开发语言·数据结构·学习·链表·intellij-idea·idea