基于grpc从零开始搭建一个准生产分布式应用(6) - 03 - MapStruct高级映射

一、对象工厂

在映射成目标对象时,创建目标对象实例,可以使用@ObjectFactory注解的方法取代调用默认的构造方法创建目标对象,工厂方法可以是无参返回类型是目标类型的方法,无参的工厂方法可以不设置@ObjectFactory注解;或有参返回类型是目标类型的方法,参数可以用@TargetType或@Context注解。

  • 为避免返回类型有泛型时的匹配错误,特别是继承List的类的情况下,不建议使用无参的工厂方法。
  • 例如protobuf中的repeated·string生成的ProtocolStringList要在CollectionMappingStrategy.ACCESSOR_ONLY策略下使用。

1.1、自定义工厂@ObjectFactory

可用来生成默认source。

@Data
public class TestFivePO {
    private TestFourPO test;
    private TestPO testPO;
}
@Mapper
public class BaseMapper {
    @ObjectFactory-------注解
    public TestSixBO createSixBO() {
        TestSixBO testSixBO = new TestSixBO();
        testSixBO.setId(1L);
        return testSixBO;
    }
}
 
@Mapper(uses = BaseMapper.class)
public interface TestMapper {
    @Mapping(target = "test.id", ignore = true)
    TestSevenBO toBOS(TestFivePO testPO);
}
 
@Component
public class TestMapperImpl implements TestMapper {
    @Autowired
    private BaseMapper baseMapper;
    @Override
    public TestSevenBO toBOS(TestFivePO testPO) {
        if ( testPO == null ) {
            return null;
        }
        TestSevenBO testSevenBO = new TestSevenBO();
        testSevenBO.setTest( testFourPOToTestSixBO( testPO.getTest() ) ); 
        return testSevenBO;
    }
 
    protected TestSixBO testFourPOToTestSixBO(TestFourPO testFourPO) {
        if ( testFourPO == null ) {
            return null;
        }
        TestSixBO testSixBO = baseMapper.createSixBO();//只用在了这行。
        testSixBO.setName( testFourPO.getName() );
        testSixBO.setCreateTime( testFourPO.getCreateTime() );
        return testSixBO;
    }
}

1.2、泛型工厂@TargetType

@Mapper
public class BaseMapper {
    @ObjectFactory
    public  T createSixBO(@TargetType Class tClass) throws IllegalAccessException, InstantiationException {
        T t = tClass.newInstance();
        t.setId(3L);
        return t;
    } 
}
 
testSevenBO.setTest( testFourPOToTestSixBO( testPO.getTest() ) );

二、高级映射选项

2.1、默认值defaultValue

//给@Mapping的属性defaultValue设置一个值,若果源字段为空,那么目标字段就为此默认值
@Mapping(target = "name", source = "name", defaultValue = "noName")
TestBO toBO(TestPO testPO);

2.2、表达式expression和defaultExpression

@Mapping(target = "name", expression = "java(testPO.getName() + \"BO\")")
@Mapping(target = "totalPrice", expression = "java(testThreePO.getTotalPrice().toString() + \"元\")")
TestBO toBO(TestPO testPO);

还可以设置@Mapping的defaultExpression设置默认表达式,在source的值为null时,调用此默认表达式代码。
@Mapping(target = "name", source = "name", defaultExpression  = "java(StringBOUtils.toBOString(testPO.getName()))")

@Mapping(target = "state", expression = "java(net.shukun.universe.core.common.DoctorMapStructUtil.doctorId1(var1.getState()))" )
//这块需要注意包装类型
@Mapping(target = "state", expression = "java(DoctorMapStructUtil.getStateByName(var1.getState().getValue()).getCode())" )
public class StringBOUtils { 
    public static String toBOString(String poString) {
        return poString + "BO";
    }
}
//使用 imports 
@Mapper(uses = BaseMapper.class, imports = {StringBOUtils.class})
public interface TestMapper {
    @Mapping(target = "name", expression = "java(StringBOUtils.toBOString(testPO.getName()))")
    TestBO toBO(TestPO testPO);
}
//还可以设置@Mapping的defaultExpression设置默认表达式,在source的值为null时,调用此默认表达式代码
@Mapping(target = "name", source = "name", defaultExpression  = "java(StringBOUtils.toBOString(testPO.getName()))")
TestBO toBO(TestPO testPO);

2.3、确定映射结果的具体类型resultType属性

如果映射的结果是父类,又存在不同子类的映射方法,编译会报错,此时需要使用@Mapping或@BeanMapping的resultType指定映射结果的具体类型。

@Mapper
public class BaseMapper {
    public TestSixBO createSixBO() {
        return new TestSixBO();
    }
    public TestEightBO createEightBO() {
        return new TestEightBO();
    }
}
@Mapper(uses = {BaseMapper.class})
public interface TestMapper {
    @BeanMapping(resultType = TestEightBO.class)
    BaseBO toBO(TestFourPO testFourPO);
}

2.4、NULL映射控制

2.4.1、源对象NULL映射

当映射的source对象为null时可以通过@BeanMapping、@IterableMapping、@MapMapping(优先级最高),@Mappe,@MappingConfig(优先级最低)的nullValueMappingStrategy策略来控制NULL值的映射结果。策略值有:

  • NullValueMappingStrategy.RETURN_NULL(默认,源为null,目标直接返回null);
  • NullValueMappingStrategy.RETURN_DEFAULT(返回一个对象,除填充的常量和表达式,其他字段属性为空;集合返回一个对象,size为0)。

@IterableMapping:

集合使用了NullValueMappingStrategy.RETURN_DEFAULT策略所以源为NULL时返回return new ArrayList();bean对象使用默认策略所以源为NULL时返回return null。

@Mapper
public interface TestMapper {
    @IterableMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT)
    List toBO(List testFivePO);
}
 
@Component
public class TestMapperImpl implements TestMapper {
 
    @Override
    public List toBO(List testFivePO) {
        if ( testFivePO == null ) {
            return new ArrayList();
        }
 
        List list = new ArrayList( testFivePO.size() );
        for ( TestFivePO testFivePO1 : testFivePO ) {
            list.add( testFivePOToTestThreeBO( testFivePO1 ) );
        }
 
        return list;
    }
 
    protected TestBO testPOToTestBO(TestPO testPO) {
        if ( testPO == null ) {
            return null;
        }
 
        TestBO testBO = new TestBO();
 
        testBO.setId( testPO.getId() );
        testBO.setName( testPO.getName() );
        if ( testPO.getPrice() != null ) {
            testBO.setPrice( testPO.getPrice().toString() );
        }
        if ( testPO.getCreateTime() != null ) {
            testBO.setCreateTime( new SimpleDateFormat().format( testPO.getCreateTime() ) );
        }
 
        return testBO;
    }
 
    protected TestThreeBO testFivePOToTestThreeBO(TestFivePO testFivePO) {
        if ( testFivePO == null ) {
            return null;
        }
 
        TestThreeBO testThreeBO = new TestThreeBO();
 
        testThreeBO.setTest( testPOToTestBO( testFivePO.getTest() ) );
 
        return testThreeBO;
    }
}

@BeanMapping

@Mapper
public interface TestMapper {
    @BeanMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT)
    @Mapping(target = "id", constant = "0L")
    @Mapping(target = "name", expression = "java(testPO.getName() + \"BO\")")
    TestBO toBO(TestPO testPO);
}
 
@Component
public class TestMapperImpl implements TestMapper {
 
    @Override
    public TestBO toBO(TestPO testPO) {
 
        TestBO testBO = new TestBO();
 
        if ( testPO != null ) {
            if ( testPO.getPrice() != null ) {
                testBO.setPrice( testPO.getPrice().toString() );
            }
            else {
                testBO.setPrice( testPO.getPrice() + "BO" );
            }
            if ( testPO.getCreateTime() != null ) {
                testBO.setCreateTime( new SimpleDateFormat().format( testPO.getCreateTime() ) );
            }
        }
        testBO.setId( (long) 0L );
        testBO.setName( testPO.getName() + "BO" );
 
        return testBO;
    }
}
2.4.2、在更新时源对象属性NULL映射

在使用@MappingTarget更新目标时,可以设置@Mapping、@BeanMapping(优先级最高),@Mapper或@MappingConfig(优先级最底)的nullValuePropertyMappingStrategy属性值,用于设置当源对象属性为null时,如何设置目标属性的值。nullValuePropertyMappingStrategy的值有:

  • NullValuePropertyMappingStrategy.SET_TO_DEFAULT:源属性为null,目标属性会被赋予特定的默认值。List被赋予ArrayList,Map被赋予HashMap,数组就是空数组,String是“”,基本类型或包装类是0或false,对象是空的构造方法。
  • NullValuePropertyMappingStrategy.IGNORE:源属性为null,忽略目标属性的设值。
  • NullValuePropertyMappingStrategy.SET_TO_NULL:默认,源属性是null,目标属性也是null。
@Mapper
public interface TestMapper {
    @Mapping(target = "name", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT)
    @Mapping(target = "price", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
    void toBO(TestPO testPO, @MappingTarget TestBO testBO);
}
 
@Component
public class TestMapperImpl implements TestMapper {
 
    @Override
    public void toBO(TestPO testPO, TestBO testBO) {
        if ( testPO == null ) {
            return;
        }
 
        if ( testPO.getName() != null ) {
            testBO.setName( testPO.getName() );
        }
        else {
            testBO.setName( "" );
        }
        if ( testPO.getPrice() != null ) {
            testBO.setPrice( testPO.getPrice().toString() );
        }
        testBO.setId( testPO.getId() );
        if ( testPO.getCreateTime() != null ) {
            testBO.setCreateTime( new SimpleDateFormat().format( testPO.getCreateTime() ) );
        }
        else {
            testBO.setCreateTime( null );
        }
    }
}

三、映射扩展

3.1、装饰器映射

在进行映射时可以通过装饰器模式,为目标对象设置一些,不能由源对象直接生成或者源对象没有的属性。spring注入策略的装饰器映射使用@DecoratedWith注解制定装饰器。装饰器中使用@Qualifier("delegate")指定注入的bean。

@Mapper
@DecoratedWith(TestDecotator.class)
public interface TestMapper {
    TestBO toTestBO(TestPO testPO);
}
 
public  abstract class TestDecorator implements TestMapper {
    @Autowired
    @Qualifier("delegate")
    private TestMapper testMapper;

    @Override
    public TestBO toTestBO(TestPO testPO) {
        TestBO testBO = testMapper.toTestBO(testPO);
        testBO.setName("1111");//这处应该是个组合关系,用来设计一些特定的不能由源对象直接映射的赋值操作
        return testBO;
    }
}
 ================================生成的代码如下================================
class TestMapperImpl extends TestDecorator implements TestMapper {
    private final TestMapper delegate;
    public TestMapperImpl() {
        this( new TestMapperImpl_() );
    }
    private TestMapperImpl(TestMapperImpl_ delegate) {
        this.delegate = delegate;
    }
}
 
class TestMapperImpl_ implements TestMapper {

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

        TestBO testBO = new TestBO();

        testBO.setId( testPO.getId() );
        testBO.setName( testPO.getName() );
        testBO.setPrice( testPO.getPrice() );
        testBO.setCreteTime( testPO.getCreteTime() );

        return testBO;
    }
}

3.2、映射前置/后置方法

可以在抽象mapper类、Mapper#uses引入的类或被@Context注解的上下文对象类中设置映射前后的回调方法。@BeforeMapping注解的方法是前置方法,@AfterMapping注解的方法是后置方法。如果前后置方法具有参数,返回的类型能被赋予映射方法的返回类型并且参数都可以用源/目标参数获取,才会调用前后置方法。

前后置方法中用@MappingTarget注解的参数获得的是目标实例,@TargetType获取的是目标类型,@Context可以获取上下文对象,其他的参数被赋予源参数。然后前后置方法不是void的,返回的值不为null的情况下将作为映射方法的返回值。同样,若前后置方法能匹配到多个,将会都调用,可以通过给前置方法添加@Named和映射方法上添加@BeanMapping#qualifiedByName制定要调用的前后置方法;一旦使用了@BeanMapping#qualifiedByName就必须指定自己选用调用的所有前后置方法的@Named名。不带@MappingTarget注解参数的@BeforeMapping会在源参数进行null检查并且构造新的目标bean之前调用;带@MappingTarget注解参数的@BeforeMapping会在构造新的目标bean之后调用;@AfterMapping会在return前最后调用。在使用建造者时,@BeforeMapping、@AfterMapping中要想获取目标对象,@MappingTarget注解的就必须是建造者。

@Mapper
@Named("baseMapper")
public class BaseMapper {
 
    @BeforeMapping
    @Named("before")
    public void before(BasePO basePO, @MappingTarget BaseBO baseBO) {
        System.out.println(basePO);
        System.out.println(baseBO);
    }
 
    @AfterMapping
    public  T after(@TargetType Class clazz, @Context ThreadLocalContext threadLocalContext){
        System.out.println(threadLocalContext);
        T t = null;
        try {
           t = clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return t;
    }
 
}
 
@Data
public class ThreadLocalContext {
 
    private ThreadLocal threadLocal;
 
    public ThreadLocalContext() {
        threadLocal = new ThreadLocal<>();
    }
 
    @BeforeMapping
    @Named("before2")
    public static void before2(BasePO basePO, @MappingTarget BaseBO baseBO) {
        System.out.println(basePO);
        System.out.println(baseBO);
    }
}
 
@Mapper(uses = BaseMapper.class)
public interface TestMapper {
 
    @BeanMapping(qualifiedByName = { "baseMapper"})
    TestSixBO toTestBO(TestFourPO testPO, @Context ThreadLocalContext threadLocalContext);
 
}
 
@Component
public class TestMapperImpl implements TestMapper {
 
    @Autowired
    private BaseMapper baseMapper;
 
    @Override
    public TestSixBO toTestBO(TestFourPO testPO, ThreadLocalContext threadLocalContext) {
        if ( testPO == null ) {
            return null;
        }
 
        TestSixBO testSixBO = new TestSixBO();
 
        baseMapper.before( testPO, testSixBO );
 
        testSixBO.setId( testPO.getId() );
        testSixBO.setName( testPO.getName() );
        if ( testPO.getCreateTime() != null ) {
            testSixBO.setCreateTime( new SimpleDateFormat().format( testPO.getCreateTime() ) );
        }
 
        TestSixBO target = baseMapper.after( TestSixBO.class, threadLocalContext );
        if ( target != null ) {
            return target;
        }
 
        return testSixBO;
    }
}
public interface LicenseModelTranslator {

    LicenseModelTranslator INSTANCE = Mappers.getMapper(LicenseModelTranslator.class);

    @Mapping(target = "activationInfo",ignore = true)
    @Mapping(target = "operatorUid", source = "operatorUserId")
    @Mapping(target = "createdAt", source = "ctime")
    LicenseActivationRecordBo toActivationRecordBo(ActivationRecordEntity var1);

    List toActivationRecordBos(List var1);

    @AfterMapping
    default void  setLicenseActivationInfoBo(@MappingTarget LicenseActivationRecordBo bo,  ActivationRecordEntity var1) {
        List activationInfo = JSONUtil.toList(var1.getActivationInfo(), LicenseActivationInfoBo.class);
        bo.setActivationInfo(activationInfo);
    }
}

3.3、父子结构映射

public class Employee {
    private String name;
    private Employee reportsTo;
    private List team;
}
public class EmployeeDto {
    private String employeeName;
    private EmployeeDto reportsTo;
    private List team;
}
@Mapper
public interface EmployeeMapper {

    EmployeeMapper MAPPER = Mappers.getMapper( EmployeeMapper.class );

    @Mapping(source = "employeeName", target = "name")
    Employee toEmployee(EmployeeDto employeeDto, @Context CycleAvoidingMappingContext context);

    @InheritInverseConfiguration
    EmployeeDto fromEmployee(Employee employee, @Context CycleAvoidingMappingContext context);
}
public class CycleAvoidingMappingContext {
    private Map knownInstances = new IdentityHashMap();

    @BeforeMapping
    public  T getMappedInstance(Object source, @TargetType Class targetType) {
        return (T) knownInstances.get( source );
    }

    @BeforeMapping
    public void storeMappedInstance(Object source, @MappingTarget Object target) {
        knownInstances.put( source, target );
    }
}
3.3.1、循环嵌套对象调用前后置方法
@Data
public class TestBOS {
 
    private TestBOS testS;
 
    private List list;
}
 
@Data
public class TestPOS {
 
    private TestPOS testS;
 
    private List list;
}
 
@Mapper
public class BaseMapper {
 
    @BeforeMapping
    public  T before(Object source, @TargetType Class targetType) {
        T t;
        try {
            t = targetType.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            return null;
        }
        return t;
    }
 
}
 
 
@Mapper(uses = BaseMapper.class)
public interface TestMapper {
 
    TestBOS toBean(TestPOS testPOS);
 
}

四、高级映射属性

4.1、映射配置继承@InheritConfiguration

@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); //toTestThreeBO的实现方法在设置nickName时,继承的toTestTwoBO方法的映射配置。
}

4.2、逆映射@InheritInverseConfiguration

当我们定义了一种对象到另一种对象的映射后,可以通过@InheritInverseConfiguration直接进行逆映射。可以看到实现的toTestBO方法中的price->priceString使用的就是toTestPO中priceString->price的逆映射,但是正映射的@Mapping#expression、#defaultExpression、#defaultValue和#constant会被逆映射忽略,就如其中的默认值“-1”在逆映射中不存在;此外某个字段的逆映射可以被ignore,expression或constant覆盖,就如name->nameString;在正映射的createTimeString->createTime上设置了ignore,若此时同时制定了source,则逆映射会继承ignore,不用再重新设置。@InheritConfiguration的优先级高于@InheritInverseConfiguration。

@Data
@ToString
public class TestPO { 
    private Long id; 
    private String nameString;
    private BigDecimal priceString;
    private Date createTimeString;
}
 //InheritInverseConfiguration 这个注解是一个相对的操作,必须要有前提此处才会有用,比如下例中必须有TestBO  toTestBO(TestPO testPO)才可以,也就是为了少写
 //映射代码,如果有多个类似的话,可以用@InheritInverseConfiguration( name = "toTestBO" )指定一个原实现方法名
@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;
    }
}

4.3、配置共享

@MapperConfig注解的接口就是共享配置,可以在@Mapper#config指定共享配置,@MapperConfig中的属性和@Mapper相同,@Mapper中的属性会覆盖@MapperConfig。共享配置中可以设置原型映射,也可以是父类映射,再通过@MapperConfig、@Mapper的mappingInheritanceStrategy就可以实现原型映射的继承。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);
}
4.3.1、MappingInheritanceStrategy.EXPLICIT

共享配置的原型映射并不会生成单独的实现方法。虽然默认继承策略支持正/逆,但是引入共享配置,且mapper中正映射能继承原型映射的情况下,再设置逆映射方法,就必须制定name属性,否则同样有冲突报错。

@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() );
    }
}
4.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() );
    }
}
4.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() );
    }
}
4.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() );
    }
}

你可能感兴趣的:(java,开发语言,spring,架构设计,rpc)