MapStruct文件(九)——高階對映選項
目錄
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
@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使用的就是toTestPO中priceString->price的逆對映,但是正對映的@Mapping#expression、#defaultExpression、#defaultValue和#constant會被逆對映忽略,就如其中的預設值“-1”在逆對映中不存在;此外某個欄位的逆對映可以被ignore,expression或constant覆蓋,就如name->nameString;在正對映的createTimeString->createTime上設定了ignore,若此時同時制定了source,則逆對映會繼承ignore,不用再重新設定。
@InheritConfiguration的優先順序高於@InheritInverseConfiguration。
8.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);
}
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() );
}
}