亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Mapstruct?@Mapper?@Mapping?使用小結(jié)

 更新時(shí)間:2023年09月13日 11:56:52   作者:極光雨雨  
這篇文章主要介紹了Mapstruct?@Mapper?@Mapping使用小結(jié),他們用于各個(gè)對(duì)象實(shí)體間的相互轉(zhuǎn)換,例如數(shù)據(jù)庫(kù)底層實(shí)體轉(zhuǎn)為頁(yè)面對(duì)象,Model?轉(zhuǎn)為?DTO,?DTO?轉(zhuǎn)為其他中間對(duì)象,?VO?等等,相關(guān)轉(zhuǎn)換代碼為編譯時(shí)自動(dòng)產(chǎn)生的新文件和代碼,需要的朋友可以參考下

作用

用于各個(gè)對(duì)象實(shí)體間的相互轉(zhuǎn)換,例如數(shù)據(jù)庫(kù)底層實(shí)體 轉(zhuǎn)為頁(yè)面對(duì)象,Model 轉(zhuǎn)為 DTO(data transfer object 數(shù)據(jù)轉(zhuǎn)換實(shí)體), DTO 轉(zhuǎn)為其他中間對(duì)象, VO 等等,相關(guān)轉(zhuǎn)換代碼為編譯時(shí)自動(dòng)產(chǎn)生的新文件和代碼。

兩個(gè)對(duì)象之間相同屬性名的會(huì)被自動(dòng)轉(zhuǎn)換,指定特殊情況時(shí)需要通過(guò)注解在抽象方法上說(shuō)明不同屬性之間的轉(zhuǎn)換。

轉(zhuǎn)換方法一般均為抽象方法,所以這一類(lèi)文件一般使用 接口 類(lèi),或者抽象類(lèi)均可,官方的介紹一般均使用了接口類(lèi)文件來(lái)完成。如果感興趣可以到官網(wǎng)看看

官網(wǎng)鏈接

Maven 依賴(lài)

官方給與的示例配置,建議使用官方推薦的版本

...
<properties>
    <org.mapstruct.version>1.5.2.Final</org.mapstruct.version>
</properties>
...
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
</dependencies>
...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>
...

在本地經(jīng)過(guò)一些實(shí)驗(yàn)后,發(fā)現(xiàn)這樣也可以

<dependencies>
........
    <dependency>
      <groupId>org.mapstruct</groupId>
      <artifactId>mapstruct</artifactId>
      <version>1.4.2.Final</version>
    </dependency>
    <dependency>
      <groupId>org.mapstruct</groupId>
      <artifactId>mapstruct-processor</artifactId>
      <version>1.2.0.Final</version>
    </dependency>
</dependencies>

這里我 IDEA 版本為 2020.1

特別注意,mapstruct 以及 mapstruct-processor 不論哪種形式兩個(gè)都需要同時(shí)存在,mapstruct 提供了注解等,mapstruct-processor 會(huì)在編譯時(shí)將相關(guān)接口文件的實(shí)現(xiàn)類(lèi)生成出來(lái),最終完成想要的映射實(shí)現(xiàn)。

若與 lombok 連用

如果同時(shí)使用了另一個(gè) lombok 代碼生成相關(guān)的依賴(lài),那么需要注意lombok maven 依賴(lài)版本需要在 1.16.16 以上,否則可能會(huì)出現(xiàn)

**No property named “XXX“ exists in source parameter(s). Did you mean “null“?**之類(lèi)的錯(cuò)誤

使用示例

1.基本使用

定義兩個(gè)類(lèi)如下:

這里使用了lombok 實(shí)際上僅僅是簡(jiǎn)化了 get set 以及構(gòu)造方法之類(lèi)的。

如果需要,可以看看另一篇關(guān)于 lombok 的介紹@Data 注解使用 lombok插件學(xué)習(xí)總結(jié)

實(shí)體一DTO

package org.aurora.lombok;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class PersionDTO {
    private Long pId;
    private String name;
    private Integer age;
    private String sex;
    private String address;
    private Float height;
    private Float weight;
    private Date birthDay;
    private String birthLocation;
    private Boolean married;
    private Boolean hasParents;
    private Boolean hasChildren;
    private String describe;
}

其中

@Data 編譯時(shí)幫助實(shí)現(xiàn)了 get set 方法

@AllArgsConstructor 全參構(gòu)造函數(shù)

@NoArgsConstructor 無(wú)參構(gòu)造函數(shù)

@Builder 允許使用 builder 方式構(gòu)造對(duì)象,其實(shí)和構(gòu)造函數(shù)差不多

另一個(gè)實(shí)體 VO:

package org.aurora.lombok;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class PersonVO {
    private Long pId;
    private String name;
    private Integer age;
    private String sex;
    private String des;
    private String birth;
    private String choice;
}

開(kāi)始加入 MapStruct 的轉(zhuǎn)換相關(guān)的,注意這里我定義的是抽象類(lèi),實(shí)際上使用接口類(lèi)也可以先看看正常的接口類(lèi)

package org.aurora.mapstruct;
import org.aurora.lombok.PersionDTO;
import org.aurora.lombok.PersonVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
@Mapper
public interface MyMapper {
    MyMapper INSTANCE = Mappers.getMapper(MyMapper.class);
    @Mapping(source = "describe", target = "des")
    PersonVO transToViewObject(PersionDTO persionDTO);
}

上面可以如下解釋

@Mapper 當(dāng)前類(lèi)認(rèn)為是要執(zhí)行 MapStruct 相關(guān)操作的類(lèi)

@Mapping 為指定某些特殊映射的注解,沒(méi)有指定的內(nèi)容,當(dāng)源對(duì)象與 目標(biāo)對(duì)象擁有一樣的屬性時(shí)會(huì)自動(dòng)轉(zhuǎn)換

INSTANCE 是為了在外面外面調(diào)用該方法, 接口中的屬性默認(rèn)為靜態(tài)屬性所以可以直接調(diào)用到

@Mapping 中 source 為入?yún)?,源?duì)象的屬性名, target 為目標(biāo)對(duì)象的屬性 source 和 target 沒(méi)有順序之分,按自己的來(lái)即可

在這里插入圖片描述

生成代碼如下,注意這些代碼是直接生成到 classes 里面的

package org.aurora.mapstruct;
import javax.annotation.Generated;
import org.aurora.lombok.PersionDTO;
import org.aurora.lombok.PersonVO;
@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2022-08-11T16:24:31+0800",
    comments = "version: 1.2.0.Final, compiler: javac, environment: Java 1.8.0_211 (Oracle Corporation)"
)
public class MyMapperImpl implements MyMapper {
    @Override
    public PersonVO transToViewObject(PersionDTO persionDTO) {
        if ( persionDTO == null ) {
            return null;
        }
        PersonVO personVO = new PersonVO();
        personVO.setDes( persionDTO.getDescribe() );
        personVO.setPId( persionDTO.getPId() );
        personVO.setName( persionDTO.getName() );
        personVO.setAge( persionDTO.getAge() );
        personVO.setSex( persionDTO.getSex() );
        return personVO;
    }
}

在Main 中測(cè)試如下:

    public static void main(String[] args){
    // 其實(shí)就是一個(gè)構(gòu)造方法??梢钥醋鬟B續(xù)的set 屬性。
        PersionDTO persionDTO = PersionDTO.builder().pId(1515435488753L).name("小天").age(-2).sex("male").birthDay(new Date()).address("甘雨胡同十六號(hào)").height(18f).weight(4f)
                .birthLocation("chinese").describe("嗷嗷嗷").married(false).hasChildren(false).hasParents(true).build();
		// 轉(zhuǎn)化
        PersonVO personVO = MyMapper.INSTANCE.transToViewObject(persionDTO);
        System.out.println(personVO.toString());
    }

結(jié)果如下

PersonVO(pId=1515435488753, name=小天, age=-2, sex=male, des=嗷嗷嗷, birth=null, choice=null)

可以看出來(lái),當(dāng)兩個(gè)實(shí)體中的參數(shù)中存在一致的屬性時(shí)會(huì)被自動(dòng)轉(zhuǎn)換,屬性名對(duì)不上如果 @Mapping 沒(méi)有指定的處理方式,則不會(huì)處理,實(shí)際上這一條已經(jīng)適用于大多數(shù)場(chǎng)景。

接下來(lái)看下使用抽象類(lèi)的方式,結(jié)果大同小異

轉(zhuǎn)換類(lèi)如下定義:

package org.aurora.mapstruct;
import org.aurora.lombok.PersionDTO;
import org.aurora.lombok.PersonVO;
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;
import java.text.SimpleDateFormat;
import java.util.Date;
@Mapper
public abstract class AbstractPersonConverter {
    public static final AbstractPersonConverter INSTANCE = Mappers.getMapper(AbstractPersonConverter.class);
    /**
     * persionDTO 轉(zhuǎn)到 PersonVO
     * @param persionDTO
     * @return
     */
    @Mapping(source = "describe", target = "des")
    public abstract PersonVO transToViewObject(PersionDTO persionDTO);
    /**
     * persionDTO 轉(zhuǎn)到  personVO的后置轉(zhuǎn)換處理
     * @param personVO
     * @param persionDTO
     */
    @AfterMapping
    void changeDateIntoStr(@MappingTarget PersonVO personVO, PersionDTO  persionDTO ){
        Date birthDay = persionDTO.getBirthDay();
        if (birthDay != null){
            personVO.setBirth(transDate(birthDay));
        }
    }
    /**
     * 日期轉(zhuǎn)換
     * @param date
     * @return
     */
    String transDate(Date date){
        if (date ==  null){
            return null;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("y-M-d");
        String format = simpleDateFormat.format(date);
        return format;
    }
}

生成代碼如下:

package org.aurora.mapstruct;
import javax.annotation.Generated;
import org.aurora.lombok.PersionDTO;
import org.aurora.lombok.PersonVO;
@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2022-08-11T15:11:27+0800",
    comments = "version: 1.2.0.Final, compiler: javac, environment: Java 1.8.0_211 (Oracle Corporation)"
)
public class AbstractPersonConverterImpl extends AbstractPersonConverter {
    @Override
    public PersonVO transToViewObject(PersionDTO persionDTO) {
        if ( persionDTO == null ) {
            return null;
        }
        PersonVO personVO = new PersonVO();
        personVO.setDes( persionDTO.getDescribe() );
        personVO.setPId( persionDTO.getPId() );
        personVO.setName( persionDTO.getName() );
        personVO.setAge( persionDTO.getAge() );
        personVO.setSex( persionDTO.getSex() );
        changeDateIntoStr( personVO, persionDTO );
        return personVO;
    }
}

其中

2.@AfterMapping @BeforeMapping

為指定某類(lèi)型換為某一類(lèi)型指定的在一般Mapping 結(jié)束后附加的操作@MappingTarget PersonVO personVO 指定了最終轉(zhuǎn)換結(jié)果為 PersonVO 類(lèi)的對(duì)象,personVO 以及 persionDTO 均為入?yún)?,在這里可以做一些自己的額外操作

實(shí)驗(yàn)代碼:

    public static void main(String[] args){
        PersionDTO persionDTO = PersionDTO.builder().pId(1515435488753L).name("小天").age(-2).sex("male").birthDay(new Date()).address("甘雨胡同十六號(hào)").height(18f).weight(4f)
                .birthLocation("chinese").describe("嗷嗷嗷").married(false).hasChildren(false).hasParents(true).build();
        PersonVO personVO = AbstractPersonConverter.INSTANCE.transToViewObject(persionDTO);
        System.out.println(personVO.toString());
    }

最終結(jié)果:

PersonVO(pId=1515435488753, name=小天, age=-2, sex=male, des=嗷嗷嗷, birth=2022-8-11, choice=null)

可以看得出最終的 結(jié)果中對(duì) birth 的特殊操作是成功進(jìn)入了最終的結(jié)果,實(shí)際上這里的時(shí)間轉(zhuǎn)換可以通過(guò) Mapstruct 的注解自帶功能完成。AfterMapping 中支持我們做更多特殊的業(yè)務(wù)操作,@BeforeMapping與 AfterMapping 相反 會(huì)在實(shí)際映射方法前執(zhí)行,但作用一致

3.多個(gè)入?yún)⑥D(zhuǎn)為一個(gè)對(duì)象

上面的方法多添加一個(gè)抽象方法如下:

    @Mapping(source = "persionDTO.describe", target = "des")
    @Mapping(source = "apee.ap", target = "choice")
    public abstract PersonVO transToViewObject(PersionDTO persionDTO, Apee apee);

生成的代碼如下:

    @Override
    public PersonVO transToViewObject(PersionDTO persionDTO, Apee apee) {
        if ( persionDTO == null && apee == null ) {
            return null;
        }
        PersonVO personVO = new PersonVO();
        if ( persionDTO != null ) {
            personVO.setDes( persionDTO.getDescribe() );
            personVO.setPId( persionDTO.getPId() );
            personVO.setName( persionDTO.getName() );
            personVO.setAge( persionDTO.getAge() );
            personVO.setSex( persionDTO.getSex() );
        }
        if ( apee != null ) {
            personVO.setChoice( apee.getAp() );
        }
        changeDateIntoStr( personVO, persionDTO );
        return personVO;
    }

測(cè)試代碼:

    public static void main(String[] args){
        PersionDTO persionDTO = PersionDTO.builder().pId(1515435488753L).name("小天").age(-2).sex("male").birthDay(new Date()).address("甘雨胡同十六號(hào)").height(18f).weight(4f)
                .birthLocation("chinese").describe("嗷嗷嗷").married(false).hasChildren(false).hasParents(true).build();
        Apee apee = new Apee();
        apee.setAp("hahahahahaha");
        PersonVO personVO = AbstractPersonConverter.INSTANCE.transToViewObject(persionDTO, apee);
        System.out.println(personVO.toString());
    }

結(jié)果:

PersonVO(pId=1515435488753, name=小天, age=-2, sex=male, des=嗷嗷嗷, birth=2022-8-11, choice=hahahahahaha)

這里需要注意的是,當(dāng)你的多個(gè)對(duì)象作為入?yún)r(shí),多個(gè)對(duì)象均含有同一個(gè)屬性時(shí)即當(dāng)目標(biāo)對(duì)象與另外多個(gè)入?yún)⒍己幸粋€(gè)或多個(gè)相同屬性時(shí),在mapping 也需要指定,否則不知道拿哪個(gè)屬性會(huì)拋出異常。

4.當(dāng)源屬性沒(méi)有時(shí)指定默認(rèn)值

在Mapping 中添加 default 屬性,給與默認(rèn)值即可,例如:

    @Mapping(source = "persionDTO.describe", target = "des")
    @Mapping(source = "apee.ap", target = "choice", defaultValue = "給個(gè)默認(rèn)值")
    public abstract PersonVO transToViewObject(PersionDTO persionDTO, Apee apee);

生成的代碼

    @Override
    public PersonVO transToViewObject(PersionDTO persionDTO, Apee apee) {
        if ( persionDTO == null && apee == null ) {
            return null;
        }
        PersonVO personVO = new PersonVO();
        if ( persionDTO != null ) {
            personVO.setDes( persionDTO.getDescribe() );
            personVO.setPId( persionDTO.getPId() );
            personVO.setName( persionDTO.getName() );
            personVO.setAge( persionDTO.getAge() );
            personVO.setSex( persionDTO.getSex() );
        }
        if ( apee != null ) {
            if ( apee.getAp() != null ) {
                personVO.setChoice( apee.getAp() );
            }
            else {
                personVO.setChoice( "給個(gè)默認(rèn)值" );
            }
        }
        changeDateIntoStr( personVO, persionDTO );
        return personVO;
    }

執(zhí)行測(cè)試代碼:

    public static void main(String[] args){
        PersionDTO persionDTO = PersionDTO.builder().pId(1515435488753L).name("小天").age(-2).sex("male").birthDay(new Date()).address("甘雨胡同十六號(hào)").height(18f).weight(4f)
                .birthLocation("chinese").describe("嗷嗷嗷").married(false).hasChildren(false).hasParents(true).build();
        Apee apee = new Apee();
//        apee.setAp("hahahahahaha");
        PersonVO personVO = AbstractPersonConverter.INSTANCE.transToViewObject(persionDTO, apee);
        System.out.println(personVO.toString());
    }

結(jié)果:

PersonVO(pId=1515435488753, name=小天, age=-2, sex=male, des=嗷嗷嗷, birth=2022-8-11, choice=給個(gè)默認(rèn)值)

5.一般的類(lèi)型以及日期轉(zhuǎn)換(dateFormat), 數(shù)字轉(zhuǎn)換(numberFormat)

之前的 Apee 定義如下

package org.aurora.lombok;
import java.util.Date;
public class Apee {
    private String ap;
    private String cp;
    private Date timeAA;
    private String strTime;
    public String getCp() {
        return cp;
    }
    public void setCp(String cp) {
        this.cp = cp;
    }
    public Date getTimeAA() {
        return timeAA;
    }
    public void setTimeAA(Date timeAA) {
        this.timeAA = timeAA;
    }
    public String getStrTime() {
        return strTime;
    }
    public void setStrTime(String strTime) {
        this.strTime = strTime;
    }
    public Apee() {
    }
    public Apee(String ap, String cp) {
        this.ap = ap;
        this.cp = cp;
    }
    public String getAp() {
        return ap;
    }
    public void setAp(String ap) {
        this.ap = ap;
    }
    @Override
    public String toString() {
        return "Apee{" +
                "ap='" + ap + '\'' +
                ", cp='" + cp + '\'' +
                ", timeAA=" + timeAA +
                ", strTime='" + strTime + '\'' +
                '}';
    }
}

抽象方法定義如下:

    @Mapping(source = "persionDTO.birthDay", target = "strTime", dateFormat = "yyyy-MM-dd")
    @Mapping(source = "persionDTO.describe", target = "timeAA", dateFormat = "yyyy-MM-dd")
    @Mapping(source = "persionDTO.age", target = "ap")
    public abstract Apee transDateToApee(PersionDTO persionDTO);

生成代碼:

@Override
    public Apee transDateToApee(PersionDTO persionDTO) {
        if ( persionDTO == null ) {
            return null;
        }
        Apee apee = new Apee();
        try {
            if ( persionDTO.getDescribe() != null ) {
                apee.setTimeAA( new SimpleDateFormat( "yyyy-MM-dd" ).parse( persionDTO.getDescribe() ) );
            }
        }
        catch ( ParseException e ) {
            throw new RuntimeException( e );
        }
        if ( persionDTO.getBirthDay() != null ) {
            apee.setStrTime( new SimpleDateFormat( "yyyy-MM-dd" ).format( persionDTO.getBirthDay() ) );
        }
        if ( persionDTO.getAge() != null ) {
            apee.setAp( String.valueOf( persionDTO.getAge() ) );
        }
        return apee;
    }

測(cè)試代碼:

    public static void main(String[] args){
        PersionDTO persionDTO = PersionDTO.builder().pId(1515435488753L).name("小天").age(-2).sex("male").birthDay(new Date()).address("甘雨胡同十六號(hào)").height(18f).weight(4f)
                .birthLocation("chinese").describe("2022-07-08").married(false).hasChildren(false).hasParents(true).build();
        Apee personVO = AbstractPersonConverter.INSTANCE.transDateToApee(persionDTO);
        System.out.println(personVO.toString());
    }

測(cè)試結(jié)果:

Apee{ap='-2', cp='null', timeAA=Fri Jul 08 00:00:00 CST 2022, strTime='2022-08-11'}

可以看的出當(dāng)指定日期格式 dateFormat 時(shí) 不論是從 String 到 Date 還是 Date 到 String 還是一般的類(lèi)型轉(zhuǎn) String 等等都可以自動(dòng)完成適應(yīng),而且我發(fā)現(xiàn)當(dāng)我提供 日期轉(zhuǎn)換方法時(shí)它竟然自動(dòng)引用了我的方法,當(dāng)我刪除時(shí),它使用了自己生成的代碼

在上方轉(zhuǎn)化代碼中我提供了

    /**
     * 日期轉(zhuǎn)換
     * @param date
     * @return
     */
    String transDate(Date date){
        if (date ==  null){
            return null;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("y-M-d");
        String format = simpleDateFormat.format(date);
        return format;
    }

結(jié)果生成的代碼如下:

    @Override
    public Apee transDateToApee(PersionDTO persionDTO) {
        if ( persionDTO == null ) {
            return null;
        }
        Apee apee = new Apee();
        try {
            if ( persionDTO.getDescribe() != null ) {
                apee.setTimeAA( new SimpleDateFormat( "yyyy-MM-dd" ).parse( persionDTO.getDescribe() ) );
            }
        }
        catch ( ParseException e ) {
            throw new RuntimeException( e );
        }
        apee.setStrTime( transDate( persionDTO.getBirthDay() ) );
        if ( persionDTO.getAge() != null ) {
            apee.setAp( String.valueOf( persionDTO.getAge() ) );
        }
        return apee;
    }

官方支持的基本類(lèi)型自動(dòng)轉(zhuǎn)換大致如下:

基本類(lèi)型及其對(duì)應(yīng)的包裝類(lèi)之間:比如, int 和 Integer, float 和 Float, long 和 Long,boolean 和 Boolean 等

任意基本類(lèi)型與任意包裝類(lèi)之間:如 int 和 long, byte 和 Integer 等

所有基本類(lèi)型及包裝類(lèi)與String之間:如 boolean 和 String, Integer 和 String, float 和 String 等枚舉和String之間。

Java大數(shù)類(lèi)型(java.math.BigInteger, java.math.BigDecimal) 和Java基本類(lèi)型(包括其包裝類(lèi))與String之間

數(shù)字轉(zhuǎn)String numberFormat

即 數(shù)字類(lèi)型轉(zhuǎn)String 指定格式下也是支持的

上面方法修改如下:

@Mapping(source = "persionDTO.birthDay", target = "strTime", dateFormat = "yyyy-MM-dd")
    @Mapping(source = "persionDTO.describe", target = "timeAA", dateFormat = "yyyy-MM-dd")
    @Mapping(source = "persionDTO.age", target = "ap", numberFormat = "#0.00歲")
    public abstract Apee transDateToApee(PersionDTO persionDTO);

生成的關(guān)鍵代碼:

if ( persionDTO.getAge() != null ) {
            apee.setAp( new DecimalFormat( "#0.00歲" ).format( persionDTO.getAge() ) );
        }

實(shí)際測(cè)試輸出后:

Apee{ap='-2.00歲', cp='null', timeAA=Fri Jul 08 00:00:00 CST 2022, strTime='2022-8-12'}

6.Expression 表達(dá)式以及 Mappings

Expression 可以用來(lái)替代 source 中的一般屬性,允許直接寫(xiě)入一般的 java 表達(dá)式,即自己提供source 的表達(dá)式,但目前支持 Java 一種語(yǔ)言。

Mappings 可以理解為一個(gè) 普通 Mapping 的父標(biāo)簽,允許里面放多個(gè) Mapping 使用 ,分割與直接寫(xiě) 多個(gè)Mapping 沒(méi)什么區(qū)別,

Expression 與 Mappings 沒(méi)必要連用,這里只是為了同時(shí)介紹

示例如下:

@Mappings({
        @Mapping(expression = "java( new java.util.Date() )", target = "timeAA"),
        @Mapping(source = "persionDTO.age", target = "ap")
    })
    public abstract Apee transExpressionToApee(PersionDTO persionDTO);

生成的代碼如下:

    @Override
    public Apee transExpressionToApee(PersionDTO persionDTO) {
        if ( persionDTO == null ) {
            return null;
        }
        Apee apee = new Apee();
        if ( persionDTO.getAge() != null ) {
            apee.setAp( String.valueOf( persionDTO.getAge() ) );
        }
        apee.setTimeAA( new java.util.Date() );
        return apee;
    }

7.轉(zhuǎn)換時(shí) 不使用對(duì)象中的同名屬性 使用指定參數(shù)作為某一屬性的值

當(dāng)我們兩個(gè)對(duì)象中的屬性一樣,但是并不想使用時(shí)可以如下類(lèi)似定義此時(shí) PersonVO PersionDTO均含有PId 但是我并不想使用對(duì)象中的值而是采用我傳入的值,則如下:

/**
     * 使用其他值
     * @param persionDTO 
     * @param id
     * @return
     */
    @Mapping(source = "persionDTO.describe", target = "des")
    @Mapping(source = "id", target = "PId")
    public abstract PersonVO transToViewObject2(PersionDTO persionDTO, Long id);

注意如果有其他值需要特殊處理時(shí) 需要如上指定參數(shù),否則可能編譯時(shí)出現(xiàn)錯(cuò)誤

生成的代碼

    @Override
    public PersonVO transToViewObject2(PersionDTO persionDTO, Long id) {
        if ( persionDTO == null && id == null ) {
            return null;
        }
        PersonVO personVO = new PersonVO();
        if ( persionDTO != null ) {
            personVO.setDes( persionDTO.getDescribe() );
            personVO.setName( persionDTO.getName() );
            personVO.setAge( persionDTO.getAge() );
            personVO.setSex( persionDTO.getSex() );
        }
        if ( id != null ) {
            personVO.setPId( id );
        }
        return personVO;
    }

8.其他類(lèi)作為屬性時(shí)

與一般的引用類(lèi)型一致,當(dāng)兩個(gè)類(lèi)中都含有某一個(gè)同類(lèi)型的同名屬性時(shí),即使是類(lèi)也會(huì)自動(dòng)映射,如果類(lèi)型一致,但是名稱(chēng)不一致,則指定名稱(chēng)后依舊會(huì)自動(dòng)映射上面的兩個(gè)類(lèi)中添加同一類(lèi)型的一個(gè)類(lèi)如下:

在這里插入圖片描述

在這里插入圖片描述

轉(zhuǎn)換方法如下定義:

@Mapping(source = "describe", target = "des")
    @Mapping(source = "apee", target = "apee2")
    public abstract PersonVO transToViewObject(PersionDTO persionDTO);

生成代碼如下

    @Override
    public PersonVO transToViewObject(PersionDTO persionDTO) {
        if ( persionDTO == null ) {
            return null;
        }
        PersonVO personVO = new PersonVO();
        personVO.setApee2( persionDTO.getApee() );
        personVO.setDes( persionDTO.getDescribe() );
        personVO.setPId( persionDTO.getPId() );
        personVO.setName( persionDTO.getName() );
        personVO.setAge( persionDTO.getAge() );
        personVO.setSex( persionDTO.getSex() );
        return personVO;
    }

9.逆映射

即 一個(gè)文件內(nèi),兩個(gè)類(lèi)之間互相轉(zhuǎn)換映射時(shí)其實(shí)只要寫(xiě)好其中一個(gè)映射,另一個(gè)可以通過(guò)注解繼承原有映射配置,即原有的 target 與 source 會(huì)互換

    @Mapping(source = "describe", target = "des")
    @Mapping(source = "apee", target = "apee2")
    public abstract PersonVO transToViewObject(PersionDTO persionDTO);
    @InheritInverseConfiguration
    public abstract PersionDTO transToViewObject(PersonVO personVO);

生成代碼:

    @Override
    public PersonVO transToViewObject(PersionDTO persionDTO) {
        if ( persionDTO == null ) {
            return null;
        }
        PersonVO personVO = new PersonVO();
        personVO.setApee2( persionDTO.getApee() );
        personVO.setDes( persionDTO.getDescribe() );
        personVO.setPId( persionDTO.getPId() );
        personVO.setName( persionDTO.getName() );
        personVO.setAge( persionDTO.getAge() );
        personVO.setSex( persionDTO.getSex() );
        return personVO;
    }
    @Override
    public PersionDTO transToViewObject(PersonVO personVO) {
        if ( personVO == null ) {
            return null;
        }
        PersionDTO persionDTO = new PersionDTO();
        persionDTO.setApee( personVO.getApee2() );
        persionDTO.setDescribe( personVO.getDes() );
        persionDTO.setPId( personVO.getPId() );
        persionDTO.setName( personVO.getName() );
        persionDTO.setAge( personVO.getAge() );
        persionDTO.setSex( personVO.getSex() );
        return persionDTO;
    }

10.支持注入spring

在mapper 上添加注解 類(lèi)似如下:

在這里插入圖片描述

之后該類(lèi)可通過(guò) @Autowired 注入方式引入到文件中

11. 自定義映射 ,list, Map, 枚舉

以下四種映射案例參考了其他文章的代碼參考博客

自定義映射 @Named

// 自定義的映射方法:轉(zhuǎn)換boolen為String時(shí),做一些判斷然后返回對(duì)應(yīng)的值。
@Named("DoneFormater")
public class DoneFormater {
    @Named("DoneFormater")
    public String toStr(Boolean isDone) {
        if (isDone) {
            return "已完成";
        } else {
            return "未完成";
        }
    }
    @Named("DoneDetailFormater")
    public String toDetail(Boolean isDone) {
        if (isDone) {
            return "該產(chǎn)品已完成";
        } else {
            return "該產(chǎn)品未完成";
        }
    }
    public Boolean toBoolean(String str) {
        if (str.equals("已完成")) {
            return true;
        } else {
            return false;
        }
    }
}
// 通過(guò)uses 來(lái)導(dǎo)入上面我們寫(xiě)的 自定義映射方法
@Mapper( uses = {DoneFormater.class})
public interface ObjectQualiferMapper {
    ObjectQualiferMapper INSTANCE = Mappers.getMapper(ObjectQualiferMapper.class);
    // 當(dāng)有多個(gè)方法 擁有一樣的參數(shù)和返回類(lèi)型時(shí),需要指定使用其中的哪一個(gè),使用qualifiedByName指定
    @Mapping(source = "isDone", target = "isDone", qualifiedByName = "DoneDetailFormater")
    ProductDTO toDto(Product product);
}

List 映射

@Mapper(componentModel = "spring")
public interface UserMapping {
    /**
     * Student 轉(zhuǎn)化為 User
     * @param Student
     * @return
     */
     User studentToUser(Student student);
    // 	當(dāng)執(zhí)行 下面這個(gè)List的轉(zhuǎn)換時(shí),會(huì)遍歷list: students,
   	//  然后自動(dòng)調(diào)用上面的Student轉(zhuǎn)User的轉(zhuǎn)換方法,來(lái)進(jìn)行轉(zhuǎn)換
     /**
     * Students 轉(zhuǎn)化為 Users
     * @param Students
     * @return
     */
     List<user> studentsToUsers(List<student> students);
}

map 映射

@Mapper
public interface MapMapper {
    MapMapper INSTANCE = Mappers.getMapper(MapMapper.class);
    @MapMapping(valueDateFormat = "yyyy-MM-dd HH:mm:ss")
    Map<string, string=""> toDTO(Map<long, date=""> map);
}

枚舉

public enum E1 {
    E1_1,
    E1_2,
    E1_3
}
public enum E2 {
    E2_1,
    E2_2,
    E2_3
}

映射方法:使用@ValueMappings和@ValueMapping ,可以理解成是用if判斷枚舉值,然后返回對(duì)應(yīng)結(jié)果

@Mapper
public interface DataEnumMapper {
    DataEnumMapper INSTANCE = Mappers.getMapper(DataEnumMapper.class);
    @ValueMappings({
            @ValueMapping(target = "E1_1", source = "E2_1"),
            @ValueMapping(target = "E1_2", source = "E2_2"),
            @ValueMapping(target = MappingConstants.NULL, source = "E2_3") //轉(zhuǎn)換成null
    })
    E1 toDTO(E2 e2);
}

Final. 其他問(wèn)題

出現(xiàn)問(wèn)題 Couldn’t retrieve @Mapper annotation

可能是 項(xiàng)目中使用了swagger,swagger里面也包含mapstruct,排除掉就好

<dependency>
    <groupid>io.springfox</groupid>
    <artifactid>springfox-swagger2</artifactid>
    <version>${swagger2.version}</version>
    <scope>compile</scope>
    <exclusions>
        <exclusion>
          <groupid>org.mapstruct</groupid>
          <artifactid>mapstruct</artifactid>
        </exclusion>
    </exclusions>
</dependency>

也可能是 導(dǎo)入mapstruct項(xiàng)目時(shí),同時(shí)使用了 mapstruct-jdk8 和 mapstruct-processor 但版本不一致,將版本號(hào)改為一樣即可

更多詳細(xì)說(shuō)明參見(jiàn)官網(wǎng)說(shuō)明文檔

https://mapstruct.org/documentation/stable/reference/html/#defining-mapper

到此這篇關(guān)于Mapstruct @Mapper @Mapping 使用介紹以及總結(jié)的文章就介紹到這了,更多相關(guān)Mapstruct @Mapper @Mapping 使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解如何使用Jersey客戶(hù)端請(qǐng)求Spring Boot(RESTFul)服務(wù)

    詳解如何使用Jersey客戶(hù)端請(qǐng)求Spring Boot(RESTFul)服務(wù)

    本篇文章主要介紹了詳解如何使用Jersey客戶(hù)端請(qǐng)求Spring Boot(RESTFul)服務(wù),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • 解決使用this.getClass().getResource()獲取文件時(shí)遇到的坑

    解決使用this.getClass().getResource()獲取文件時(shí)遇到的坑

    這篇文章主要介紹了解決使用this.getClass().getResource()獲取文件時(shí)遇到的坑問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 詳細(xì)說(shuō)明關(guān)于Java的數(shù)據(jù)庫(kù)連接(JDBC)

    詳細(xì)說(shuō)明關(guān)于Java的數(shù)據(jù)庫(kù)連接(JDBC)

    這篇文章主要介紹了詳細(xì)說(shuō)明關(guān)于Java的數(shù)據(jù)庫(kù)連接JDBC,JDBC是用Java語(yǔ)言向數(shù)據(jù)庫(kù)發(fā)送SQL語(yǔ)句,需要的朋友可以參考下面文章內(nèi)容
    2021-09-09
  • Java使用Ehcache緩存框架的技術(shù)指南

    Java使用Ehcache緩存框架的技術(shù)指南

    Ehcache 是 Java 平臺(tái)下一個(gè)開(kāi)源、高性能的分布式緩存框架,常用于提高系統(tǒng)性能和可擴(kuò)展性,它能夠幫助開(kāi)發(fā)者緩存頻繁訪問(wèn)的數(shù)據(jù),從而減少對(duì)數(shù)據(jù)庫(kù)和其他持久化存儲(chǔ)的訪問(wèn)壓力,本文給大家介紹了Java使用Ehcache緩存框架的技術(shù)指南,需要的朋友可以參考下
    2025-03-03
  • 詳解SpringMVC中的異常處理

    詳解SpringMVC中的異常處理

    這篇文章主要介紹了SpringMVC中的異常處理的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用SpringMVC,感興趣的朋友可以了解下
    2021-03-03
  • JAVA構(gòu)造器是否為靜態(tài)方法你知道嗎

    JAVA構(gòu)造器是否為靜態(tài)方法你知道嗎

    這篇文章主要為大家詳細(xì)介紹了JAVA構(gòu)造器是否為靜態(tài)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • Java繼承的實(shí)現(xiàn)與繼承限制分析

    Java繼承的實(shí)現(xiàn)與繼承限制分析

    這篇文章主要介紹了Java繼承的實(shí)現(xiàn)與繼承限制,結(jié)合具體實(shí)例形式分析了Java繼承的定義、實(shí)現(xiàn)以及繼承的相關(guān)限制,需要的朋友可以參考下
    2019-01-01
  • Java8新特性之新日期時(shí)間庫(kù)的使用教程

    Java8新特性之新日期時(shí)間庫(kù)的使用教程

    這篇文章主要給大家介紹了關(guān)于Java8新特性之新日期時(shí)間庫(kù)使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java枚舉之EnumSet詳解

    Java枚舉之EnumSet詳解

    這篇文章主要介紹了Java枚舉之EnumSet詳解,使用時(shí)進(jìn)行與或運(yùn)算,但是定義多了之后,會(huì)很亂、臃腫,編寫(xiě)容易出錯(cuò),EnumSet可以實(shí)現(xiàn)類(lèi)似的功能,且使用起來(lái)很簡(jiǎn)潔,需要的朋友可以參考下
    2023-12-12
  • 使用Java實(shí)現(xiàn)驗(yàn)證碼程序

    使用Java實(shí)現(xiàn)驗(yàn)證碼程序

    這篇文章主要為大家詳細(xì)介紹了使用Java實(shí)現(xiàn)驗(yàn)證碼程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04

最新評(píng)論