推土机:如何限制映射的深度?

时间:2015-11-03 12:14:36

标签: java dozer object-object-mapping

我目前正在使用 Dozer Entity个对象映射到我项目中的Dto个对象。

我的问题是如何限制内部映射的级别或深度?

例如,我有一个AccountProfile实体,其中有List<AccountProfileDetail>个实体作为成员。此外,AccountProfileDetail本身有一个FinancialTransLimit实体作为成员。

现在我想告诉映射器,例如只用depth = 2进行映射。因此,FinancialTransLimit成员不会被复制到目标对象的AccountProfileDetail成员。

我需要在xml中使用Programming API 指定深度。但是,我也没有在xml配置中找到它。

我也尝试过 Orika ,但我也无法在Orika找到这样的功能!

以下两个代码(使用Dozer和Orika作为替代方案进行测试)都可以正常工作并进行深层复制。 我需要限制其中至少一个的深度

有人可以帮帮我吗?

非常感谢!

示例代码:

AccountProfile

//My Entities:
import java.util.List;

public class AccountProfile{

    private Long id;
    private String name;
    private List<AccountProfileDetail> accountProfileDetails;

    public AccountProfile() {
    }

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<AccountProfileDetail> getAccountProfileDetails() {
        return this.accountProfileDetails;
    }

    public void setAccountProfileDetails(List<AccountProfileDetail> accountProfileDetails) {
        this.accountProfileDetails = accountProfileDetails;
    }
}

AccountProfileDetail

import java.math.BigDecimal;

public class AccountProfileDetail {

    private Long id;
    private BigDecimal accountMinBalance;
    private AccountProfile accountProfile;
    private FinancialTransLimit financialTransLimit;

    public AccountProfileDetail() {
    }

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public BigDecimal getAccountMinBalance() {
        return this.accountMinBalance;
    }

    public void setAccountMinBalance(BigDecimal accountMinBalance) {
        this.accountMinBalance = accountMinBalance;
    }

    public AccountProfile getAccountProfile() {
        return this.accountProfile;
    }

    public void setAccountProfile(AccountProfile accountProfile) {
        this.accountProfile = accountProfile;
    }

    public FinancialTransLimit getFinancialTransLimit() {
        return this.financialTransLimit;
    }

    public void setFinancialTransLimit(FinancialTransLimit financialTransLimit) {
        this.financialTransLimit = financialTransLimit;
    }
}

FinancialTransLimit

public class FinancialTransLimit{

    private Long id;
    private String limitCode;

    public FinancialTransLimit() {
    }

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getLimitCode() {
        return this.limitCode;
    }

    public void setLimitCode(String limitCode) {
        this.limitCode = limitCode;
    }
}

AccountProfileDto

// My Dtos:
import java.util.List;

public class AccountProfileDto{
    private Long id;
    private String name;
    private List<AccountProfileDetailDto> accountProfileDetails;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    public List<AccountProfileDetailDto> getAccountProfileDetails() {
        return accountProfileDetails;
    }

    public void setAccountProfileDetails(List<AccountProfileDetailDto> accountProfileDetails) {
        this.accountProfileDetails = accountProfileDetails;
    }
}

AccountProfileDetailDto

import java.math.BigDecimal;

public class AccountProfileDetailDto {

    private Long id;
    private BigDecimal accountMinBalance;
    private AccountProfileDto accountProfile;
    private FinancialTransLimitDto financialTransLimit;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public BigDecimal getAccountMinBalance() {
        return accountMinBalance;
    }

    public void setAccountMinBalance(BigDecimal accountMinBalance) {
        this.accountMinBalance = accountMinBalance;
    }

    public AccountProfileDto getAccountProfile() {
        return accountProfile;
    }

    public void setAccountProfile(AccountProfileDto accountProfile) {
        this.accountProfile = accountProfile;
    }

    public FinancialTransLimitDto getFinancialTransLimit() {
        return financialTransLimit;
    }

    public void setFinancialTransLimit(FinancialTransLimitDto financialTransLimit) {
        this.financialTransLimit = financialTransLimit;
    }
}

FinancialTransLimitDto

public class FinancialTransLimitDto {
    private Long id;
    private String limitCode;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getLimitCode() {
        return limitCode;
    }

    public void setLimitCode(String limitCode) {
        this.limitCode = limitCode;
    }
}

现在使用推土机的测试用例代码:

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.dozer.DozerBeanMapper;
import org.dozer.Mapper;


public class TestDozer {

    public static void main(String[] args) {

        List<AccountProfile> profiles = createList();

        Mapper mapper = new DozerBeanMapper();

        List<AccountProfileDto> profileDtos = new ArrayList<AccountProfileDto>(); 

        for (AccountProfile entity: profiles) {
            AccountProfileDto dto = new AccountProfileDto();
            mapper.map(entity, dto);
            profileDtos.add(dto);
        }

        System.out.println(Arrays.deepToString(profileDtos.toArray()));
    }

    private static List<AccountProfile> createList(){
        List<AccountProfile> accountProfiles = new ArrayList<AccountProfile>();

        AccountProfile ap1 = new AccountProfile();
        ap1.setId(new Long(1000));
        ap1.setName("profile1");

        FinancialTransLimit ftlt1 = new FinancialTransLimit();
        ftlt1.setId(new Long(3000));
        ftlt1.setLimitCode("L1");

        AccountProfileDetail apd1 = new AccountProfileDetail();
        apd1.setId(new Long(2000));
        apd1.setAccountProfile(ap1);
        apd1.setAccountMinBalance(new BigDecimal(100000));
        apd1.setFinancialTransLimit(ftlt1);

        List<AccountProfileDetail> apds1 = new ArrayList<AccountProfileDetail>();
        apds1.add(apd1);
        ap1.setAccountProfileDetails(apds1);

        accountProfiles.add(ap1);
        //
        AccountProfile ap2 = new AccountProfile();
        ap2.setId(new Long(1001));
        ap2.setName("profile2");

        FinancialTransLimit ftlt2 = new FinancialTransLimit();
        ftlt2.setId(new Long(3001));
        ftlt2.setLimitCode("L2");

        AccountProfileDetail apd2 = new AccountProfileDetail();
        apd2.setId(new Long(2001));
        apd2.setAccountProfile(ap2);
        apd2.setAccountMinBalance(new BigDecimal(200000));
        apd2.setFinancialTransLimit(ftlt2);

        List<AccountProfileDetail> apds2 = new ArrayList<AccountProfileDetail>();
        apds2.add(apd2);
        ap2.setAccountProfileDetails(apds2);

        accountProfiles.add(ap2);
        //
        return accountProfiles;
    }
}

使用 Orika 测试代码:

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import ma.glasnost.orika.BoundMapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;

public class TestOrika {

    public static void main(String[] args) {

        List<AccountProfile> profiles = createList();

        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        BoundMapperFacade<AccountProfile, AccountProfileDto> mapper = mapperFactory.getMapperFacade(AccountProfile.class, AccountProfileDto.class);

        List<AccountProfileDto> profileDtos = new ArrayList<AccountProfileDto>(); 

        for (AccountProfile entity: profiles) {
            AccountProfileDto dto = new AccountProfileDto();
            mapper.map(entity, dto);
            profileDtos.add(dto);
        }

        System.out.println(Arrays.deepToString(profileDtos.toArray()));
    }

    private static List<AccountProfile> createList(){
        List<AccountProfile> accountProfiles = new ArrayList<AccountProfile>();

        AccountProfile ap1 = new AccountProfile();
        ap1.setId(new Long(1000));
        ap1.setName("profile1");

        FinancialTransLimit ftlt1 = new FinancialTransLimit();
        ftlt1.setId(new Long(3000));
        ftlt1.setLimitCode("L1");

        AccountProfileDetail apd1 = new AccountProfileDetail();
        apd1.setId(new Long(2000));
        apd1.setAccountProfile(ap1);
        apd1.setAccountMinBalance(new BigDecimal(100000));
        apd1.setFinancialTransLimit(ftlt1);

        List<AccountProfileDetail> apds1 = new ArrayList<AccountProfileDetail>();
        apds1.add(apd1);
        ap1.setAccountProfileDetails(apds1);

        accountProfiles.add(ap1);

        //

        AccountProfile ap2 = new AccountProfile();
        ap2.setId(new Long(1001));
        ap2.setName("profile2");

        FinancialTransLimit ftlt2 = new FinancialTransLimit();
        ftlt2.setId(new Long(3001));
        ftlt2.setLimitCode("L2");

        AccountProfileDetail apd2 = new AccountProfileDetail();
        apd2.setId(new Long(2001));
        apd2.setAccountProfile(ap2);
        apd2.setAccountMinBalance(new BigDecimal(200000));
        apd2.setFinancialTransLimit(ftlt2);

        List<AccountProfileDetail> apds2 = new ArrayList<AccountProfileDetail>();
        apds2.add(apd2);
        ap2.setAccountProfileDetails(apds2);

        accountProfiles.add(ap2);

        //

        return accountProfiles;
    }
}

1 个答案:

答案 0 :(得分:2)

我认为在我使用的最后一个版本(5.5.X)中不可能。推土机会尝试将物体从一个物体映射到另一个物体,直到它到达终点。如果他找到一个循环关系,它将抛出异常。此外,如果两个对象具有名称相同的不同类型的属性,则将抛出异常。这是使用第3方映射器库的重点。 但是,如果目标对象不包含可在源映射期间使用的属性,则只会忽略该属性。如果您以不同方式命名目标属性,理论上应该相同。你可以使用这些规则来解决一些问题。

如果你有1到1个映射,而源和目标对象没有区别,我建议你坚持使用Dozer。如果您对映射方式有不同或限制,请编写自己的转换器。