在企业应用的开发中,经常对遇到一些非常复杂的查询,尤其是需要对很多表进行关联查询。而在DAO对象中无法将这种需求封装起来,这就造成不得不在业务逻辑中包含与持久化机制相关的代码(虽然可以做到仅仅是传送一条String型的SQL语句,但毕竟这也与持久层发生了耦合,味道很坏),请问各位高人有没有什么好的办法解决这个问题,谢谢!!!!
按照Evans DDD,尽量使用Critirea,也可以将这些SQl作为领域的业务规则。
我也曾考虑过用Criteria这种更加面向对象的方式(纠正一下,应该Criteria是面向对象的SQL,HQL才是完全面向对象的),可惜Hibernate对Criteria的实现还不够完善,官方也推荐HQL。
另外,如果在业务逻辑中使用Criteria就得使用Session,这就还是没办法与持久层实现分离。似乎跟直接传String型的HQL语句到DAO对象的find方法没什么区别,甚至更复杂了。
至于设计为业务规则,也有一定难度,比如本身就是要做一个查询引擎,查询条件就是由用户来动态设置这种情况。
请问还有什么其它更好的办法吗?
[该贴被maybeiamtooold于2008-01-24 22:38修改过]
[该贴被maybeiamtooold于2008-01-24 22:40修改过]
[该贴被maybeiamtooold于2008-01-24 22:43修改过]
Evans DDD中专门有一个specification章节讨论这个问题,结合筛选,后面还谈到规格的组合设计,当然如果觉得SQL放在模型specification中不太好,也可以放入仓储中,specification需要和仓储进行交互。
这些方式其实都是说明:将复杂的SQL语句分离,变成模型对象的过滤和筛选,这样,我们就可以动态建立一些过滤器或筛选组件,对来自仓储的领域模型进行层层筛选最后变成客户端需要的结果。
具体可以参考JiveJdon3的一些复杂查询,在JiveJdon3的持久层中很难见到复杂的SQL语句,难道这个论坛不需要复杂的SQL语句?当然不是,而是我们将之分解了,很多组合筛选动作在内存中实现,然后将筛选结果cache,避免多次操作浪费性能。
>业务逻辑中使用Criteria就得使用Session,这就还是没办法与持久层实现分离
这是因为你使用了Hibernate的Criteria,可以制造自己的Criteria,我在JiveJdon3中就这样做了,不依赖持久层。
虽然可以通过自建Criteria来实现和持久层的分离,但这算不算重新发明轮子呢?
只要自己有创新和需求就不是重新发明轮子,学以至用,用可创新,创新为需!
Criteria是一种很理想的解决方案,(当然不是指Hibernate的Criteria,即使Hibernate的Criteria将来设计的如何完美,我们也不能让持久层框架直接以它作为查询的OO封装,因为这样我们的持久层使用者,通常是业务层就必须耦合于Hiernate了,所以Criteria应该是独立设计的接口,实现当然可以来源于任何地方,包括Hibernate)。
但,问题还是,要设计一个能符合多种复杂查询的完全OO的Criteria,确实不是一件容易事情,至少Hibernate还没能很好的解决。