我记得我曾经学javaweb的时候,也是被这个问题困惑过大半年,service层到底要不要出现sql或者Hibernate的hql语句?
我曾经有和你一样的困惑,比如有一个UserDao的接口,假如我想查询User,根据Id查询可能UserDao就需要设置一个findUserById(Integer id)这样的方法,根据用户名查询就是findUserByName(String name),根据邮箱查询就是findUserByEmail(String email),可能我还需要一个模糊查询,根据用户名模糊查询findUserByNameLike(String NameLike)等等,如果我的查询条件很多,我很有可能会在UserDao里面设置很多个不同的方法!可能会导致这个UserDao的小方法泛滥的多!我当时就想,能不能UserDao里面只设置一个find方法,然后sql语句和参数都由service传入,那么这样,UserDao岂不是非常清爽简洁啦?比如findUserByQuerySql(String querySql,Object... params),service业务层负责传入sql查询语句和参数,UserDao执行通用的findUserByQuerySql就行了。
我想,听完上面我说的这段,你一定泪流满面想和我握爪,就像找到了战友一般是不是!!
不幸的是,这种方案很快就被我当时的老大否定了!!
采用这种所谓通用Dao从service接收参数的方法在大型团队中会有以下几个严重问题!
1,假如你在多个地方中调用了这个通用的findUserByQuerySql(String querySql,Object... params),很有可能你的sql语句会在service中重复,举个例子,假如你在多个地方需要通过用户名模糊查询用户,那么,每个地方,你都需要准备完全一样的querySql(参数可能不同)。也就是说,你的service层的代码会重复!你就会在多个地方复制同一段代码,如果哪一天模糊查询的方式改变了,你需要把所有涉及到此查询条件的sql语句都给找出来一个一个来改变!!在大项目中是不可想象的!(Dao模式中是把sql封装到dao的方法中,那么,相当于只要调用这个dao方法就复用了方法里面的sql)。
2,涉及到多人合作问题,你可能现在是一个人做项目,感受不到,如果项目很大,是多个人合作,你的这个通用的UserDao被多个程序员调用了,假如,我为了一个很复杂的查询,光思考sql结构都思考了老半天(不要以为sql查询就是简单的select from,我曾经见过单条100行以上的sql查询语句!),嗯,我花了大概30分钟搞定了一条复杂的sql查询,另外一个程序员恰好也需要这个功能了,这个时候,他可能也会在那里想同样的一条sql查询啊!!结果他想了2个小时才搞定,你说浪费不浪费???这还不算什么,很有可能你们对于同一个查询写出来的sql语句是不一致的!!甚至有些人写的是正确的,有些人写的是有bug的,那么,极有可能出现你们两个人对于同一个查询不一致的情况发生!这都还不算事,最恐怖的就是,如果涉及到的查询由于业务原因发生变化了,那么,每一个人都去代码中捉虫子去吧!!结果再来一次每一个人都一套自己的sql,这种糟糕的局面会像滚雪球一样,越来越严重。(采用Dao模式,只需要一个sql高手把同一个查询的sql封装到dao的方法中,所有需要此功能的只需要调用此dao的该方法就行了)。
你的本意是想让UserDao更简单点,最好只有一个通用的查询方法,出发点是好的,但是,我希望你明白一点,不是东西越少就越好,就像java程序一样,本质上都是从main方法进去,main方法出来,我把全部代码放在一个main方法,弄他个30万行,有没有问题?依我说,没问题,jvm不会拒绝的,一样执行。这样整个程序只有一个方法呢,是不是越简单越好呢?可实际情况是一个大型项目中,所有类的总和都会有上千甚至上万个,大家各司其职,把业务拆分到单元中,说的专业点,就是面向对象三大特性之一的封装了。
Dao是数据访问对象,一个业务逻辑不仅仅是访问数据,应该说,数据是业务逻辑的一个底层支撑,举个例子,把你的日常生活看作你的业务的话,那么,一日三餐饭就相当于是你的业务活动的支撑了!我们在论坛交流的目的不是为了把问题文章存到数据库中好玩,而是为了和其他人交流,实现论坛的商业或非商业需求,存到数据库的唯一理由是为了持久化,好让你明天登录还能看到你的帖子,或者其他人能够发现你的帖子!持久化本身并非是商业活动意义上的业务逻辑,他只是为了能够提供更好更智能的商业业务而设置的一个基础设施,否则,一个发了帖子第二天就看不到的论坛,谁会去用呢?
可能对于业务逻辑的概念你还是很迷糊,我再举个例子,假如现在有一个网站系统,“每天首次登录就会送10个分,重复登录不送分,发一个帖子送50个分,如果帖子被置为精华,送1000个分,如果用户捣乱犯规,一次扣500个积分,犯规三次或积分小于0,锁定用户”,注意我用引号引起来的部分,这是一个论坛逻辑,这就是一个论坛经营过程中的业务规则,这些东西都需要在service层中去实现的!只不过Dao层,对于上述业务提供了数据持久底层支撑。如果有一个神存在,它可以监控所有的数据并记在脑子里,我们就可以不需要数据库了,需要什么业务就去找神询问就行了。这个时候我们的Dao可能就变成GodBrain(神的脑子)这样一个对象呢,获取用户积分就是GodBrain.getUserPointsByUid(Integer uid)。
回到你的问题本身,把sql写到service层是不行的(如果有程序员反驳我的观点,我只能说,你做的项目太小了,或者根据就是一些纯忽悠的辣鸡项目,你根本不知道什么是大型项目的有价值的项目了),那么怎么控制Dao层中太多的小方法呢?
我觉得可以这样做,还是以UserDao为例子,我们还是设置很多个小的琐碎的查询方法,比如UserDao.findUserByName(String name),UserDao.findUserByNameLike(String nameLike),同时我们在UserDao中设置一个通用的private的私有find(querySql)方法,findUserByName这样的方法不做具体的查询工作,而只是根据用户传递进来的name啊nameLike等参数生成sql语句,生成sql语句后调用Dao中的private的find方法,这个find方法是一个通用的方法!
通过上面的解决方法,可以将Dao中的重复代码降低到最小。
你能够在这里发这样的帖子说明你是一个爱思考的人,慢慢学吧,不要轻信菜鸟同事的说法,或者大部分人的看法,多读点书,特别是那些被大家公认的好书,说句不客气的,程序员之间的差异比人和猴子之间的差异还大,所以网络上一些人告诉你的很有可能是错误的。
解决问题还是看实际需求,耦合不耦合也是看实际需求的,我很不喜欢一些人一上来就否定这个,说这个辣鸡,那个辣鸡,举个例子,你自己开个杂货铺,你有必要成立采购部,销售部,财务部吗?你有必要采用MBA的管理方式吗?显然是不需要的,但是你要是开个大企业,你就需要了,因为大企业涉及到的也无太大,人员太多,业务越复杂,就越应该拆分,越应该把一个整体软件组件化,采用分布式子系统等,否则业务错综复杂,以至于单个项目超出了人脑子能够理解的极限,无论是维护还是可理解性上都是极其困难的。分而治之就是分层思想的一个体现,也是将复杂性包裹在一个组件中不让他扩散到外部。Dao接管了整个数据库部分,如果你们公司有人很懂sql的话,他们完全可以封装一整套Dao,作为业务开发人员,你连sql都是看不到的,你只需要使用它们提供的Dao的api就行了。这样,你在做业务的时候,你的业务中不会包含任何的数据库逻辑,因为所有的数据库逻辑都被围困在Dao中而不会扩散到外部,这样,复杂性就被管理起来了,就被征服了。
很多网友说,jsp一样能干,不分层也能干,是的,这是可以的,但是这仅限于小型项目或者试验项目。如果你想成长的更快,真的在软件业有成绩,一定要把分而治之这种思想理解到一个底朝天,分布式系统,集群,SOA,消息中间件MQ等,这些东西的思想都是想通的,不要因为一个人告诉你jsp也能干你就裹足不前了。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/y_dzaichirou/article/details/53673528