I'm currently using Dozer for mapping Entity
objects to Dto
objects in my project.
My question is how to limit the levels or the depth of internal mappings?
For example I have a AccountProfile
entity which has a List<AccountProfileDetail>
entity as a member. Moreover AccountProfileDetail
itself has a FinancialTransLimit
entity as a member.
Now I want to tell the mapper that for example do the mappings only with depth = 2
. So the FinancialTransLimit
member doesn't get copied to the AccountProfileDetail
member of destination object.
I need to specify the depth using Programming API not in xml. However, I didn't find it in the xml configurations, too.
I've tried Orika too, but I couldn't find such feature in Orika too!
Both of the following codes (for testing with Dozer and Orika as an alternative) work fine and do a deep copy. I need to limit the depth for at least one of them.
Could anyone help me with this, please?
Many thanks!
Sample Code:
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;
}
}
And now the test case code with 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;
}
}
Test code with 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;
}
}
I don't think that was possible in the last version I used (5.5.X). Dozer will try to map objects from one to another until he hits the end. If he finds a circular relations, it will throw an exception. Also, exception will be thrown if two objects have attributes of different types named the same. That is the whole point of using the 3th party mapper library. However, if the target object does not contain the attribute that could be used during mapping of source, that attribute will just be ignored. Same should theoretically work if you name the target-attributes differently. You can work out some hacks using these rules.
I would advise you to stick with Dozer only if you have 1 to 1 mappings with no difference in source and target objects. If you have differences or constraints on how you want to map it, write your own converters.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With