锁定老帖子 主题:一次关于简化DAO设计的初步思考!
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2004-10-12
firebody 写道 potian 写道 DAO层还可以封装很多东西,不是简单的一个数据存取,譬如我们希望做自己的缓存,一个简单的例子例如我有一个分类树,/level1/level2/level3/,下面还可以有页面(页面可以是多级的)page1.page2.page3,在Web层可以输入
/level1/level2/level3/page1.page2.page3得到这个页面的内容,现在如果要构造这个查询语句的话就非常复杂,需要动态产生,执行的效率极低,如果是一个getPage(categoryKey,pageKey)那么我就可以在中间加入一个cache,采用编程方式也好,或者用AOPcache拦截也好,得到这个page的id,然后用getPageById(id)把他取出来。 当然这一层放在Service也可以,但这个方法可能被很多service用到,我偏向于放在DAO层次。一旦涉及到DAO被多个service所用,那么你构造参数的过程将在各个不同的service里面重复,如果你要改变的话,bang!,全部都需要变化,这是典型的重复代码的例子。 page2 page3? 这些是属于page的咚咚把。dao可以封装这么一个查询dao.getPageByName(id) (..) 我的wiki是一个可以多级分类的系统,每个分类里面都可以有多级的页面,上面的情况下page1是page2的父页面,page2是page3的父页面,所以/level1/level2/level3/page1.page2.page3指的是level1分类下面的level2子分类的level3子分类下面的page1页面的page2子页面的page3子页面,你可以直接输入url,http://xxx/pages/level1/level2/level3/page1.page2.page3存取这个页面 所以ByName是不够的,必须是一个全路径,而这个page2是可能移到page11下面的,所以这个全路径是不能够写在数据库里面的,必须是动态组装出来的。不然的话,一移动,所有下面的子节点就麻烦了,当然首先取page的时候就需要一个分类的名字和一个页面的名字,而这个分类的名字同样也是多级的,是不能写在数据库里面的。 |
|
返回顶楼 | |
发表时间:2004-10-12
引用 我的wiki是一个可以多级分类的系统,每个分类里面都可以有多级的页面,上面的情况下page1是page2的父页面,page2是page3的父页面,所以/level1/level2/level3/page1.page2.page3指的是level1分类下面的level2子分类的level3子分类下面的page1页面的page2子页面的page3子页面,你可以直接输入url,http://xxx/pages/level1/level2/level3/page1.page2.page3存取这个页面
对于这个查找page1.page2.page3 如果因为page名字可重复带来的查询问题,那么构造一个绝对的page名目录还是可以解决问题。比如: public class page{ private String name; public String getAbsoluteTreeName();{ StringBuffer buf=new StringBuffer();; buf.append(name);; Page parentP=this.getParentPage();; while(parentP!=null);{ buf.append( "."+parentP.getName(););; parentP=parentP.getParentPage();; } } } |
|
返回顶楼 | |
发表时间:2004-10-12
这个本来就是这样的,那是已经得到了这个page的时候。
但你去取一个页面的时候 getPage("/level1/level2/level3","page1.page2.page3") 是不是需要构造出一个动态查询语句?因为层次是不知道的,这个语句要几次自我join,效率非常低的,不用cache不足以平民愤,呵呵 |
|
返回顶楼 | |
发表时间:2004-10-12
potian 写道 这个本来就是这样的,那是已经得到了这个page的时候。
但你去取一个页面的时候 getPage("/level1/level2/level3","page1.page2.page3") 是不是需要构造出一个动态查询语句?因为层次是不知道的,这个语句要几次自我join,效率非常低的,不用cache不足以平民愤,呵呵 我还是不理解为什么一定要用cache! 比如: public Level getLevelByAbsolutePath(String abPath);{ List levels=this.findAllLevels();; for(Iterator it=list.Iterator();;it.hasNext();;);{ Level curL=it.next();; if(curL.getAbsolutePath.equals(abPath);); return curL; } } public Page getPageByAbsolutePath(String absoluteLevelPath,String abP);{ Level level=this.getLevelByAbsolutePath(absoluteLevelPath);; //...... the same logic above } } } |
|
返回顶楼 | |
发表时间:2004-10-12
如果我的分类有3层,每一层里面有n个子分类,我的页面有n层,每一个父页面里面有n个子页面,你想想看,多少个lazy collection要被你引用到?要做多少次数据库操作?要加载多少数据?恐怖!
哦,我看错了,你没有用递归,findALl,那你的比较次数太多了,要多少次比较?照样恐怖 |
|
返回顶楼 | |
发表时间:2004-10-12
potian 写道 如果我的分类有3层,每一层里面有n个子分类,我的页面有n层,每一个父页面里面有n个子页面,你想想看,多少个lazy collection要被你引用到?要做多少次数据库操作?要加载多少数据?恐怖!
赫赫,确实如此。很恐怖。性能杀手。 如果你的页面名字不允许更改的话,可以考虑用一个表将absolutepath与pageId对应起来。 |
|
返回顶楼 | |
发表时间:2004-10-12
改名字、移动目录层次等等都是大问题
这个就是cache的责任了 |
|
返回顶楼 | |
发表时间:2004-10-12
potian 写道 改名字、移动目录层次等等都是大问题
这个就是cache的责任了 如果硬是要将这个多级目录查询一个重要业务逻辑加以考虑,还是可以再重新设计一下增/该目录 增改页面的逻辑。 将这些更新与absolutepath pageId 对应表同步。 用cache,不知道您是怎么实现的? |
|
返回顶楼 | |
发表时间:2004-10-12
这个问题其实是个在很多系统里面出现的问题,至少我已经碰到过好几个了,例如你们整个银行的组织机构
cache实现很简单 getPage(absoluteCategoryKey,absolutepageKey) 的时候首先用categoryKey+absolutepageKey去取cache里面的id,如果找到,用这个id去取Page对象,比较一下它的absoluteCategoryKey和absolutepageKey是不是一样,如果一样的话,就表明没有过期,如果过期的话,就把从缓存去掉 如果过期或者没有找到,就直接构造一个动态查询语句把它查出来,用它的 absoluteCategoryKey和absolutepageKey放入id即可 |
|
返回顶楼 | |
发表时间:2004-10-12
相比我出的馊主意,好的多了。
不用改原有的大部分逻辑,直接增加一个cache的访问逻辑。 |
|
返回顶楼 | |