ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

mapstruct 实体转换及List转换,@Mapper注解转换

2021-01-19 11:31:05  阅读:353  来源: 互联网

标签:Mapper 转换 student mapstruct Mapping private User Student target


mapstruct 实体转换及List转换,@Mapper注解转换

开发中,我们经常需要将PO转DTO、DTO转PO等一些实体间的转换。比较出名的有BeanUtil 和ModelMapper等,它们使用简单,但是在稍显复杂的业务场景下力不从心。MapStruct这个插件可以用来处理domin实体类与model类的属性映射,可配置性强。只需要定义一个 Mapper 接口,MapStruct 就会自动实现这个映射接口,避免了复杂繁琐的映射实现。MapStruct官网地址:http://mapstruct.org/

本文类型简单包含四方面:

(1)属性名称不对应

(2)list集合转换

(3)字段类型不对应

(4)多个来源实体转换成一个参数实体

引入依赖

<dependency>
     <groupId>org.mapstruct</groupId>
     <artifactId>mapstruct-jdk8</artifactId>
     <version>1.1.0.Final</version>
</dependency>

需求

我们假设有学生student 类 需要转换成 用户 user 类,将学生信息存入用户信息库

此时Student 类内容如下:

public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;//setters, getters, toString()  方法此处省略不写,但是实际开发需要写的哦 
}

此时User 类内容如下

public class User {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;//setters, getters, toString() 方法此处省略不写,但是实际开发需要写的哦  }

 

普通转换model

此时 Student 和 User 的属性名字都相同那么转换接口就是

import org.mapstruct.Mapper;

@Mapper(componentModel = "spring")
public interface UserMapping {

    /**
     * Student 转化为 User
     * @param Student
     * @return
     */
     User studentToUser(Student student);
}

程序运行前要先编译 mvn clean compile , 从而mapstruct框架生成UserMappingImpl 实现类。

特殊转换model

(1)属性名称不对应,如果 User 和 Student 的属性名称不对应例如:

此时Student 类内容如下:

public class Student {
    private Integer id;
    private String sname;
    private Integer age;
    private String sex;
    
      //setters, getters, toString()  方法此处省略不写,但是实际开发需要写的哦 
      }

 此时User 类内容如下:

public class User {
       private Integer id;
    private String uname;
    private Integer age;
    private String sex;
    
   //setters, getters, toString()  方法此处省略不写,但是实际开发需要写的哦 

  }

那么转换接口为

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;

@Mapper(componentModel = "spring")
public interface UserMapping {

    /**
     * Student 转化为 User
     * @param Student
     * @return
     */
     @Mappings({
            @Mapping(target = "uname", source = "sname")
          // 多个属性不对应可以用 "," 隔开编写多个@Mapping
          // ,@Mapping(target = "uname", source = "sname")
    })
     User studentToUser(Student student);
}

(2) 转换集合list
当user 和 student 都是集合形式list 时应当如下转换
转化 List<> 集合时必须有 实体转化,因为在实现中,List 转换是 for循环调用 实体转化的。所以当属性名不对应时,应该在 实体转化进行 @Mappings 的属性名映射配置,然后list的转换也会继承这和属性的映射。

例如 属性名相同

import org.mapstruct.Mapper;

@Mapper(componentModel = "spring")
public interface UserMapping {

    /**
     * Student 转化为 User
     * @param Student
     * @return
     */
     User studentToUser(Student student);
     
     /**
     * Students 转化为 Users
     * @param Students
     * @return
     */
     List<User> studentsToUsers(List<Student> students);

属性名不同:

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;

@Mapper(componentModel = "spring")
public interface UserMapping {

    /**
     * Student 转化为 User
     * @param Student
     * @return
     */
     @Mappings({
            @Mapping(target = "uname", source = "sname")
          // 多个属性不对应可以用 "," 隔开编写多个@Mapping
          // ,@Mapping(target = "uname", source = "sname")
    })
     User studentToUser(Student student);
     
     
    /**
     * 此时 studentsToUsers 的实现为循环调用 studentToUser 并继承了 studentToUser 的属性映射
     * Students 转化为 Users
     * @param Students
     * @return
     */
     List<User> studentsToUsers(List<Student> students);
}

展示 自动生成的 UserMappingImpl 实现(此类为 执行 mvn clean compile 后自动生成)

@Component

public class UserMappingImpl implements UserMapping {

    @Override

    public User studentToUser(student student) {

        if ( student == null ) {

            return null;
        }

        User user = new User();

        User.setId(student.getId() );
        User.setName(student.getName() );
        // 如果配置了属性映射则为
        //User.setUname(student.getSname() );
        
        User.setSex(student.getSex() );
        User.setAge(student.getAge() );
        return user;
    }

    @Override

    public List<User> studentsToUsers(List<student> students) {

        if ( students == null ) {

            return null;
        }

        List<User> list = new ArrayList<User>();

        for ( student student : students ) {

            list.add( studentToUser( student ) );
        }

        return list;
    }
}

(3)字段类型不对应

  字符串转时间,或者时间转字符串,都是用后面的dateFormat值为时间格式

    @Mappings({
            @Mapping(target = "createTime", source = "createTimeStr", dateFormat = "yyyy-MM-dd~hh:mm:ss") 
            // 多个属性不对应可以用 "," 隔开编写多个@Mapping
    }) 
    User studentToUser(Student student);

字段类型不对应,比如说user 类的sex字段类型改为boolean
此时User 类内容如下:

public class User {
    private Integer id;
    private String uname;
    private Integer age;
    private boolean sex;
    
   //setters, getters, toString()  方法此处省略不写,但是实际开发需要写的哦 

  }

Mappings中qualifiedByName属性可以取由@Named声明的名称

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;

@Mapper(componentModel = "spring")
public interface UserMapping {

    /**
     * Student 转化为 User
     * @param Student
     * @return
     */
     @Mappings({
            @Mapping(target = "uname", source = "sname",qualifiedByName= "booleanToString")
// 多个属性不对应可以用 "," 隔开编写多个@Mapping // ,
     @Mapping(target = "uname", source = "sname") }) 
    User studentToUser(Student student); 

    @Named("booleanToString")
    default String booleanToString(boolean value){  
      if(value){ 
          return "男"; 
       }   
         return "女"; 
    }
}

 有的时候有一个额外的转换方法多个mapping类文件都要用到,所以肯定有写一个工具类,mapping引用外部的方法

public class Utils{
    @Named("booleanToString")
    default String booleanToString(boolean value){ 
       if(value){ 
          return "男"; 
       } 
       return "女"; 
    }
}
@Mapper(componentModel = "spring",uses=Utils.class)
public interface UserMapping {

    /**
     * Student 转化为 User
     * @param Student
     * @return
     */
     @Mappings({
            @Mapping(target = "uname", source = "sname",qualifiedByName = "booleanToString")
    }) 
  User studentToUser(Student student); 
}

也可以直接使用expression

@Mappings({
            @Mapping(target = "uname",expression = "java(booleanToString(student.getSname()))")
// 多个属性不对应可以用 "," 隔开编写多个@Mapping // ,@Mapping(target = "uname", source = "sname") 
}) 

(4) 多个来源实体转换成一个参数实体

@Mappings({
    @Mapping(target = "chartName", source = "chart.name"), 
    @Mapping(target = "title", source = "song.title"), 
    @Mapping(target = "artistName", source = "song.artist.name"), 
    @Mapping(target = "recordedAt", source = "song.artist.label.studio.name"), 
    @Mapping(target = "city", source = "song.artist.label.studio.city"), 
    @Mapping(target = "position", source = "position") })
    ChartEntry map(Chart chart, Song song, Integer position);

(5)有一些参数不是来自传入参数,而是默认是一些外部的枚举类或者常量类数据,

  就可以在mapper中声明要导入的外部枚举类或者常量类,

@Mapper(componentModel = "spring",
        unmappedTargetPolicy = ReportingPolicy.IGNORE,
        imports = {StringUtils.class,
                UserConsts.class,
                UserStatusEnum.class
})
@Mapping(target = "key",expression = "java( UserConsts.FULL_GIFT)"),
@Mapping(target = "status",expression = "java(UserStatusEnum.VALID_STATUS_NO.getCode())"),

 

标签:Mapper,转换,student,mapstruct,Mapping,private,User,Student,target
来源: https://blog.csdn.net/qq_34287953/article/details/112802225

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有