gpt4 book ai didi

java - 对将父方法映射到不同类的子类进行相同的删除

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:05:47 25 4
gpt4 key购买 nike

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

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

所以它最终看起来像:

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()
);
}
}

但是,这不适用于我们只处理 pojo 和表的经典 DAO 案例。

不过,这里有一个共同的功能,可以抽象成更基本的 AbstractDao,跨项目有用。像这样的东西:

AbstractDao<T extends DatabaseTable, R extends Record>

它有一个子类

AbstractMappedDao<T extends DatabaseTable, R extends Record, M> extends AbstractDao<T, R>

Abstract 有一个像这样的方法:

public List<R> insert(List<R> records) {
connection.insertBulk(records);
}

Mapped 应该有一个像这样的方法:

public List<M> insert(List<M> records) {
super.insert(StreamEx.of(records).map(mapper::map).toList());
}

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

我已经尝试将它抽象成一个接口(interface):

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

并使 Abstract 实现 Dao 和 Mapped 实现 Dao,但同样的问题。

所以我的问题是如何最好地解决这个问题?如果我将 map 的签名更改为类似以下内容,这将按预期工作:

insertMapped(List<M> mapped);

但我宁愿保持契约(Contract)不变。

感谢您的帮助。期待讨论!

最佳答案

当谈到组合行为时,总是最好使用组合而不是继承,这实际上就是您的情况。 mapper 不会增强 已经存在于您的Dao 中的行为,而是添加 行为,一个额外的间接层在里面;这不一定是 Dao 的关注点,例如 aspect/cross cutting concern .

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

        private Map<Class, Function> mappers;

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

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

        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;
}

这更简洁、更健壮且更具可扩展性,因为您的插入可以用组合的关注点以集中的方式处理各种关注点。完整的编译代码如下所示:

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) {}
}

Complete code on GitHub

希望这对您有所帮助。

关于java - 对将父方法映射到不同类的子类进行相同的删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56195282/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com