通用 DAO - “永远不要完全通用!”
Posted
技术标签:
【中文标题】通用 DAO - “永远不要完全通用!”【英文标题】:Generic DAO - "Never go full generic!" 【发布时间】:2013-05-13 19:41:18 【问题描述】:我在互联网上看到了很多通用 dao 的用法。 你一定会喜欢它:
public interface GenericDao <T, PK extends Serializable>
public class GenericDaoHibernateImpl <T, PK extends Serializable>
implements GenericDao<T, PK>
一个新的班级出现了?没问题:
public interface NewClassDao extends GenericDao<NewClass, Long>
我们都准备好了。
现在, 如果我去“全通用”并做类似的事情有多糟糕:
public interface FullGenericDao
public class FullGenericDaoHibernateImpl
现在我只能使用一个 DAO(Object with cast!)
一个新的班级又出现了? 没问题:
NewClassApperedAgain newClassAppeared = (NewClassApperedAgain) FullGenericDao.getItemById(20, NewClassApperedAgain.class);
想到两个问题:
1) 是否有可能“完全通用”并实际创建这样的 DAO?我的意思是我不明白为什么不为 dao 的每个方法传递 className 而只是进行必要的强制转换? 保存(对象,类名); 删除(对象,类名);等等。
2) 这种做法有什么缺点(我敢肯定有)?
谢谢!
【问题讨论】:
【参考方案1】:DAO 对象包含与持久层相关的领域模型特定逻辑。
您可以完全通用,但您必须面对以下问题:
我应该把与搜索相关的逻辑放在哪里(例如构造 WHERE 子句)?User findUserByOrganizationId(Serializable organizationId)
在哪里放置一些特定的映射函数(例如聚合查询)?
Map<Organization, Integer> findUserCountPerOrganization()
我很确定还有其他架构/逻辑问题。此外,泛型将在运行时被删除,因此您已经介绍了在每个方法签名中包含域对象 Class<?>
的必要性。
TL;DR 可以“完全通用”,但您需要将非共享持久性逻辑移至更高级别。最好在某些AbstractDaoImpl
中执行共享的通用逻辑,然后对其进行子类化。您最终可能会得到空的实现(通用超类可能拥有您所需要的一切),但您将拥有未来领域模型特定方法的位置。
【讨论】:
以上是关于通用 DAO - “永远不要完全通用!”的主要内容,如果未能解决你的问题,请参考以下文章