MapStruct文档(五)——集合映射

目录

4.1、List

4.2、Map

4.3、更新集合

4.4、集合策略

4.5、*集合属性映射

4.5.1、手动创建add方法

4.5.2、getter和adder类型不同

4.5.3、多个相同参数列表的add方法


4.1、List

迭代的每一项遵循以上规则。


@Mapper
public interface TestMapper {

    TestBO testToBO(TestPO testPO);

    List<TestBO> testToBOS(List<TestPO> testPOS);
}
 
@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public TestBO testToBO(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;
    }

    @Override
    public List<TestBO> testToBOS(List<TestPO> testPOS) {
        if ( testPOS == null ) {
            return null;
        }

        List<TestBO> list = new ArrayList<TestBO>( testPOS.size() );
        for ( TestPO testPO : testPOS ) {
            list.add( testToBO( testPO ) );
        }

        return list;
    }
}
 
@Test
public void baseTest() {
    List<TestPO> list = new ArrayList<>();
    for (int i = 0; i < 2; i++) {
        TestPO testPO = new TestPO();
        testPO.setId(1L);
        testPO.setName("haru");
        testPO.setPrice(new BigDecimal("12.02"));
        testPO.setCreteTime(new Date(System.currentTimeMillis()));
        list.add(testPO);
    }

    System.out.println(testMapper.testToBOS(list));
}

结果


4.2、Map

map的key、value分别遵循以上规则。


@Mapper
public interface TestMapper {

    TestBO testToBO(TestPO testPO);

    Map<TestBO, TestBO> testToBOS(Map<TestPO, TestPO> testPOS);

}
 
@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public TestBO testToBO(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.getCreteTime() != null ) {
            testBO.setCreteTime( new SimpleDateFormat().format( testPO.getCreteTime() ) );
        }

        return testBO;
    }

    @Override
    public Map<TestBO, TestBO> testToBOS(Map<TestPO, TestPO> testPOS) {
        if ( testPOS == null ) {
            return null;
        }

        Map<TestBO, TestBO> map = new HashMap<TestBO, TestBO>( Math.max( (int) ( testPOS.size() / .75f ) + 1, 16 ) );

        for ( java.util.Map.Entry<TestPO, TestPO> entry : testPOS.entrySet() ) {
            TestBO key = testToBO( entry.getKey() );
            TestBO value = testToBO( entry.getValue() );
            map.put( key, value );
        }

        return map;
    }
}
 

Map<TestPO, TestPO> testPOS = new HashMap<>(8);
TestPO testPO = new TestPO();
testPO.setId(1L);
testPO.setName("haru");
testPO.setPrice(new BigDecimal("12.02"));
testPO.setCreteTime(new Date(System.currentTimeMillis()));
testPOS.put(testPO, testPO);
System.out.println(testMapper.testToBOS(testPOS));

结果


4.3、更新集合

@MappingTarget注释集合上时,会先清除要更新的集合,再添加。


@Mapper
public interface TestMapper {

    void updateBO(List<TestPO> testPOS, @MappingTarget List<TestBO> testBOS);

}
 
@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public void updateBO(List<TestPO> testPOS, List<TestBO> testBOS) {
        if ( testPOS == null ) {
            return;
        }

        testBOS.clear();
        for ( TestPO testPO : testPOS ) {
            testBOS.add( testPOToTestBO( testPO ) );
        }
    }

    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.getCreteTime() != null ) {
            testBO.setCreteTime( new SimpleDateFormat().format( testPO.getCreteTime() ) );
        }

        return testBO;
    }
}

4.4、集合策略

通过@Mapping#collectionMappingStrategy设置集合的映射策略:CollectionMappingStrategy.ACCESSOR_ONLY:默认、CollectionMappingStrategy.SETTER_PREFERREDCollectionMappingStrategy.ADDER_PREFERREDCollectionMappingStrategy.TARGET_IMMUTABLE

 只有set方法修改集合只有add方法修改集合set、add方法都有修改集合set、add方法都没有已经存在的集合对象
ACCESSOR_ONLY直接set集合先get获取集合再addAll直接set集合先get获取集合再addAll先get获取集合再addAll
SETTER_PREFERRED直接set集合add集合一项直接set集合先get获取集合再addAll先get获取集合再addAll
ADDER_PREFERRED直接set集合add集合一项add集合一项先get获取集合再addAll先get获取集合再addAll
TARGET_IMMUTABLE直接set集合异常直接set集合异常直接set集合

只有add方法,使用CollectionMappingStrategy.ADDER_PREFERRED策略。


public class TestPOS {

    private List<TestPO> list;

    public List<TestPO> getList() {
        return list;
    }

    public void addList(TestPO testPO) {
        this.list.add(testPO);
    }
}
 
public class TestBOS {

    private List<TestBO> list;

    public List<TestBO> getList() {
        return list;
    }

    public void addList(TestBO testBO) {
        this.list.add(testBO);
    }
}
 
@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
public interface TestMapper {

    TestBO toBO(TestPO testPO);

    TestBOS toBOS(TestPOS testPOS);

}
 
@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public TestBO toBO(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.getCreteTime() != null ) {
            testBO.setCreteTime( new SimpleDateFormat().format( testPO.getCreteTime() ) );
        }

        return testBO;
    }

    @Override
    public TestBOS toBOS(TestPOS testPOS) {
        if ( testPOS == null ) {
            return null;
        }

        TestBOS testBOS = new TestBOS();

        if ( testPOS.getList() != null ) {
            for ( TestPO list : testPOS.getList() ) {
                testBOS.addList( toBO( list ) );
            }
        }

        return testBOS;
    }
}

可以看到testBOS.addList( toBO( list ) )使用了add方法。

 

再看把add方法去掉,使用CollectionMappingStrategy.ACCESSOR_ONLY策略。


public class TestPOS {

    private List<TestPO> list;

    public List<TestPO> getList() {
        return list;
    }

}
 
public class TestBOS {

    private List<TestBO> list;

    public List<TestBO> getList() {
        return list;
    }

}
 
@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ACCESSOR_ONLY)
public interface TestMapper {

    TestBO toBO(TestPO testPO);

    TestBOS toBOS(TestPOS testPOS);

}
 
@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public TestBO toBO(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.getCreteTime() != null ) {
            testBO.setCreteTime( new SimpleDateFormat().format( testPO.getCreteTime() ) );
        }

        return testBO;
    }

    @Override
    public TestBOS toBOS(TestPOS testPOS) {
        if ( testPOS == null ) {
            return null;
        }

        TestBOS testBOS = new TestBOS();

        if ( testBOS.getList() != null ) {
            List<TestBO> list = testPOListToTestBOList( testPOS.getList() );
            if ( list != null ) {
                testBOS.getList().addAll( list );
            }
        }

        return testBOS;
    }

    protected List<TestBO> testPOListToTestBOList(List<TestPO> list) {
        if ( list == null ) {
            return null;
        }

        List<TestBO> list1 = new ArrayList<TestBO>( list.size() );
        for ( TestPO testPO : list ) {
            list1.add( toBO( testPO ) );
        }

        return list1;
    }
}

testBOS.getList().addAll( list )先getList在addAll。

 

最后看一下集合对象存在的情况。使用CollectionMappingStrategy.TARGET_IMMUTABLE策略。


@Data
public class TestPOS {

    private List<TestPO> list;
}


@Data
public class TestBOS {

    private List<TestBO> list;
}
 
@Mapper(collectionMappingStrategy = CollectionMappingStrategy.TARGET_IMMUTABLE)
public interface TestMapper {

    TestBO toBO(TestPO testPO);

    void toBOS(TestPOS testPOS, @MappingTarget TestBOS testBOS);

}
 
@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public TestBO toBO(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.getCreteTime() != null ) {
            testBO.setCreteTime( new SimpleDateFormat().format( testPO.getCreteTime() ) );
        }

        return testBO;
    }

    @Override
    public void toBOS(TestPOS testPOS, TestBOS testBOS) {
        if ( testPOS == null ) {
            return;
        }

        testBOS.setList( testPOListToTestBOList( testPOS.getList() ) );
    }

    protected List<TestBO> testPOListToTestBOList(List<TestPO> list) {
        if ( list == null ) {
            return null;
        }

        List<TestBO> list1 = new ArrayList<TestBO>( list.size() );
        for ( TestPO testPO : list ) {
            list1.add( toBO( testPO ) );
        }

        return list1;
    }
}

直接使用testBOS.setList( testPOListToTestBOList( testPOS.getList() ) )

 

使用默认集合策略


@Mapper
public interface TestMapper {

    TestBO toBO(TestPO testPO);

    void toBOS(TestPOS testPOS, @MappingTarget TestBOS testBOS);

}
 
@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public TestBO toBO(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.getCreteTime() != null ) {
            testBO.setCreteTime( new SimpleDateFormat().format( testPO.getCreteTime() ) );
        }

        return testBO;
    }

    @Override
    public void toBOS(TestPOS testPOS, TestBOS testBOS) {
        if ( testPOS == null ) {
            return;
        }

        if ( testBOS.getList() != null ) {
            List<TestBO> list = testPOListToTestBOList( testPOS.getList() );
            if ( list != null ) {
                testBOS.getList().clear();
                testBOS.getList().addAll( list );
            }
            else {
                testBOS.setList( null );
            }
        }
        else {
            List<TestBO> list = testPOListToTestBOList( testPOS.getList() );
            if ( list != null ) {
                testBOS.setList( list );
            }
        }
    }

    protected List<TestBO> testPOListToTestBOList(List<TestPO> list) {
        if ( list == null ) {
            return null;
        }

        List<TestBO> list1 = new ArrayList<TestBO>( list.size() );
        for ( TestPO testPO : list ) {
            list1.add( toBO( testPO ) );
        }

        return list1;
    }
}

先清除了目标集合testBOS.getList().clear(),再testBOS.getList().addAll( list )。


4.5、*集合属性映射

4.5.1、手动创建add方法

在1.7中介绍过对象属性值和getter/setter方法的匹配规则,这里在介绍下List属性字段名的映射规则。


public class TestBOS {

    private List<TestBO> oneTest_;

    public List<TestBO> getOneTestList() {
        return oneTest_;
    }

    public void addOneTest(TestBO testBO) {
        oneTest_.add(testBO);
    }

}

这里不使用lombok,手动编写get、add方法。


@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
public interface TestMapper {

    @Mapping(target = "oneTest_", source = "tests")
    TestBOS toBean(TestPOS testPO);

}
 
@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
public interface TestMapper {

    @Mapping(target = "oneTest", source = "tests")
    TestBOS toBean(TestPOS testPO);

}

以上编译后的实现类会是什么样呢?答案是编译报错。

这里都提示了“oneTestList”的属性名。

 


@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED)
public interface TestMapper {

    @Mapping(target = "oneTestList", source = "tests")
    TestBOS toBean(TestPOS testPO);

}
 
@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public TestBOS toBean(TestPOS testPO) {
        if ( testPO == null ) {
            return null;
        }

        TestBOS testBOS = new TestBOS();

        if ( testPO.getTests() != null ) {
            for ( TestPO test : testPO.getTests() ) {
                testBOS.addOneTest( testPOToTestBO( test ) );
            }
        }

        return testBOS;
    }

    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;
    }
}

修改属性为“oneTestList”,可以正确编译,testBOS.addOneTest( testPOToTestBO( test ) ),集合的映射策略是ADDER_PREFERRED,所以调用了add方法。


4.5.2、getter和adder类型不同


public class TestBOS {

    private List<Integer> oneTest_;

    public List<TestBO> getOneTestList() {
        return new ArrayList<>();
    }

    public void addOneTest(Integer integer) {
        oneTest_.add(integer);
    }

}

这个例子将oneTest_的类型改成List<Integer>,getOneTestList()方法还是返回List<TestBO>,addOneTest方法的参数改为Integer。结果如下。


@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public TestBOS toBean(TestPOS testPO) {
        if ( testPO == null ) {
            return null;
        }

        TestBOS testBOS = new TestBOS();

        if ( testBOS.getOneTestList() != null ) {
            List<TestBO> list = testPOListToTestBOList( testPO.getTests() );
            if ( list != null ) {
                testBOS.getOneTestList().addAll( list );
            }
        }

        return testBOS;
    }

    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 List<TestBO> testPOListToTestBOList(List<TestPO> list) {
        if ( list == null ) {
            return null;
        }

        List<TestBO> list1 = new ArrayList<TestBO>( list.size() );
        for ( TestPO testPO : list ) {
            list1.add( testPOToTestBO( testPO ) );
        }

        return list1;
    }
}

集合的映射调用的是testBOS.getOneTestList().addAll( list )。推测要先能匹配add方法,add方法的参数类型要和get方法返回List中泛型类型一致。

再修改下。


public class TestBOS {

    private List<Integer> oneTest_;

    public List<TestBO> getOneTestList() {
        return new ArrayList<>();
    }

    public void addOneTest(TestBO testBO) {
        oneTest_.add(testBO.getId().intValue());
    }

}
 
@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public TestBOS toBean(TestPOS testPO) {
        if ( testPO == null ) {
            return null;
        }

        TestBOS testBOS = new TestBOS();

        if ( testPO.getTests() != null ) {
            for ( TestPO test : testPO.getTests() ) {
                testBOS.addOneTest( testPOToTestBO( test ) );
            }
        }

        return testBOS;
    }

    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;
    }
}

这样就是调用了add方法testBOS.addOneTest( testPOToTestBO( test ) )


4.5.3、多个相同参数列表的add方法


public class TestBOS {

    private List<TestBO> oneTest;

    public List<TestBO> getOneTestList() {
        return oneTest;
    }

    public void addOneTest(TestBO testBO) {
        oneTest.add(testBO);
    }

    public void addTwoTest(TestBO testBO) {
        oneTest.add(testBO);
    }

}
 
@Component
public class TestMapperImpl implements TestMapper {

    @Override
    public TestBOS toBean(TestPOS testPO) {
        if ( testPO == null ) {
            return null;
        }

        TestBOS testBOS = new TestBOS();

        if ( testBOS.getOneTestList() != null ) {
            List<TestBO> list = testPOListToTestBOList( testPO.getTests() );
            if ( list != null ) {
                testBOS.getOneTestList().addAll( list );
            }
        }

        return testBOS;
    }

    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 List<TestBO> testPOListToTestBOList(List<TestPO> list) {
        if ( list == null ) {
            return null;
        }

        List<TestBO> list1 = new ArrayList<TestBO>( list.size() );
        for ( TestPO testPO : list ) {
            list1.add( testPOToTestBO( testPO ) );
        }

        return list1;
    }
}

如果找到多个相同参数列表的add方法,则会因为无法确认匹配哪一个就会调用get方法了testBOS.getOneTestList().addAll( list )

 

介绍这个主要是为了给第11章铺垫。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值