Orika MapperFacade 对象属性复制在SpringBoot项目中的使用

文章目录

  • 前言
  • 正文
    • 一、项目代码
      • 1.1 maven依赖
      • 1.2 核心配置文件
      • 1.3 时间工具类
      • 1.4 实体类
      • 1.5 转换对象的调用
    • 二、MapperFacade API

前言

众所周知,在Java项目中经常会有用到各种对象属性复制的情况,以及从一个对象转换为另一个对象。

之前我们可能会使用以下工具:

  • BeanUtils.copyProperties(A, B);
  • MapStruct 对象映射

今天我们来一起看看另一种功能同样强大,性能也很高的工具!就是Orika MapperFacade

正文

在SpringBoot项目中,我们使用Orika MapperFacade时也是非常方便的。以下会用代码举例。

一、项目代码

项目环境是java1.8,使用了Springboot的2.x版本。

1.1 maven依赖


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
    <groupId>org.fenggroupId>
    <artifactId>mapper-facade-demoartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>mapper-facade-demoname>
    <description>mapper-facade-demodescription>
    <properties>
        <java.version>1.8java.version>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
        <spring-boot.version>2.7.6spring-boot.version>
    properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>

        <dependency>
            <groupId>com.gitlab.haynesgroupId>
            <artifactId>orika-spring-boot-starterartifactId>
            <version>1.26.0version>
        dependency>

        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <optional>trueoptional>
        dependency>
    dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-dependenciesartifactId>
                <version>${spring-boot.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.pluginsgroupId>
                <artifactId>maven-compiler-pluginartifactId>
                <version>3.8.1version>
                <configuration>
                    <source>1.8source>
                    <target>1.8target>
                    <encoding>UTF-8encoding>
                configuration>
            plugin>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
                <version>${spring-boot.version}version>
                <configuration>
                    <mainClass>org.feng.MapperFacadeDemoApplicationmainClass>
                    <skip>trueskip>
                configuration>
                <executions>
                    <execution>
                        <id>repackageid>
                        <goals>
                            <goal>repackagegoal>
                        goals>
                    execution>
                executions>
            plugin>
        plugins>
    build>

project>

1.2 核心配置文件

因为在转换java8的时间类(诸如LocalDateTime等)时,会有格式问题,所以增加了类转换器。

package org.feng.config;

import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.MappingContext;
import ma.glasnost.orika.converter.BidirectionalConverter;
import ma.glasnost.orika.converter.ConverterFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import ma.glasnost.orika.metadata.Type;
import org.feng.util.TimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDateTime;

/**
 * mapperFacade配置
 *
 * @author feng
 */
@Configuration
public class MapperFacadeConfig {

    @Bean
    public MapperFactory mapperFactory() {
        DefaultMapperFactory mapperFactory = new DefaultMapperFactory.Builder()
                // 忽略映射空字段
                .mapNulls(false)
                .build();

        ConverterFactory converterFactory = mapperFactory.getConverterFactory();
        // 注册时间转换器
        converterFactory.registerConverter(new LocalDateTimeStrConverter());

        return mapperFactory;
    }

    @Bean
    public MapperFacade mapperFacade(@Autowired MapperFactory mapperFactory) {
        return mapperFactory.getMapperFacade();
    }

    private static class LocalDateTimeStrConverter extends BidirectionalConverter<LocalDateTime, String> {

        @Override
        public String convertTo(LocalDateTime localDateTime, Type<String> type, MappingContext mappingContext) {
            return TimeUtil.parse(localDateTime);
        }

        @Override
        public LocalDateTime convertFrom(String str, Type<LocalDateTime> type, MappingContext mappingContext) {
            return TimeUtil.format(str);
        }
    }
}

1.3 时间工具类

package org.feng.util;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 时间工具类
 *
 * @version v1.0
 * @author: fengjinsong
 * @date: 2024年01月18日 22时40分
 */
public class TimeUtil {
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static String parse(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return "";
        }
        return DATE_TIME_FORMATTER.format(localDateTime);
    }


    public static LocalDateTime format(String dateTime) {
        if (dateTime == null) {
            return null;
        }
        return LocalDateTime.parse(dateTime, DATE_TIME_FORMATTER);
    }
}

1.4 实体类

为了简化文章篇幅,这里将用到的实体类放在了一起。

@Data
public class Order {
    private Long id;
    private String code;
    private String type;
    private String desc;
    private LocalDateTime createDateTime;
}

@Data
public class User {
    private Long id;
    private String userName;
    private String email;
    private LocalDateTime birthday;
    private LocalDate registerDay;

    private List<Order> orders;
}

@Data
public class OrderVO {
    private Long id;
    private String code;
    private String type;
    private String desc;
    private String createDateTime;
}

@Data
public class UserVO {
    private Long id;
    private String name;
    private String email;
    private String birthday;
    private LocalDate registerDay;

    private List<OrderVO> orders;
}

1.5 转换对象的调用

为了方便,直接在启动类中进行操作。在springboot项目启动后,会执行对应的转换代码。

package org.feng;

import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.BoundMapperFacade;
import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import org.feng.entity.Order;
import org.feng.entity.User;
import org.feng.vo.UserVO;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@SpringBootApplication
public class MapperFacadeDemoApplication implements CommandLineRunner {

    @Resource
    private MapperFactory mapperFactory;

    public static void main(String[] args) {
        SpringApplication.run(MapperFacadeDemoApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        // 存在不同字段名映射,需要增加映射规则;字段名完全相同时,可以直接获取mapperFacade实例进行转换
        mapperFactory.classMap(User.class, UserVO.class)
                .field("userName", "name")
                .byDefault()
                .register();
        BoundMapperFacade<User, UserVO> mapperFacade = mapperFactory.getMapperFacade(User.class, UserVO.class);

        User user = new User();
        user.setUserName("玑而");
        user.setId(2L);
        user.setBirthday(LocalDateTime.now());
        user.setRegisterDay(LocalDate.of(2023,12,21));

        List<Order> orders = new ArrayList<>();
        Order order = new Order();
        order.setCreateDateTime(LocalDateTime.now());
        order.setId(21L);
        order.setCode("323d2");
        orders.add(order);
        user.setOrders(orders);

        UserVO userVO = mapperFacade.map(user);
        log.info(userVO.toString());
    }
}

控制台输出:

UserVO(id=2, name=玑而, email=null, birthday=2024-01-31 11:47:50, registerDay=2023-12-21, orders=[OrderVO(id=21, code=323d2, type=null, desc=null, createDateTime=2024-01-31 11:47:50)])

二、MapperFacade API

  • map(…) 普通对象转换
  • mapAsArray(…) 数组转换为数组
  • mapAsCollection(…) 集合转换为集合
  • mapAsList(…) 转换list
  • mapAsSet(…) 转换set
  • mapAsMap(…) 转换map
  • newObject(…) 创建一个新对象

另外需要注意一下,MapperFacade本身是使用递归的方式去做的。
也就是说如果你要转换的对象内嵌套了其他对象,也是可以复制的。

你可能感兴趣的:(web框架学习,spring,boot,java,spring,orika,mapperfacade)