让我们考虑一个简单的DAO模式示例 . 设 Person
是一个值对象, PersonDAO
是对应的特征,它提供了与数据库存储/检索 Person
的方法 .
trait PersonDAO {
def create(p:Person)
def find(id:Int)
def update(p:Person)
def delete(id:Int)
}
如果我们想要分离业务域和持久性逻辑,我们使用这种模式(例如,与Active Record相对) .
如果我们使用another approach会怎么样?我们将创建 PersonDatabaseAdapter
trait PersonDatabaseAdapter{
def create
def retrieve(id:Int)
def update
def delete
}
从 Person
到它的隐式转换 .
implicit def toDatabaseAdapter(person:Person) = new PersonDatabaseAdapter {
def create = ...
def retrieve(id:Int) = ...
def update = ...
def delete = ...
}
现在,如果我们导入这些转换,我们可以编写客户端代码来操作 Persons
并以下列方式将数据存储/检索到数据库:
val person1 = new Person
...
person1.create
...
val person2 = new Person
...
person2.retrieve(id)
...
此代码看起来像 Active Record
但业务域和持久性仍然是分开的 .
是否有意义 ?
4 回答
好吧,我对“过时”的模式一无所知 . 模式是一种模式,您可以在适当的地方使用它 . 此外,我不知道语言是否应该在语言中过时,除非语言本身使用相同的功能实现它 .
据我所知,数据访问对象并不过时:
http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
http://en.wikipedia.org/wiki/Data_access_object
在我看来,你仍在使用DAO模式 . 您刚刚以不同方式实现了它 .
我实际上发现了这个问题,因为考虑到Hibernate的强大功能,我正在研究DAO模式是否在普通的Java中死了 . 看起来Hibernate Session是DAO的通用实现,定义了诸如create,save,saveOrUpdate等操作 .
在实践中,我发现使用DAO模式没什么 Value . 当使用Hibernate时,DAO接口和实现是围绕单行Hibernate Session惯用语的冗余包装器,例如getSession() . update(...);
您最终得到的是重复接口 - 一个服务接口,它重新定义了DAO接口中的所有方法以及根据这些接口实现的其他几个方法 .
似乎Spring Hibernate几乎将持久性逻辑降低到了微不足道的程度 . 几乎所有应用程序都不需要持久性技术可移植性 . Hibernate已经为您提供了数据库可移植性 . 当然,DAO会让你有能力从Hibernate变为Toplink,但在实践中,人们永远不会这样做 . 持久性技术已经是漏洞抽象,应用程序是为了处理这一事实而构建的 - 例如加载用于设置关联的代理与执行数据库命中 - 这必然将它们与持久性技术相结合 . 与Hibernate耦合并不是那么糟糕,因为它尽力避开(没有检查过的例外,JDBC和其他废话) .
总之,我认为你的DAO模式的Scala实现很好,尽管你可能创建一个完全通用的mixin,它可以为任何实体提供基本的CRUD操作(大多数有能力的开发人员倾向于在Java中实现“泛型DAO”基类) ,也) . 这是Active Record的作用吗?
/随机评论结束/
我相信你的
PersonDatabaseAdapter
在其retrieve(id: Int)
方法中改变Person
. 因此,这种模式会强制您的域对象变得可变,而Scala社区似乎由于语言的功能性(或特性)而倾向于不可变性 .否则,我认为DAO模式在Scala中仍然具有与在Java中相同的优点和缺点(列为here) .
现在我注意到Repository模式非常受欢迎,特别是因为它的术语使它看起来像你正在处理集合 .