DAO的演进

这个思考源于最近项目中对DAO的使用和讨论。数据访问对象,在贫血模型下,要怎样去设计,框架需要完成什么,后续的开发人员需要关注什么,设计的时候到底需要把握怎样的粒度?

最早做项目的时候,是老老实实给每个必要的模型增加DAO接口和实现类的:

public interface IUserDAO{
     public long add(User user);
     public void delete(User user);
     public int count(String condition);
     ... ...
}
public class UserDAOImpl{
}

这样做的好处是针对每个模型都可以自由地扩展和定义想要的数据访问方法,但是明显缺乏控制,每个人实现自己的东西,基础增删改查这种通用的逻辑没有办法规约起来,也没有办法重用起来。

查询条件的部分,上面用了一个字符串拼接sql语句的片段传入,这其实是让数据层的东西泄漏到业务层去了,不是一个好的实现;但是也要看到,对于复杂的查询方案,这又是比较容易实现的。

————————————————————————————————————-

后来做了一些改进,采用了下面这种DAO模型:

IBaseDAO ← BaseDAOImpl
      ↑                      ↑
IUserDAO ← UserDAOImpl

IUserDAO实现IBaseDAO接口,同时BaseDAOImpl是IBaseDAO的一个增删改查的基本实现,而UserDAOImpl继承自BaseDAOImpl,又实现了IUserDAO接口。

这样一来起码增删改查这样标准的简单操作全部统一起来了,也不需要在各个模型中重新定义。借由iBatis框架,把SQL语句全部放到xml里去,而又因为有了BaseDAOImpl这个通用实现,对于大多数只需要增删改查的模型来说,在实现类中就不需要做任何事情了。

对于条件查询,部分可以通过对模型中字段取值的特殊情况来处理,name取值为null表示不把该字段放入where子句中,否则则作为匹配条件:

< if test = "name != null" >
     AND NAME LIKE '%#{name}'
</ if >

不过把增删改查(CRUD)这样的基础方法(或者可以增加一些其他的方法)放到基类中也存在一些问题。比如有的类其实不需要update方法,但是没有办法,BaseDAOImpl给实现了——换言之,实现或暴露了本不想实现或暴露的方法,这是让DAO的调用者不舒服的地方。

对于复杂的查询,当时我们引入了少量查询对象,避免了DAO的以外的上层去拼接SQL语句。但是查询对象并不总是一个好东西,往往使得整个对象很庞大,设计很臃肿:

Criteria c = session.createCriteria(User. class );
c.add(Restrictions.eq( "name" ,name));
c.add(Restrictions.lt( "age" , 18 ));

如果是某些动态语言,查询对象可以做到优雅一些:

userDAOImpl.query({
     name: 'Jimmy' ,
     desc: {like: '%funny' }
     age:  and(
         {lt:30},
         {gt:18}
     )
});

如果用Java等语言实现,代码可能写不了那么漂亮,不过也可以做得优雅一些,比如这种链式调用:

CriteriaBuilder.eq( "name" , "Jimmy" ).like( "desc" , "%funny" ).and().gt( "age" , 18 ).lt( "age" , 30 ).and0().toCriteria();

————————————————————————————————————-

最近的项目,则是干脆把实现类全部都省了,用Spring对AOP支持的方式,把这些DAO的实现全部指引到一个GenericDAOImpl上了:

public interface IBaseDAO<T>{
     List<T> list(Map<String, String> conditions);
     void create(T object);
     ... ...
}
public class GenericDAOImpl<T> extends DAOSupport implements IBaseDAO<T>{
}

不同的模型DAO可以完成自己各异的查询方法定义,但是最基础的增删改查全部都由IBaseDAO定义,而所有DAO的实现全部都被Spring拦截后指向GenericDAOImpl完成——换言之,不需要写任何DAO的实现类,而且连类定义都免了。

但是有利必有弊,除了前面提到的会不得不暴露所有增删改查基础接口的问题,这样的方式还使得对每个DAO做不同的灵活扩展不太容易,而且固定的接口为了通用性可能显得有些啰嗦(比如我在查询时只需要返回一个数的时候,由于查询接口被定义为返回一个对象的链表,所以被迫要把这个数封装到对象里,再塞进一个链表中返回),当然这也算是框架给开发人员带来的约束力。

值得一提的是,查询条件呢?这次用一个Map来承载,看起来这样查询条件的控制就比较灵活,比如:

map.put( "name" , "Jimmy" );
map.put( "ageGreatThan" , "18" );

而这样的map业务语义只有到了存储查询sql的xml中才能被理解,例如上面的条件也许会变成这样的子句:

where name like '%#{name}'
<if test= "ageGreatThan != null" >
     and ang > #{ageGreatThan}
</if>

总之,相较于查询对象,用map的方式就要自如得多。但是有利必有弊,map方式也存在一些问题,比如多数情况下嵌套层次不如对象易于理解,比如说对开发人员的约束力弱,实现可能五花八门,而且如果拼写错误,在insert/update/delete操作的时候后果会尤其严重。举例来说,有这样一条SQL:

delete from user u
where
< if test = "name != null" >
u.name = '#{name}'
</ if >
... ...

要根据用户名字来删除记录,如果匹配该条件的参数写错了,比如写成这样(多写了一个“s”):

map.put( "names" , "Jimmy" );

就失去了通过该条件寻找被删除条目的能力,导致全表数据被清空。所以通常不建议在update/delete/insert的时候使用map来传递参数,还是考虑对象方式传参优先,map只是在查询的语义下显得更加适合。

————————————————————————————————————-

上面的代码经过了这样三个步骤的演进过程:

  1. DAO接口和实现全部都要开发人员自己实现;
  2. 抽象出部分共同的基础增删改查方法不需要实现;
  3. 将所有实现全部约束到同一个DAOImpl中,开发人员只需要实现各个模型的DAO接口。

看起来逐步地后续开发人员的工作似乎越来越少了,那么能不能达成终极的第4步,把这个工作全部省去,让DAO层完全由框架自动完成呢?

其实也是可以的,只是这个时候DAO方法的执行只能被约束在比较有限的几个增删改查基础方法之内了,这样的DAO是完全不具备业务语义的——换言之,真正将业务逻辑从DAO解耦出去了。

这种情况下后续的开发人员只需要完成存放SQL的xml文件,如果命名按照规约来办,连这个存放SQL的xml文件都可以省去(请参见Grails利用Hibernate自动生成数据库、增删改查的SQL语句,自动完成OR mapping的过程),只是,很多情况下看起来美好而已,这样的解耦未必是一件好事:我们始终要在各种利弊的分析和选择中权衡,如果因为性能等原因需要涉及到联表查询怎么做?业务语义已经不能侵入DAO层了,那么只能以某种方式在DAO外上方的Service来实现条件的拼装,可以用代码来实现,也可以用某种自定义的DSL来实现,这又容易显得过于臃肿了。

所以,兼容也好,灵活也好,都要讲究个度,在DAO层的设计上亦如此。权衡的技巧。没有通用的和完美的解决办法,只有适合和不适合一说而已。

文章系本人原创,转载请注明作者和出处(http://www.raychase.net)

注:本博客已经迁移到个人站点 http://www.raychase.net/ ,欢迎大家访问收藏,本ITEye博客在数日后将不再更新。

Web3与DAO:下一代互联网演进逻辑 随着科技的不断发展,互联网已经成为我们生活中不可或缺的一部分。然而,随着时间的推移,人们对互联网的期望也在不断演变。Web3和DAO(去中心化自治组织)正成为推动下一代互联网演进的关键力量。 阅读详情

相关推荐

区块链技术的演进与应用:代币化、DAO与私有链

本文探讨了区块链技术如何从1.0版本演化到2.0版本,介绍了区块链代币化、去中心化自治组织(DAO)的概念,以及公有链与私有链的区别。通过案例分析,解释了稳定币的运作原理和DAO如何通过智能合约实现自治。同时,文章也阐述了私有链在特定应用场景下的优势,如供应链管理,以及公钥基础设施(PKI)在私有链中如何确保网络访问权限的安全。

weixin_35756637的博客 516

一、数据持久层Dao层代码的演变

一、开发回顾 Struts:基于mvc模式的web层的框架。 Hibernate:基于持久层的框架(数据持久层) 二、Dao层代码的演变 1.操作XML,使用XML作为数据库。 2.使用JDBC技术 a.使用JDBC1.0的API(最原始的jdbc操作。Connectiin/ResultSet/Statement) 数据连接...

weixin_45602227的博客 472

深入理解ODBC和DAO在数据库编程中的应用

本文深入探讨了ODBC(开放式数据库连接)和DAO(数据访问对象)在数据库编程中的应用及架构。ODBC作为标准化的数据库访问方法,通过SQL翻译机制简化了应用程序与多种数据库的通信。DAO提供了面向对象的API,允许与关系型和面向对象的数据存储进行交互。文章还讨论了ODBC驱动程序管理员、驱动程序管理器、ODBC驱动程序以及ODBC API的程序化序列,包括如何连接数据源、分配语句句柄、准备和执行SQL语句、获取结果以及提交事务。通过这些介绍,为数据库开发者提供了理解传统数据库API的宝贵洞察。

weixin_36019375的博客 314

DAO 治理的技术演进:从 Snapshot 到 AI 辅助决策的去中心化自治组织未来形态

DAO 治理的三代演进,表面上是技术工具的迭代——从 Governor 合约到 Snapshot 签名到 AI 风险模型——本质上是对"去中心化决策效率"这一矛盾的持续求解。第一代追求"完全去信任",但 Gas 成本限制了参与;第二代通过链下签名降低了门槛,但引入了多签信任假设;第三代尝试用 AI 填补信息鸿沟,让投票者基于更充分的上下文做出决策。

qq_40635035的博客 5419

看完这篇爽文我终于学会了示波器(一)

示波器基础篇的介绍,希望对你有用,下次分享一下如何测试。

qq_45508321的博客 973

Win10系统权限深度解析:如何安全地将C盘所有者从TrustedInstaller变更为Administrators

本文深入解析了Win10系统中C盘文件权限管理的核心机制,解释了为何管理员账户(Administrators)默认无法修改由TrustedInstaller保护的系统文件。文章在强调安全风险的前提下,详细提供了通过图形界面和命令行两种方式,将文件或文件夹所有权从TrustedInstaller安全变更为Administrators的实操步骤,并给出了关键的风险预警与权限恢复方法。

weixin_29305313的博客 549

从DAO到领域驱动:Go项目中的分层架构演进之路

本文探讨了Go项目中从DAO模式到领域驱动设计(DDD)的架构演进过程。通过分析传统DAO模式的局限性,介绍了DDD的核心概念如实体、值对象和聚合根,并提供了Go语言实现示例。文章重点讲解了领域模型与数据模型的转换策略、事务边界设计以及GORM在DDD中的适用性,为开发者提供了渐进式重构复杂业务系统的实践指南。

vodka的博客 966

Ubuntu安装opencv4.5(自己安装过程详细)

1.下载opencv 在opencv官网下载source版,下载链接 http://opencv.org/releases.html。别下载错版本 下载过程就不多说了。 2.安装过程 2.1解压 unzip opencv-4.5.0.zip cd opencv-4.5.0 2.2安装依赖的库 sudo apt-get install cmake sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev libavformat-

weixin_45629790的博客 1万+

2024三掌柜赠书活动第八期:Web3与DAO:下一代互联网演进逻辑

随着区块链技术的崛起,Web3和DAO成为了当前互联网领域炙手可热的话题,它们代表了一种新的互联网演进逻辑,将互联网从中心化和垄断的模式转变为去中心化和民主化的模式。本文将探讨Web3和DAO(去中心化自治组织)的概念,并讨论它们如何成为下一代互联网的演进逻辑。我们将介绍Web3的基本原则和技术,以及DAO的工作原理和应用场景,通过深入了解这两个概念,读者将能够理解Web3和DAO对互联网发展的重要性,并展望未来的发展方向。Web3是一场基于加密货币和DAO的革命。

全沾软贱开发攻城狮 1万+

(二)使用VS2022克隆下载C++自制植物大战僵尸游戏教程

本文将介绍如何使用VS2022克隆下载《植物大战僵尸C++自制版本》。Gitee项目地址:Gitee仓库地址Github项目地址:Github仓库地址游戏官网地址(下载可直接运行)游戏官网。

尔灵尔亿的博客 4930

NXP S32k3 MCAL ADC配置

S32K3 配置MCAL ADC

Leon_0125的博客 5071

以太坊智能合约的历史里程碑: 从DAO到数据隐私的技术演进

在短短的几年内,以太坊不仅成为了去中心化应用和智能合约的主导平台,而且也见证了区块链技术和应用的多次重大革命。本文详细回顾了自2016年至今,以太坊生态所经历的几个关键时刻与技术浪潮,包括DAO事件、ICO热潮、DeFi的崛起、NFT市场的兴起,Layer 2技术和跨链解决方案,以及对数据隐私和计算的关注。一、时间线2016年DAO(去中心化自治组织)代表项目**(The DAO) ,** DAO项目募集了大约1.5亿美元的众筹资金,成为当时最大的众筹项目。The DAO创始。

知识的共享,拓宽视野,深化思考,获得新的启发. 1531

Autosar软件组件分析及ARXML文件分析

Autosar软件组件分析及ARXML文件分析

专注汽车软件开发、AutoSAR、车载以太网、SOA、EE架构。 3601

解锁区块链治理新范式:DAO赋能DApp开发的全链路创新指南

在区块链技术从概念验证迈向产业落地的关键阶段,去中心化自治组织(DAO)正以颠覆性的治理模式重塑数字经济的底层逻辑。当传统企业仍在为组织架构的科层制困局焦头烂额时,DAO已通过智能合约构建起无需中央权威的决策网络。

2501_91377248的博客 841

【Arduino+ESP32专题】CP2102串口自动下载电路

CP2102串口自动下载电路原理是什么?

一点硬件 2956

PyCharm 配置 Anaconda 环境时找不到 python.exe 的解决办法

通过本文的排查步骤与详细解决方案,你应该能够迅速定位并修复 PyCharm 配置 Anaconda 环境时找不到 python.exe 的问题。确保正确设置环境路径、激活目标环境以及手动指定解释器路径是解决此问题的关键。随着开发工具与包管理器的不断更新,类似的问题可能会出现新的变体。持续关注官方文档、社区讨论和版本更新,可以帮助开发者及时适应新变化,并优化工作流程。希望本文提供的分析和代码示例能为你的开发环境配置带来帮助,让你在 PyCharm 与 Anaconda 的高效协同下,专注于创新与代码实现。

s13596191285的博客 3117

spring 中的DAO是什么

在 Spring 中,DAO 是数据访问层的核心设计模式,通过解耦、模板化和标准化,显著提升代码的可维护性和可扩展性。是一种设计模式,它的核心目标是将数据访问逻辑与业务逻辑解耦,提供一种标准化的方式操作数据源(如数据库、文件、外部 API)。Spring 对 DAO 模式提供了强大的支持,通过依赖注入、模板设计模式、统一的异常体系等特性,简化了数据访问层的开发。:将数据访问逻辑(如 SQL 查询、事务管理)封装在 DAO 层,业务层(Service 层)只需调用 DAO 方法,无需关心底层数据源细节。

LCY133的博客 1220

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

DAO与Mapper:数据访问层的两种实现范式

本文系统解析了Java持久层中DAO与Mapper的关系。DAO是经典设计模式,通过抽象接口实现数据访问层的解耦;Mapper则是MyBatis框架对DAO模式的具体实现,采用动态代理自动生成实现类。二者本质上是设计模式与具体实现的关系:DAO是数据访问层的抽象规范,Mapper是该规范在MyBatis中的特定实现方式。文章通过演进历程分析指出,从传统DAO到MyBatis Mapper的发展体现了持久层技术的简化趋势,并给出不同场景下的实践建议。关键在于区分设计思想与实现方式,根据项目需求灵活选用最合适的

wsj__WSJ的博客 1206

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

dao模式和前端控制器结合使用_前端技术演进(五):现代前端交互框架

这个系列来自之前做的内部培训,删减了业务相关的部分,如有错误,欢迎指出。鉴于知乎文章编辑器呵呵的体验,可能会有排版错误,如发现也请指正。系列目录:jnoodle:前端技术演进(一):Web前端技术基础​zhuanlan.zhihu.comjnoodle:前端技术演进(二):前端与协议​zhuanlan.zhihu.comjnoodle:前端技术演进(三):前端安全​zhuanlan.zhihu.c...

weixin_39797780的博客 241

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

分布式自治组织 DAO

定义 先给出 DAO 一句话的定义:一个由代码控制的组织。 区块链跟互联网一样,更多的是改变了人和人协作的方式。所以区块链研究的各个方向中,很重要的一个就是 Institutional Technoloay 制度技术。区块链带来了自动化的信任系统,人们可以在无需信任对方,或者第三方的情况下,去自由的进行价值传递。也就是说,我给你在网上转账,就跟我当面给你现金一样,是一个只有你我双方参与的事情。而做到了这一点,就带来了货币的可编程性,组织的管理就有可能通过代码来自动完成了。 总之, DAO 是代码管理的组织,

lgyfhk的博客 1147

DAO组织应当如何有效进行资金管理? |链捕手

DAO组织在DeFi生态扮演着越来越重要的作用,其中一个重要命题则是DAO组织作为一种新事物应当如何管理其金库资产,如今各类DAO组织管理资产超过140亿美元,其管理策略的重要性愈发凸出。...

659

机器学习专项课程实验:零基础环境与部署指南

这个仓库是斯坦福大学与 DeepLearning.AI 合作的 Machine Learning Specialization 课程(2022 版)配套解题与笔记,覆盖从回归到强化学习的全部三周内容。下面是一份面向新手的环境搭建与跑通指南,帮你从零把第一份课程实验在本地跑起来。 [![单变量线性回归模型:训练集、假设与代价曲线](https://raw.gitcode.com/gh_mirror

gitblog_00894的博客 139

DAO 模式详解:数据访问层的设计与实现

DAO 模式详解:数据访问层的设计与实现

weixin_51288065的博客 691

互联网分层架构之-DAO与服务化

互联网分层架构的本质,是数据的移动。 互联网分层架构演进的核心原则: 让上游更高效的获取与处理数据,复用 让下游能屏蔽数据的获取细节,封装 这些在上一篇《互联网分层架构的本质》中有详尽的描述,在实际系统架构演进过程中,如何利用这两个原则,对系统逐步进行分层抽象呢?咱们先从后端系统开始讲解。 本文主要解答两个问题: 后端架构,什么时候进行DAO层的抽象...

HelloWorld搬运工 764

DAO:重构人类协作的“数字基因组”——从比特币到全球自治社区,一场静默的组织革命

这些场景的共同底色是DAO(Decentralized Autonomous Organization,去中心化自治组织)——一种通过智能合约编码规则、由全球成员共同治理的新型组织形态。它正以“代码即法律”的逻辑,颠覆传统公司、协会甚至国家的协作范式。

2501_91377248的博客 846
上一篇: Dart,你凭什么挑战JavaScript?
下一篇: 对象转换的问题
RayChase
博客等级 码龄20年 71粉丝 87原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值