mapstruct 實體轉換及List轉換,@Mapper注解轉換


   本文參考  
         https://blog.csdn.net/u012373815/article/details/88367456 
         
 主要是為了自己使用方便查詢。 這些都是我平時用到了,大家有什么好方法或者有什么更多知識,希望大家不吝賜教

開發中,我們經常需要將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())"),

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM