Dozer:如何限制映射的深度?
Posted
技术标签:
【中文标题】Dozer:如何限制映射的深度?【英文标题】:Dozer: How to limit the depth of mappings? 【发布时间】:2016-02-03 14:11:51 【问题描述】:我目前正在使用 Dozer 将Entity
对象映射到我项目中的Dto
对象。
我的问题是如何限制内部映射的级别或深度?
例如,我有一个 AccountProfile
实体,它有一个 List<AccountProfileDetail>
实体作为成员。而且AccountProfileDetail
本身有一个FinancialTransLimit
实体作为成员。
现在我想告诉映射器,例如只使用depth = 2
进行映射。所以FinancialTransLimit
成员不会被复制到目标对象的AccountProfileDetail
成员。
我需要指定深度使用编程 API 不在 xml 中。但是,我也没有在xml配置中找到它。
我也尝试过Orika,但我也没有在Orika中找到这样的功能!
以下两个代码(用于使用 Dozer 和 Orika 作为替代进行测试)都可以正常工作并进行深度复制。 我需要限制其中至少一个的深度。
有人可以帮我解决这个问题吗?
非常感谢!
示例代码:
账户资料
//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;
账户资料详情
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;
现在是 Dozer 的测试用例代码:
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;
【问题讨论】:
你有代码要分享吗? @cheffe:明天我会分享我的代码示例。 @cheffe:我添加了一些代码。 【参考方案1】:我认为这在我使用的上一个版本 (5.5.X) 中是不可能的。推土机将尝试将对象从一个映射到另一个,直到他到达终点。如果他找到循环关系,就会抛出异常。此外,如果两个对象具有名称相同的不同类型的属性,则会引发异常。这就是使用第 3 方映射器库的全部意义所在。 但是,如果目标对象不包含可在源映射期间使用的属性,则该属性将被忽略。如果您以不同的方式命名目标属性,理论上应该同样有效。您可以使用这些规则制定一些技巧。
我建议您仅在源对象和目标对象之间没有差异的 1 对 1 映射时才坚持使用 Dozer。如果您对如何映射它有不同或限制,请编写您自己的转换器。
【讨论】:
以上是关于Dozer:如何限制映射的深度?的主要内容,如果未能解决你的问题,请参考以下文章