我试图重构一个DAO,使它在我们的代码库中更有用。我们目前有一个参数化的AbstractDao,它有三种类型:
1.数据库表
1.数据库pojo
- 2)的不同Mappojo表示
所以它看起来像这样:
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,在项目中很有用。
AbstractDao<T extends DatabaseTable, R extends Record>
它有一个子类
AbstractMappedDao<T extends DatabaseTable, R extends Record, M> extends AbstractDao<T, R>
摘要的方法如下:
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());
}
然而,这会产生“相同擦除”问题,因为insert会接受泛型列表。
我试着把它抽象成一个接口:
public interface Dao<T> {
public List<T> insert(List<T> records);
}
并使抽象实现道和Map实现道,但同样的问题。
所以我的问题是如何最好地解决这个问题?如果我将map的签名更改为如下形式,它将按预期工作:
insertMapped(List<M> mapped);
但我希望合同保持不变。
谢谢你的帮助。期待讨论!
1条答案
按热度按时间oaxa6hgo1#
当涉及到 * 组合行为 * 时,最好是使用组合而不是继承,这实际上就是你的情况。
mapper
并没有 * 增加 *Dao
中已经存在的行为,而是 * 增加 * 了行为,这是一个额外的间接层;这不一定是X1 M2 N1 X(如X1 E0 F1 X)所关心的。因此,我的建议是创建一个能够组合
mappers
的AbstractDao
类(您可以根据需要只创建一个类;但是使用复合很容易允许单个Dao
对象支持多个Map器):然后创建一个
insert
方法,该方法允许使用已注册的mappers
处理未扩展Record
的记录的 * 预转换 *,如下所示:这更干净、更健壮、更可扩展,因为您的
insert
可以通过 composed concerns 以集中的方式处理各种关注点。完整的编译代码看起来如下所示:Complete code on GitHub