1. 程式人生 > 其它 >MapStruct文件(九)——高階對映選項

MapStruct文件(九)——高階對映選項

技術標籤:mapstructjava

目錄

8.1、對映配置繼承

8.2、逆對映

8.3、共享配置

8.3.1、MappingInheritanceStrategy.EXPLICIT

8.3.2、MappingInheritanceStrategy.AUTO_INHERIT_FROM_CONFIG

8.3.3、MappingInheritanceStrategy.AUTO_INHERIT_REVERSE_FROM_CONFIG

8.3.4、MappingInheritanceStrategy.AUTO_INHERIT_ALL_FROM_CONFIG


8.1、對映配置繼承

@InheritConfiguration

可以繼承@Mapping@BeanMapping@IterableMapping的對映規則。

@InheritConfiguration註解的方法上,有需要對映的欄位,它會搜尋有相同配置的對映,找到了直接複用此對映;若找到多個方法上都有滿足此對映的配置,需要制定@InheritConfiguration#name的值,制定繼承方法的對映。


@Data
@ToString
public class TestPO {

    private String name;

}
 
@Data
@ToString
public class TestBO {

    private String nickName;


}
 
@Data
public class TestTwoBO {

    private String realName;
}


@Mapper
public interface TestMapper {

    @Mapping(target = "nickName", source = "name", defaultValue = "nickName")
    TestBO toTestBO(TestPO testPO);

    @Mapping(target = "nickName", source = "name", defaultValue = "realName")
    TestBO toTestTwoBO(TestPO testPO);

    @InheritConfiguration(name = "toTestTwoBO")
    TestBO toTestThreeBO(TestPO testPO);

}
 
@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public TestBO toTestBO(TestPO testPO) {
        if ( testPO == null ) {
            return null;
        }

        TestBO testBO = new TestBO();

        if ( testPO.getName() != null ) {
            testBO.setNickName( testPO.getName() );
        }
        else {
            testBO.setNickName( "nickName" );
        }

        return testBO;
    }

    @Override
    public TestBO toTestTwoBO(TestPO testPO) {
        if ( testPO == null ) {
            return null;
        }

        TestBO testBO = new TestBO();

        if ( testPO.getName() != null ) {
            testBO.setNickName( testPO.getName() );
        }
        else {
            testBO.setNickName( "realName" );
        }

        return testBO;
    }

    @Override
    public TestBO toTestThreeBO(TestPO testPO) {
        if ( testPO == null ) {
            return null;
        }

        TestBO testBO = new TestBO();

        if ( testPO.getName() != null ) {
            testBO.setNickName( testPO.getName() );
        }
        else {
            testBO.setNickName( "realName" );
        }

        return testBO;
    }
}

toTestThreeBO的實現方法在設定nickName時,繼承的toTestTwoBO方法的對映配置。


8.2、逆對映

當我們定義了一種物件到另一種物件的對映後,可以通過@InheritInverseConfiguration直接進行逆對映。


@Data
@ToString
public class TestPO {

    private Long id;

    private String nameString;

    private BigDecimal priceString;

    private Date createTimeString;

}


@Mapper
public interface TestMapper {

    @Mapping(target = "price", source = "priceString", defaultValue = "-1")
    @Mapping(target = "name", source = "nameString")
    @Mapping(target = "createTime", source = "createTimeString", ignore = true)
    TestBO  toTestBO(TestPO testPO);

    @InheritInverseConfiguration
    @Mapping(target = "nameString", constant = "namePO")
    TestPO  toTestBO(TestBO testBO);

}


@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public TestBO toTestBO(TestPO testPO) {
        if ( testPO == null ) {
            return null;
        }

        TestBO testBO = new TestBO();

        if ( testPO.getPriceString() != null ) {
            testBO.setPrice( testPO.getPriceString().toString() );
        }
        else {
            testBO.setPrice( "-1" );
        }
        testBO.setName( testPO.getNameString() );
        testBO.setId( testPO.getId() );

        return testBO;
    }

    @Override
    public TestPO toTestBO(TestBO testBO) {
        if ( testBO == null ) {
            return null;
        }

        TestPO testPO = new TestPO();

        if ( testBO.getPrice() != null ) {
            testPO.setPriceString( new BigDecimal( testBO.getPrice() ) );
        }
        testPO.setId( testBO.getId() );

        testPO.setNameString( "namePO" );

        return testPO;
    }
}

可以看到實現的toTestBO方法中的price->priceString使用的就是toTestPOpriceString->price的逆對映,但是正對映的@Mapping#expression#defaultExpression#defaultValue#constant會被逆對映忽略,就如其中的預設值“-1”在逆對映中不存在;此外某個欄位的逆對映可以被ignoreexpressionconstant覆蓋,就如name->nameString;在正對映的createTimeString->createTime上設定了ignore,若此時同時制定了source,則逆對映會繼承ignore,不用再重新設定。

@InheritConfiguration的優先順序高於@InheritInverseConfiguration


8.3、共享配置

@MapperConfig註解的介面就是共享配置,可以在@Mapper#config指定共享配置,@MapperConfig中的屬性和@Mapper相同,@Mapper中的屬性會覆蓋@MapperConfig。

共享配置中可以設定原型對映,也可以是父類對映,再通過@MapperConfig、@MappermappingInheritanceStrategy就可以實現原型對映的繼承。

mappingInheritanceStrategy的值有:

MappingInheritanceStrategy.EXPLICIT:預設,要想繼承原型對映必須使用@InheritConfiguration或@InheritInverseConfiguration註解方法,且此方法的源型別和目標型別要能賦予原型對映型別;

MappingInheritanceStrategy.AUTO_INHERIT_FROM_CONFIG:不需要@InheritConfiguration註解方法,只需要滿足型別條件就能繼承,但只能是正對映

MappingInheritanceStrategy.AUTO_INHERIT_REVERSE_FROM_CONFIG:不需要@InheritInverseConfiguration註解方法,只需要滿足型別條件就能繼承,但只能是逆對映

MappingInheritanceStrategy.AUTO_INHERIT_ALL_FROM_CONFIG:不需要@InheritInverseConfiguration註解方法,只需要滿足型別條件就能繼承,正/逆對映都可以

以上也都要注意對映型別衝突,衝突同樣需要指明name屬性。


@Data
@ToString
public class BaseBO {

    private Long id;

    private String name;

    private String createTimeString;
}


@MapperConfig
public interface BaseConfig {

    @Mapping(target = "createTimeString", source = "createTime")
    BaseBO toTestBaseBO(BasePO basePO);

}

8.3.1、MappingInheritanceStrategy.EXPLICIT


@Mapper(config = BaseConfig.class, mappingInheritanceStrategy = MappingInheritanceStrategy.EXPLICIT)
public interface TestMapper {

    @InheritConfiguration
    void updateBO(TestFourPO testFourPO, @MappingTarget TestSixBO testSixBO);

    @InheritInverseConfiguration(name = "toTestBaseBO")
    void updatePO(TestSixBO testSixBO, @MappingTarget TestFourPO testFourPO);

}
 
@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public void updateBO(TestFourPO testFourPO, TestSixBO testSixBO) {
        if ( testFourPO == null ) {
            return;
        }

        if ( testFourPO.getCreateTime() != null ) {
            testSixBO.setCreateTimeString( new SimpleDateFormat().format( testFourPO.getCreateTime() ) );
        }
        else {
            testSixBO.setCreateTimeString( null );
        }
        testSixBO.setId( testFourPO.getId() );
        testSixBO.setName( testFourPO.getName() );
    }

    @Override
    public void updatePO(TestSixBO testSixBO, TestFourPO testFourPO) {
        if ( testSixBO == null ) {
            return;
        }

        try {
            if ( testSixBO.getCreateTimeString() != null ) {
                testFourPO.setCreateTime( new SimpleDateFormat().parse( testSixBO.getCreateTimeString() ) );
            }
            else {
                testFourPO.setCreateTime( null );
            }
        }
        catch ( ParseException e ) {
            throw new RuntimeException( e );
        }
        testFourPO.setId( testSixBO.getId() );
        testFourPO.setName( testSixBO.getName() );
    }
}

共享配置的原型對映並不會生成單獨的實現方法。

雖然預設繼承策略支援正/逆,但是引入共享配置,且mapper中正對映能繼承原型對映的情況下,再設定逆對映方法,就必須制定name屬性,否則同樣有衝突報錯。

8.3.2、MappingInheritanceStrategy.AUTO_INHERIT_FROM_CONFIG


@Mapper(config = BaseConfig.class, mappingInheritanceStrategy = MappingInheritanceStrategy.AUTO_INHERIT_FROM_CONFIG)
public interface TestMapper {

    void updateBO(TestFourPO testFourPO, @MappingTarget TestSixBO testSixBO);

}
 
@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public void updateBO(TestFourPO testFourPO, TestSixBO testSixBO) {
        if ( testFourPO == null ) {
            return;
        }

        if ( testFourPO.getCreateTime() != null ) {
            testSixBO.setCreateTimeString( new SimpleDateFormat().format( testFourPO.getCreateTime() ) );
        }
        else {
            testSixBO.setCreateTimeString( null );
        }
        testSixBO.setId( testFourPO.getId() );
        testSixBO.setName( testFourPO.getName() );
    }
}

8.3.3、MappingInheritanceStrategy.AUTO_INHERIT_REVERSE_FROM_CONFIG


@Mapper(config = BaseConfig.class, mappingInheritanceStrategy = MappingInheritanceStrategy.AUTO_INHERIT_ALL_FROM_CONFIG)
public interface TestMapper {

    void updatePO(TestSixBO testSixBO, @MappingTarget TestFourPO testFourPO);

}
 
@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public void updatePO(TestSixBO testSixBO, TestFourPO testFourPO) {
        if ( testSixBO == null ) {
            return;
        }

        try {
            if ( testSixBO.getCreateTimeString() != null ) {
                testFourPO.setCreateTime( new SimpleDateFormat().parse( testSixBO.getCreateTimeString() ) );
            }
            else {
                testFourPO.setCreateTime( null );
            }
        }
        catch ( ParseException e ) {
            throw new RuntimeException( e );
        }
        testFourPO.setId( testSixBO.getId() );
        testFourPO.setName( testSixBO.getName() );
    }
}

8.3.4、MappingInheritanceStrategy.AUTO_INHERIT_ALL_FROM_CONFIG


@Mapper(config = BaseConfig.class, mappingInheritanceStrategy = MappingInheritanceStrategy.AUTO_INHERIT_ALL_FROM_CONFIG)
public interface TestMapper {

    void updateBO(TestFourPO testFourPO, @MappingTarget TestSixBO testSixBO);

    void updatePO(TestSixBO testSixBO, @MappingTarget TestFourPO testFourPO);

}

@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public void updateBO(TestFourPO testFourPO, TestSixBO testSixBO) {
        if ( testFourPO == null ) {
            return;
        }

        if ( testFourPO.getCreateTime() != null ) {
            testSixBO.setCreateTimeString( new SimpleDateFormat().format( testFourPO.getCreateTime() ) );
        }
        else {
            testSixBO.setCreateTimeString( null );
        }
        testSixBO.setId( testFourPO.getId() );
        testSixBO.setName( testFourPO.getName() );
    }

    @Override
    public void updatePO(TestSixBO testSixBO, TestFourPO testFourPO) {
        if ( testSixBO == null ) {
            return;
        }

        try {
            if ( testSixBO.getCreateTimeString() != null ) {
                testFourPO.setCreateTime( new SimpleDateFormat().parse( testSixBO.getCreateTimeString() ) );
            }
            else {
                testFourPO.setCreateTime( null );
            }
        }
        catch ( ParseException e ) {
            throw new RuntimeException( e );
        }
        testFourPO.setId( testSixBO.getId() );
        testFourPO.setName( testSixBO.getName() );
    }
}