抽象ModelMapper实现通用Entity-DTO转换器时,如何填充类型参数占位符?
如何实现通用的Entity-DTO转换器?
嘿,这个问题问得好!把重复的Entity-DTO转换逻辑抽象成泛型类确实是个减少冗余代码的好思路,不过你遇到的问题其实是Java泛型的类型擦除导致的——在运行时,JVM不知道T和S具体是什么类型,所以ModelMapper没法直接拿到目标类的Class对象。下面给你两种可行的解决方案:
方案一:构造函数传入目标类型Class(推荐,简单直接)
这种方法最直观,通过构造函数把T和S对应的Class对象传入转换器,存在成员变量中供map方法使用。另外建议把ModelMapper实例化一次(放到成员变量),不要每次调用转换方法都新建,能提升性能。
public class Converter<T, S> { private final Class<T> entityClass; private final Class<S> dtoClass; private final ModelMapper modelMapper; // 构造时传入两个类型的Class对象 public Converter(Class<T> entityClass, Class<S> dtoClass) { this.entityClass = entityClass; this.dtoClass = dtoClass; this.modelMapper = new ModelMapper(); } public S convertEntityToDto(T t) { return modelMapper.map(t, dtoClass); } public T convertDtoToEntity(S s) { return modelMapper.map(s, entityClass); } }
使用的时候只需要创建实例时传入对应Class:
// 创建UserEntity和UserDto的转换器 Converter<UserEntity, UserDto> userConverter = new Converter<>(UserEntity.class, UserDto.class); // 转换使用 UserDto dto = userConverter.convertEntityToDto(userEntity); UserEntity entity = userConverter.convertDtoToEntity(userDto);
方案二:通过反射获取泛型类型(适合固定转换对场景)
如果你不想每次创建转换器都手动传Class,可以利用Java反射从子类的泛型参数中提取实际类型。这种方式需要把Converter改成抽象类,然后针对每个转换对创建子类:
public abstract class Converter<T, S> { private final Class<T> entityClass; private final Class<S> dtoClass; private final ModelMapper modelMapper; @SuppressWarnings("unchecked") public Converter() { // 通过反射获取父类的泛型参数 Type genericSuperclass = getClass().getGenericSuperclass(); ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass; // 第一个泛型参数是T(Entity类型),第二个是S(DTO类型) this.entityClass = (Class<T>) parameterizedType.getActualTypeArguments()[0]; this.dtoClass = (Class<S>) parameterizedType.getActualTypeArguments()[1]; this.modelMapper = new ModelMapper(); } public S convertEntityToDto(T t) { return modelMapper.map(t, dtoClass); } public T convertDtoToEntity(S s) { return modelMapper.map(s, entityClass); } }
使用时创建具体的转换器子类(不用写任何额外代码):
public class UserConverter extends Converter<UserEntity, UserDto> { // 直接继承父类方法即可 } // 使用示例 UserConverter userConverter = new UserConverter(); UserDto dto = userConverter.convertEntityToDto(userEntity);
这种方案的好处是代码更简洁,不用每次传Class,但缺点是必须为每个转换对创建子类,而且反射有轻微的性能开销,适合那些转换关系固定的场景。
内容的提问来源于stack exchange,提问作者Dario Anguilla
相关产品推荐
相关产品推荐

