【问题标题】:Spring Boot mapper with generic Service具有通用服务的 Spring Boot 映射器
【发布时间】:2019-11-16 00:38:08
【问题描述】:

我正在尝试使用 Java 框架 Spring Boot 制作通用架构。

我尝试的映射器似乎没有像 .Net Core 框架中的 Automapper 这样的通用方法 -> Mapper.Map<TEntity>(source)

有没有办法在不传递目标的情况下在 Spring Boot 中实现泛型映射?因为我的目标是TEntity,无法直接实例化(T target = new T();)直接在方法(mapper.map(source, target))中传递。

在Service层的.Net Core框架中有一个我想用C#实现的例子。

public virtual TDataTransferObject Insert(TInsertDTO request){
   var entity = Mapper.Map<TEntity>(request);
   return Mapper.Map<TDataTransferObject>(Repository.Add(entity));
}

【问题讨论】:

标签: java spring-boot dto


【解决方案1】:

我的经验主要是ModelMapper,它只映射在两个对象之间或从一个对象映射到一个目标类。

快速浏览一下其他流行的mappers,它们在这方面提供了类似的功能,可能是因为Java 中的Type erasure

要解决该限制,应将泛型类的类型作为字段添加到基类中。 一种解决方案是将其作为参数传递给基类的构造函数。 另一种是使用反射:

public abstract class BaseService<E> {

    private final Class<E> entityClass;
    private final ModelMapper mapper;

    protected BaseService(ModelMapper mapper) {
        this.mapper = mapper;
        entityClass = getEntityClass();
    }

    @SuppressWarnings("unchecked")
    private Class<E> getEntityClass() {
        return (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass())
           .getActualTypeArguments()[0];
    }

    public <I, O> O insert(I inputData, Class<O> outClass) {
        E entity = mapper.map(inputData, entityClass);
        O outData = mapper.map(entity, outClass);
        return outData;
    }
}


public class FooService extends BaseService<Foo> {

    public FooService(ModelMapper mapper) {
        super(mapper);
    }
}

public class Demo {

    public static void main(String[] args) {
        FooService service = new FooService(new ModelMapper());

        Foo foo = new Foo("foo");
        Baz baz = service.insert(foo, Baz.class);
    }
}

Live demo

比较Performance of Java Mapping Frameworks的文章

【讨论】:

  • 感谢您分享您的想法,但我在尝试在构造函数中初始化 entityClass 时遇到了即时错误。它不允许我将类型参数转换为Class&lt;E&gt;。顺便提一句。这是我的 BaseService public class BaseService&lt;TEntity, TDto, IdType&gt; implements IBaseService&lt;TEntity, TDto, IdType&gt; { ... }
  • @Adnan 请显示代码及其产生的确切错误。您没有将Class&lt;E&gt; 用于BaseRntity&lt;TEntity, ...&gt; 课程,不是吗(应该是Class&lt;TEntity&gt;)?顺便说一句,这是我的一个简单的project,其中使用了这个概念。
  • 是的,我正在使用Class&lt;TEntity&gt;,这里是code 的链接。我会看看你的项目。顺便提一句。别介意你觉得奇怪,这是我的第一个 Spring Boot 测试项目,那可能是因为缺少好的 Spring Boot 演示和文档。
  • @Adnan 我已经检查了您项目的存储库,但恐怕那里存在更严重的问题。我建议您阅读更多有关 Java 泛型的内容。例如public class CrudService&lt;TEntity, TDto, Type, TUpdate, TInsert&gt; extends BaseService&lt;TEntity, TDto, Type&gt; implements ICrudService&lt;TEntity, TDto, Type, TUpdate, TInsert&gt; 应该类似于public class CrudService extends BaseService&lt;Country, CountryDTO, Long&gt; 以允许Spring 创建这个bean。
猜你喜欢
  • 2022-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-29
  • 2020-10-24
  • 2015-03-22
  • 2018-10-02
  • 2019-07-08
相关资源
最近更新 更多