mapstruct

一、什么是 MapStruct

MapStruct 核心概念
MapStruct是一个Java注解处理器,它的主要功能是自动生成类型安全、高性能且无依赖的bean映射代码。这个工具基于“约定优于配置”的原则,极大地简化了Java Bean类型之间的映射实现过程。

在这里插入图片描述

在多层架构的应用中,经常需要在不同的对象模型之间进行转换,例如在持久层的实体和传输层的DTO(Data Transfer Object,数据传输对象)之间。手动编写这种映射代码是一项繁琐且容易出错的任务。MapStruct通过自动化的方式解决了这个问题,它可以在编译时生成映射代码,从而保证了高性能、快速的开发反馈以及严格的错误检查。

具体来说,使用MapStruct时,开发者只需要定义一个接口,并在接口中定义转换方法。然后,MapStruct会自动生成实现这些方法的代码。这些生成的代码使用纯方法调用,因此速度快、类型安全且易于理解。

MapStruc主要特性
1、类型安全:MapStruct在编译时生成映射代码并进行类型检查,如果源对象和目标对象的属性不匹配,会在编译阶段就报错。

2、性能优秀:由于MapStruct在编译时就生成了映射代码,运行时无需通过反射进行属性拷贝,因此性能较高。

3、灵活性:MapStruct支持复杂的映射,如嵌套映射、集合映射、自定义转换规则等。

4、简洁性:MapStruct使用注解来定义映射规则,使得映射规则的定义更加直观和简洁。

5、无依赖:MapStruct不依赖于任何第三方库,可以很容易地集成到任何项目中。

6、集成Spring:MapStruct也可以与Spring框架集成,允许在映射器中注入Spring管理的bean。

使用MapStruct,开发者只需要定义一个接口,并在接口中声明源对象和目标对象之间的映射关系,MapStruct会在编译时自动生成映射实现类。这极大地提高了代码的可读性和可维护性,同时也避免了手动编写繁琐的转换代码。

二、MapStruct和BeanUtils区别

MapStruct和BeanUtils都是Java中常用的对象属性映射工具,但它们在使用方式和性能上有一些区别。

1、使用方式:
BeanUtils:使用反射机制进行属性拷贝,使用简单,无需写额外的映射代码。
MapStruct:需要定义映射接口,在编译阶段生成映射实现类,使用注解来定义源对象和目标对象之间的映射关系。
2、性能:
BeanUtils:由于使用了反射机制,性能较低。
MapStruct:在编译阶段就生成了映射代码,运行时无需通过反射进行属性拷贝,因此性能较高。
3、灵活性和安全性:
BeanUtils:由于是动态映射,如果源对象和目标对象的属性不匹配,可能会在运行时出现错误。
MapStruct:在编译阶段就进行了类型检查,如果源对象和目标对象的属性不匹配,会在编译阶段就报错,提高了类型安全性。另外,也支持复杂的映射,如嵌套映射、集合映射等。

对象转换次数

属性个数

BeanUtils耗时

Mapstruct耗时

5千万次

6

14秒

1秒

5千万次

15

36秒

1秒

5千万次

25

55秒

1秒

Mapstruct 依赖

//这是一个坑,lombok 依赖必须在 mapstruct 前面。
//lombok 依赖必须在 mapstruct 前面。
//lombok 依赖必须在 mapstruct 前面。
            <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <!-- jdk8以下就使用mapstruct -->
            <artifactId>mapstruct</artifactId>
            <version>1.5.5.Final</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.5.5.Final</version>
        </dependency>

简单的属性拷贝

下面我们先来看下Mapstruct最简单的使用方式。

当两个对象的属性类型和名称完全相同时,Mapstruct会自动拷贝;假设我们现在需要把UserPo的属性值拷贝到UserEntity中,我们需要做下面几件事情:

  1. 定义UserPo和UserEntity
  2. 定义转换接口
  3. 编写测试main方法

▐ 首先定义UserPo和UserEntity

UserPo和UserEntity的属性类型和名称完全相同。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserPo {

    private Long id;
    private Date gmtCreate;
    private Date createTime;
    private Long buyerId;
    private Long age;
    private String userNick;
    private String userVerified;

}
@Data
public class UserEntity {

    private Long id;
    private Date gmtCreate;
    private Date createTime;
    private Long buyerId;
    private Long age;
    private String userNick;
    private String userVerified;

}

▐ 定义转换接口

定义mapstruct接口,在接口上打上@Mapper注解。

接口中有一个常量和一个方法,常量的值是接口的实现类,这个实现类是Mapstruct默认帮我们实现的,下文会讲到。定义了一个po2entity的转换方法,表示把入参UserPo对象,转换成UserEntity。

注意@Mapper是Mapstruct的注解,不要引错了。

import com.example.msstruct.pojo.UserEntity;
import com.example.msstruct.pojo.UserPo;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface IPersonMapper {
        IPersonMapper Instance = Mappers.getMapper( IPersonMapper.class );
        //用UserPo 转 UserEntity
        UserEntity po2entity(UserPo userPo );
}

▐ 测试类

创建一个UserPo对象,并使用Mapstruct做转化。

UserPo 属性较多,或者UserEntity 属性较多,多可以映射,没有的自动为null

public class MapStructTest {
    public static void main(String[] args) {
        //正常转换,类型和名字都能对应上
        testNormal();
    }

    private static void testNormal() {
        System.out.println("-----------testNormal-----start------");
        UserPo userPo = new UserPo(1L, new Date(), new Date(), 2L, 3L, "test", "testmp");
        System.out.println("1234" + userPo);
        //获取到mapstruct的实例
        IPersonMapper instance = IPersonMapper.Instance;
        System.out.println(instance.po2entity(userPo));
        System.out.println("-----------testNormal-----ent------");

    }
}

▐ 测试结果

可以看到,所有赋值的属性都做了处理,且两边的值都一样,结果符合预期。

在这里插入图片描述
Mapstruct 性能优于 BeanUtils 的原因

Java程序执行的过程,是由编译器先把java文件编译成class字节码文件,然后由JVM去解释执行class文件。Mapstruct正是在java文件到class这一步帮我们实现了转换方法,即做了预处理,提前编译好文件,如果用过lombok的同学一定能理解其好处,通过查看class文件,可以看出IPersonMapper被打上org.mapstruct.Mapper注解后,编译器自动会帮我们生成一个实现类IPersonMapperImpl,并实现了po2entity这个方法,看下面的截图。

▐ IPersonMapperImpl代码

从生成的代码可以看出,转化过程非常简单,只使用了UserPo的get方法和UserEntity的set方法,没有复杂的逻辑处理,清晰明了,所以性能很高

在这里插入图片描述
▐ Spring的BeanUtils源码

BeanUtils部分源码如下,转换的原理是使用的反射,反射的效率相对来说是低的,因为jvm优化在这种场景下有可能无效,所以在对性能要求很高或者经常被调用的程序中,尽量不要使用。我们平时在研发过程中,也会遵守这个原则,非必要,不反射。

从下面的BeanUtils代码中可以看出,转化逻辑非常复杂,有很多的遍历,去获取属性,获取方法,设置方法可访问,然后执行,所以执行效率相对Mapstruct来说,是非常低的。回头看Mapstruct自动生成的实现类,简洁、高效。

private static void copyProperties(Object source, Object target, Class<?> editable, String... ignoreProperties)
      throws BeansException {
 
 
    Assert.notNull(source, "Source must not be null");
    Assert.notNull(target, "Target must not be null");
 
 
    Class<?> actualEditable = target.getClass();
    if (editable != null) {
      if (!editable.isInstance(target)) {
        throw new IllegalArgumentException("Target class [" + target.getClass().getName() +
            "] not assignable to Editable class [" + editable.getName() + "]");
      }
      actualEditable = editable;
    }
    PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
    List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
 
 
    for (PropertyDescriptor targetPd : targetPds) {
      Method writeMethod = targetPd.getWriteMethod();
      if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
        PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
        if (sourcePd != null) {
          Method readMethod = sourcePd.getReadMethod();
          if (readMethod != null &&
              ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
            try {
              if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
                readMethod.setAccessible(true);
              }
              Object value = readMethod.invoke(source);
              if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
                writeMethod.setAccessible(true);
              }
              writeMethod.invoke(target, value);
            }
            catch (Throwable ex) {
              throw new FatalBeanException(
                  "Could not copy property '" + targetPd.getName() + "' from source to target", ex);
            }
          }
        }
      }
    }

属性类型相同名称不同

对于属性名称不同的属性进行处理时,需要使用@Mapping,比如修改UserEntity中的userNick为userNick1,然后进行转换

@Data
public class UserEntity {

    private Long id;
    private Date gmtCreate;
    private Date createTime;
    private Long buyerId;
    private Long age;
    private String userNick1;
    private String userVerified;

}

如果没有映射执行会报错:
在这里插入图片描述

▐ @Mapping注解指定source和target字段名称对应关系

@Mapping(target = “userNick1”, source = “userNick”),此处的意思就是在转化的过程中,将UserPo的userNick属性值赋值给UserEntity的userNick1属性。

import com.example.msstruct.pojo.UserEntity;
import com.example.msstruct.pojo.UserPo;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

@Mapper
public interface IPersonMapper {
        IPersonMapper Instance = Mappers.getMapper( IPersonMapper.class );
        //用UserPo 转 UserEntity
    @Mapping(source = "userNick", target = "userNick1")
        UserEntity po2entity(UserPo userPo );
}

▐ 执行结果

可以看到,正常映射,符合预期。

在这里插入图片描述
▐ 查看class文件

可以看到,Mapstruct帮我们做了处理,把po的userNick属性赋值给了entity的userNick1。

在这里插入图片描述
String转日期&String转数字&忽略某个字端&给默认值等

//时间字符串的模板
@Mapping(target = "createTime", source = "createTime", dateFormat = "yyyy-MM-dd") 
@Mapping(target = "age", source = "age", numberFormat = "#0.00")
@Mapping(target = "id", ignore = true)
@Mapping(target = "userVerified", defaultValue = "defaultValue-2")
import com.example.msstruct.pojo.UserEntity;
import com.example.msstruct.pojo.UserPo;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

@Mapper
public interface IPersonMapper {
        IPersonMapper Instance = Mappers.getMapper( IPersonMapper.class );
        //用UserPo 转 UserEntity
    @Mapping(source = "userNick", target = "userNick1")
    @Mapping(source = "createTime", target = "createTime",dateFormat = "yyyy-MM-dd")
        UserEntity po2entity(UserPo userPo );
}

在这里插入图片描述

设置默认值:

@Mapper
public interface IPersonMapper {
        IPersonMapper Instance = Mappers.getMapper( IPersonMapper.class );
        //用UserPo 转 UserEntity
    @Mapping(source = "userNick", target = "userNick1")
    @Mapping(source = "createTime", target = "createTime",dateFormat = "yyyy-MM-dd")
    @Mapping(target = "userVerified", defaultValue = "defaultValue-2")
        UserEntity po2entity(UserPo userPo );
}

▐ 执行结果
在这里插入图片描述

List类型转化到List型

list类型的实体类UserPo 转成UserEntity类型的实体类

import com.example.msstruct.pojo.UserEntity;
import com.example.msstruct.pojo.UserPo;
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;

import java.util.List;

@Mapper
public interface IPersonMapper {
        IPersonMapper Instance = Mappers.getMapper( IPersonMapper.class );



   List<UserEntity> po2entity(List<UserPo> userPos);

}

▐ 测试方法


import com.example.msstruct.mapstruct.IPersonMapper;
import com.example.msstruct.pojo.UserEntity;
import com.example.msstruct.pojo.UserPo;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author GJ
 * @date 2024/8/16 16:24
 */
public class MapStructTest {
    public static void main(String[] args) {
        //正常转换,类型和名字都能对应上
//        testNormal();
        //list 封装转换
        testList();

    }

    private static void testList() {
        System.out.println("-----------testNormal-----start------");
        Date date = new Date();
        ArrayList<UserPo> userPos = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            UserPo userPo = new UserPo(1L, date, date ,  20L, 10L, "test", "test");
            userPos.add(userPo);
        }
        IPersonMapper instance = IPersonMapper.Instance;
        List<UserEntity> userEntities = instance.po2entity(userPos);
        System.out.println(userEntities);
        System.out.println("-----------testNormal-----ent------");
    }
}

▐ 测试结果

List 封装的结果展示出来
在这里插入图片描述

实体类中嵌套list,填充值

import lombok.Data;

import java.util.Date;
import java.util.List;

@Data
public class UserEntity {

    private Long id;
    private Date gmtCreate;
    private Date createTime;
    private Long buyerId;
    private Long age;
    private String userNick1;
    private String userVerified;
    private List<Account> accounts;

}
import lombok.Data;

@Data
public class Account {
private String id;
private String name;
}

▐ @Mapping 实体中封装List

import com.example.msstruct.pojo.Account;
import com.example.msstruct.pojo.UserEntity;
import com.example.msstruct.pojo.UserPo;
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;

import java.util.List;


@Mapper
public interface IPersonMapper {
        IPersonMapper Instance = Mappers.getMapper( IPersonMapper.class );

accountList 属性名要 和实体类中的 属性名accounts  对应上。
   @Mapping(source = "accountList", target = "accounts")
   UserEntity po2account(List<Account> accountList,UserPo userPo);
}

▐ 测试方法

public class MapStructTest {
    public static void main(String[] args) {
        //正常转换,类型和名字都能对应上
//        testNormal();
        //list 封装转换
//        testList();
        //accountList  封装转换UserEnity
        testAccountList();

    }

    private static void testAccountList() {
        System.out.println("-----------testAccountList-----start------");
        Date date = new Date();
        ArrayList<UserPo> userPos = new ArrayList<>();
        for (int i = 0; i < 1; i++) {
            UserPo userPo = new UserPo(1L, date, date ,  20L, 10L, "test", "test");
            userPos.add(userPo);
        }
        ArrayList<Account> accounts = new ArrayList<>();
        for (int j = 0; j < 10; j++) {
            Account account = new Account();
            account.setId("1");
            account.setName("test");
            accounts.add(account);
        }        
        IPersonMapper instance = IPersonMapper.Instance;
        UserEntity userEntity = instance.po2account(accounts, userPos.get(0));
        System.out.println(userEntity);
        System.out.println("-----------testAccountList-----ent------");
    }
    }

▐ 测试结果

在这里插入图片描述

6、根据枚举类型code–>name

枚举类

public enum TypeEnum {
    /**
     * 类型枚举
     */
    TYPE1("1", "类型1"),
    TYPE2("2", "类型2");
    private String code;
    private String name;
    TypeEnum(String code, String name) {
        this.code = code;
        this.name = name;
    }
    public String getCode() {
        return code;
    }
    public String getName() {
        return name;
    }
    public static String getByCode(String code) {
        for (TypeEnum type : TypeEnum.values()) {
            if (type.getCode().equals(code)) {
                return type.getName();
            }
        }
        return null;
    }

}

@Mapping 映射

   @Mapping(source = "createTime", target = "createTime",dateFormat = "yyyy-MM-dd")
   // @Mapping(target = "userVerified", defaultValue = "defaultValue-2")

//   通过枚举转化  expression ="java(里面填写类名+方法名(参数))"
   @Mapping(target = "name", expression = "java(com.example.msstruct.enums.TypeEnum.getByCode(userPo.getCode()))")
        UserEntity po2entity(UserPo userPo );

测试类

public class MapStructTest {
    public static void main(String[] args) {
        //正常转换,类型和名字都能对应上
        testNormal();


    }


    private static void testNormal() {
        System.out.println("-----------testNormal-----start------");
        Date date = new Date();

        UserPo userPo = new UserPo(1L, date, date ,  20L, 10L, "test", "test","1");
        System.out.println("------" + userPo);
        //获取到mapstruct的实例
        IPersonMapper instance = IPersonMapper.Instance;
        System.out.println(instance.po2entity(userPo));
        System.out.println("-----------testNormal-----ent------");

    }
}

测试结果

在这里插入图片描述


boot集成mapstruct


@Mapper(componentModel = MappingConstants.ComponentModel.SPRING,import= {TypeEnum.class})
public interface IPersonMapper {
      
//   通过枚举转化
   @Mapping(target = "name", expression = "java(TypeEnum.getByCode(userPo.getCode()))")
        UserEntity po2entity(UserPo userPo );


}

解释import 和uses:

import 属性就和java中的import是一样的,导入后在expression中就可以不使用类的全限定名称了。例如你的转换用到了一个静态工具类,那么如果不在import中导入此工具类,那么使用的时候就要全限定名了。

没有使用import 并不是全路径,结果报错
在这里插入图片描述
使用import 返回结果成功
在这里插入图片描述

没有使用import 但添加上全路径名称
在这里插入图片描述

使用uses属性,就像 spring中的依赖注入。

只需将@mapper 中添加一个componentModel =“spring”,将接口注册到spring中,
@Mapper注解的uses属性用于指定自定义的类型转换器或映射器接口,以帮助MapStruct处理复杂的映射场景。

1、映射器接口:一个被@Mapper注解标记的Java接口,用于定义对象之间的映射逻辑,MapStruct会自动生成这个接口的实现。

2、类型转换器类:虽然不是MapStruct的直接概念,但在需要自定义类型转换时可能会用到。在MapStruct中,更常见的是通过映射器接口、@Mapping注解的expression属性、@AfterMapping/@BeforeMapping注解等方式来实现类型转换。

//这个地方也是看别的文章

@Mapper(componentModel = MappingConstants.ComponentModel.SPRING,
        uses = {
            GirlFriendMapper.class
        }
)
public interface ProgramerConvetor {
    //属性之间的映射
    @Mapping(target = "girlFriend", source = "programer")
    ProgramerDto toProgramerDto(Programer programer);
}

但在Programer 属性 转成ProgramerDto 中的 girlFriend ,需要 girlFriendMapper 这个属性注入。

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2023-01-08T21:03:17+0800",
    comments = "version: 1.5.3.Final, compiler: javac, environment: Java 11.0.16.1 (Oracle Corporation)"
)
@Component
public class ProgramerConvetorImpl implements ProgramerConvetor {
     @Autowired
    private GirlFriendMapper girlFriendMapper;

    @Override
    public ProgramerDto toProgramerDto(Programer programer) {
        ProgramerDto programerDto = new ProgramerDto();
        ...
        programerDto.setGirlFriend( girlFriendMapper.toGirlFriendDto( programer ) );
        return programerDto;
    }
 }

测试方法

@RestController
public class MapStructTestController {
    @Autowired
    private  IPersonMapper iPersonMapper;
    @GetMapping("/test")
    public  void test(String[] args) {
        //正常转换,类型和名字都能对应上
        testNormal();
        //list 封装转换
//        testList();
        //accountList  封装转换UserEnity
//        testAccountList();

    }
    private  void testNormal() {
        System.out.println("-----------testNormal-----start------");
        Date date = new Date();
        UserPo userPo = new UserPo(1L, date, date ,  20L, 10L, "test", "test","1");
        System.out.println("------" + userPo);
        //获取到mapstruct的实例
//        IPersonMapper instance = IPersonMapper.Instance;
        System.out.println(iPersonMapper.po2entity(userPo));
        System.out.println("-----------testNormal-----ent------");

    }
}

测试结果

在这里插入图片描述

8、在@mapper中注入对象

目的: 在 映射的 mapper中注入 依赖

实体类

@Data
public class UserEntity {

    private Long id;
    private Date gmtCreate;
    private Date createTime;
    private Long buyerId;
    private Long age;
    private String userNick1;
    private String userVerified;
    private List<Account> accounts;
    private String name;

}
@Data
public class Account {
private String id;
private String name;
}

service

@Service
public class AccountService {
//往account 中赋值
    public List<Account> setAccount() {
        ArrayList<Account> accounts = new ArrayList<>();
        Account account = new Account();
        account.setId("123");
        account.setName("张三");
        accounts.add(account);
        return accounts;
    }
}

测试@Mapper

//需要注入对象使用interface 是不合理的,需要使用abstract 
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING,imports = {TypeEnum.class})
public abstract class IAccountMapper {
    @Autowired
    protected AccountService accountService;

    @Mapping(target = "name", expression = "java(TypeEnum.getByCode(userPo.getCode()))")
    @Mapping(target = "accounts", expression = "java(accountService.setAccount())")
    public abstract UserEntity po2entity(UserPo userPo) ;
}

测试方法

@RestController
public class MapStructTestController {


    @Autowired
    private IAccountMapper accountMapper;

    @GetMapping("/test")
    public  void test(String[] args) {
        //正常转换,类型和名字都能对应上
        testNormal();
    }

  

    private  void testNormal() {
        System.out.println("-----------testNormal-----start------");
        Date date = new Date();
        UserPo userPo = new UserPo(1L, date, date ,  20L, 10L, "test", "test","1");
        System.out.println("------" + userPo);
        //获取到mapstruct的实例
        System.out.println(accountMapper.po2entity(userPo));
        System.out.println("-----------testNormal-----ent------");

    }
}

IAccountMapperImpl 代码

在这里插入图片描述

测试结果
在这里插入图片描述


9、类共有属性,复用

目的: 返回的实体有同样的属性,并且属性值生成同样的方法,可以定义一个注解的形式进行生成

注解定义

import org.mapstruct.Mapping;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

//这个地方引用 random 类,需要在IPersonMapper 引入 这个类。
@Retention(RetentionPolicy.CLASS)
@Mapping(target = "id", expression = "java(Long.parseLong(new Random().nextInt(10) + \"\"))")
public @interface ToEntity {
}

IPersonMapper

import com.example.msstruct.enums.TypeEnum;
import com.example.msstruct.pojo.Account;
import com.example.msstruct.pojo.UserEntity;
import com.example.msstruct.pojo.UserPo;
import com.example.msstruct.pojo.UserPo2;
import org.mapstruct.*;
import org.mapstruct.factory.Mappers;

import java.util.List;
import java.util.Random;



@Mapper(componentModel = MappingConstants.ComponentModel.SPRING, imports = {TypeEnum.class, Random.class})
public interface IPersonMapper {
        IPersonMapper Instance = Mappers.getMapper( IPersonMapper.class );

//   通过枚举转化
   @ToEntity
   @Mapping(target = "name", expression = "java(TypeEnum.getByCode(userPo.getCode()))")
        UserEntity po2entity(UserPo userPo );


    @ToEntity
    UserEntity entity2po(UserPo2 userPo2);

}

IPersonMapperImpl 生成代码

在这里插入图片描述

测试方法

public class MapStructTest {
    public static void main(String[] args) {

        testBeanUtils();


    }

    private  static void testBeanUtils() {
        System.out.println("-----------testNormal-----start------");
        UserPo2 userPo2 = new UserPo2();
        IPersonMapper instance = IPersonMapper.Instance;
        UserEntity userEntity = instance.entity2po(userPo2);
        System.out.println(userEntity);

        System.out.println("-----------testNormal-----mid------");

        UserPo userPo = new UserPo();
        UserEntity userEntity1 = instance.po2entity(userPo);

        System.out.println(userEntity1);

        System.out.println("-----------testNormal-----ent------");

}
}

测试结果
在这里插入图片描述

  • 8
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值