Which Java Bean Mapper Is Fastest? 12 Conversion Tools Compared and Ranked
This article evaluates twelve Java object‑property mapping libraries—including MapStruct, ModelMapper, Dozer, and BeanUtils—by measuring their performance across 100 to one‑million conversions, presenting code examples, rating each tool, and recommending the most efficient solution for backend development.
1. Introduction
Writing code that merely works without technical depth, solid knowledge, or experience leads to fragile solutions that lack proper data‑structure, algorithmic, and design‑pattern considerations. Relying on copy‑paste snippets without understanding their principles results in code that is only "usable" but not reliable.
2. Performance Test Comparison
In Java system development, converting objects such as VO, DTO, and PO manually with get / set is time‑consuming and error‑prone. Therefore, an automated conversion tool is preferred. Twelve conversion methods were benchmarked with 100, 1,000, 10,000, 100,000 and 1,000,000 iterations to compare execution time.
3. 12 Conversion Cases
1. get\set
@Component
public class GetSetAssembler implements IAssembler<UserVO, UserDTO> {
@Override
public UserDTO sourceToTarget(UserVO var) {
UserDTO userDTO = new UserDTO();
userDTO.setUserId(var.getUserId());
userDTO.setUserNickName(var.getUserNickName());
userDTO.setCreateTime(var.getCreateTime());
return userDTO;
}
}Rating: ★★★☆☆ Performance: ★★★★★ Method: Manual getter/setter. Comment: Most common but cumbersome for many fields; shortcuts in IDE can help.
2. json2Json
@Component
public class Json2JsonAssembler implements IAssembler<UserVO, UserDTO> {
@Override
public UserDTO sourceToTarget(UserVO var) {
String strJson = JSON.toJSONString(var);
return JSON.parseObject(strJson, UserDTO.class);
}
}Rating: ☆☆☆☆☆ Performance: ★☆☆☆☆ Method: Serialize to JSON then deserialize. Comment: Simple but very inefficient.
3. Apache copyProperties
@Component
public class ApacheCopyPropertiesAssembler implements IAssembler<UserVO, UserDTO> {
@Override
public UserDTO sourceToTarget(UserVO var) {
UserDTO userDTO = new UserDTO();
try {
BeanUtils.copyProperties(userDTO, var);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return userDTO;
}
}Rating: ☆☆☆☆☆ Performance: ★☆☆☆☆ Method: Uses Apache BeanUtils with reflection. Comment: Compatibility issues; not recommended.
4. Spring copyProperties
@Component
public class SpringCopyPropertiesAssembler implements IAssembler<UserVO, UserDTO> {
@Override
public UserDTO sourceToTarget(UserVO var) {
UserDTO userDTO = new UserDTO();
BeanUtils.copyProperties(var, userDTO);
return userDTO;
}
}Rating: ★★★☆☆ Performance: ★★★★☆ Method: Spring’s BeanUtils (reflection). Comment: Safer than Apache version; works well when used correctly.
5. Bean Mapping
@Component
public class BeanMappingAssembler implements IAssembler<UserVO, UserDTO> {
@Override
public UserDTO sourceToTarget(UserVO var) {
UserDTO userDTO = new UserDTO();
BeanUtil.copyProperties(var, userDTO);
return userDTO;
}
}Rating: ★★☆☆☆ Performance: ★★★☆☆ Method: Simple property copy via BeanUtil. Comment: Average performance.
6. Bean Mapping ASM
@Component
public class BeanMappingAssembler implements IAssembler<UserVO, UserDTO> {
@Override
public UserDTO sourceToTarget(UserVO var) {
UserDTO userDTO = new UserDTO();
BeanUtil.copyProperties(var, userDTO);
return userDTO;
}
}Rating: ★★★☆☆ Performance: ★★★★☆ Method: ASM‑based bytecode generation. Comment: Faster than plain Bean Mapping.
7. BeanCopier
@Component
public class BeanCopierAssembler implements IAssembler<UserVO, UserDTO> {
@Override
public UserDTO sourceToTarget(UserVO var) {
UserDTO userDTO = new UserDTO();
BeanCopier beanCopier = BeanCopier.create(var.getClass(), userDTO.getClass(), false);
beanCopier.copy(var, userDTO, null);
return userDTO;
}
}Rating: ★★★☆☆ Performance: ★★★★☆ Method: CGLIB bytecode generation. Comment: Good performance and easy to use.
8. Orika
@Component
public class OrikaAssembler implements IAssembler<UserVO, UserDTO> {
private static MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
static {
mapperFactory.classMap(UserDTO.class, UserVO.class)
.field("userId", "userId")
.byDefault()
.register();
}
@Override
public UserDTO sourceToTarget(UserVO var) {
return mapperFactory.getMapperFacade().map(var, UserDTO.class);
}
}Rating: ★★☆☆☆ Performance: ★★★☆☆ Method: Bytecode‑generated mapper. Comment: Not outstanding; needs MapperFactory optimization.
9. Dozer
@Component
public class DozerAssembler implements IAssembler<UserVO, UserDTO> {
private static DozerBeanMapper mapper = new DozerBeanMapper();
@Override
public UserDTO sourceToTarget(UserVO var) {
return mapper.map(var, UserDTO.class);
}
}Rating: ★☆☆☆☆ Performance: ★★☆☆☆ Method: Recursive property mapping. Comment: Poor performance; avoid using.
10. ModelMapper
@Component
public class ModelMapperAssembler implements IAssembler<UserVO, UserDTO> {
private static ModelMapper modelMapper = new ModelMapper();
static {
modelMapper.addMappings(new PropertyMap<UserVO, UserDTO>() {
@Override
protected void configure() {
map().setUserId(source.getUserId());
}
});
}
@Override
public UserDTO sourceToTarget(UserVO var) {
return modelMapper.map(var, UserDTO.class);
}
}Rating: ★★★☆☆ Performance: ★★★☆☆ Method: ASM‑based mapper. Comment: Good for small batches; performance drops with large volumes.
11. JMapper
JMapper<UserDTO, UserVO> jMapper = new JMapper<>(UserDTO.class, UserVO.class,
new JMapperAPI()
.add(JMapperAPI.mappedClass(UserDTO.class))
.add(JMapperAPI.attribute("userId").value("userId"))
.add(JMapperAPI.attribute("userNickName").value("userNickName"))
.add(JMapperAPI.attribute("createTime").value("createTime"))
);Rating: ★★★★☆ Performance: ★★★★★ Method: High‑performance bytecode mapper. Comment: Very fast but integration with SpringBoot can be a bit cumbersome.
12. MapStruct
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE, unmappedSourcePolicy = ReportingPolicy.IGNORE)
public interface UserDTOMapping extends IMapping<UserVO, UserDTO> {
UserDTOMapping INSTANCE = Mappers.getMapper(UserDTOMapping.class);
@Mapping(target = "userId", source = "userId")
@Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
UserDTO sourceToTarget(UserVO var);
@Mapping(target = "userId", source = "userId")
@Mapping(target = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
UserVO targetToSource(UserDTO var);
}Rating: ★★★★★ Performance: ★★★★★ Method: Compile‑time generated getters/setters. Comment: Fastest, type‑safe, and easy to integrate with Spring.
4. Summary
All object‑property conversion tools ultimately rely on reflection, AOP, CGLIB, ASM, or Javassist at runtime; the best approach is to generate the necessary getter/setter code at compile time, which is exactly what MapStruct does. Regardless of the chosen library, thorough testing is essential to avoid hidden pitfalls.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
