首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将父方法映射到不同类的for子类的相同擦除

将父方法映射到不同类的for子类的相同擦除
EN

Stack Overflow用户
提问于 2019-05-18 01:29:49
回答 1查看 169关注 0票数 2

我正在尝试重构一个DAO,以使它在我们的代码库中更加可用。我们目前有一个参数化的AbstractDao,它接受三种类型:

  1. 数据库表
  2. 数据库pojo
  3. 不同映射的pojo表示形式为2)

所以它看起来就像:

代码语言:javascript
复制
public class AbstractDao<T extends DatabaseTable, R extends DatabaseRecord, M> {
  public AbstractDao(Connection connection, Mapper<R,M> mapper) {
  //save connection and mapper to protected variables
}
public List<M> insert(List<M> records) {
 connection.insertBulk(
   StreamEx.of(records).map(mapper::map).toList()
 );
 }
}

但是,这并不适用于经典的DAO案例,在这种情况下,我们只处理pojo和表。

但是,这里有一个通用的功能,可以抽象成一个更基本的AbstractDao,它在各个项目中都很有用。类似于:

代码语言:javascript
复制
AbstractDao<T extends DatabaseTable, R extends Record>

它有一个子类

代码语言:javascript
复制
AbstractMappedDao<T extends DatabaseTable, R extends Record, M> extends AbstractDao<T, R>

摘要有一个方法,如:

代码语言:javascript
复制
public List<R> insert(List<R> records) {
  connection.insertBulk(records);
}

映射的方法应该如下:

代码语言:javascript
复制
public List<M> insert(List<M> records) {
  super.insert(StreamEx.of(records).map(mapper::map).toList());
}

但是,这会产生“相同的擦除”问题,因为insert接受泛型列表。

我尝试将它抽象到一个接口中:

代码语言:javascript
复制
public interface Dao<T> {
  public List<T> insert(List<T> records);
}

并且使抽象实现了Dao和映射实现了Dao,但是同样的问题。

所以我的问题是如何最好地解决这个问题?如果我将地图的签名更改为如下所示,则此操作与预期的相同:

代码语言:javascript
复制
insertMapped(List<M> mapped);

但我宁愿保持合同不变。

谢谢你的帮助。期待着大家的讨论!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-18 03:16:49

当涉及到组合行为时,最好是使用组合而不是继承,这实际上就是您的情况。mapper并没有增加Dao中已经存在的行为,而是添加了行为,这是一个额外的间接层;这不一定是Dao所关心的,就像https://en.wikipedia.org/wiki/Aspect-oriented_programming一样。

因此,我的建议是创建一个AbstractDao类,该类具有组合mappers的能力(您可以根据自己的需要创建一个;但是使用组合可以很容易地允许单个Dao对象支持多个映射器):

代码语言:javascript
复制
        private Map<Class, Function> mappers;

        public <M> void registerMapper(Class<M> mappingClass, Function<M, R> mapper) {
            mappers.put(mappingClass, mapper);
        }

然后创建一个insert方法,该方法允许使用它注册的mappers处理未扩展Record的记录的预转换,如下所示:

代码语言:javascript
复制
        public <M> List<M> insert(List<M> records) {
            if (records.isEmpty()) return records;
            M rec = records.get(0);

            List<? extends Record> actualRecords = (rec instanceof Record) ? 
                    (List<Record>)records : createMappedRecords(records, rec.getClass());

            connection.insertBulk(actualRecords);
            return records;
        }

这是更干净、更健壮和更可扩展的,因为您的insert可以使用组合的关注点集中处理各种关注点。完整的编译代码如下所示:

代码语言:javascript
复制
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class ParentErasure {

    public abstract class AbstractDao<T extends DatabaseTable, R extends Record> {
        private Connection connection;
        private Map<Class, Function> mappers = new HashMap<>();

        public <M> void registerMapper(Class<M> mappingClass, Function<M, R> mapper) {
            mappers.put(mappingClass, mapper);
        }

        public <M> List<M> insert(List<M> records) {
            if (records.isEmpty()) return records;
            M rec = records.get(0);

            List<? extends Record> actualRecords = (rec instanceof Record) ? 
                    (List<Record>)records : createMappedRecords(records, rec.getClass());

            connection.insertBulk(actualRecords);
            return records;
        }

        private <M> List<R> createMappedRecords(List<M> records, Class<? extends Object> recordsClazz) {
            Function<M, R> mapper = mappers.get(recordsClazz);
            return records.stream()
                    .map(mapper::apply)
                    .collect(Collectors.toList());
        }
    }

    public interface Dao<T> {
        public List<T> insert(List<T> records);
    }
}

class Record {}
class DatabaseTable {}
class DatabaseRecord {}
class Connection {
    public void insertBulk(List<? extends Record> records) {}
}

GitHub上的完整代码

希望这能有所帮助。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56195282

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档