改写DAO层步骤

见开发社区的:issue 5:modify DAO tier

The DAO tier of "learndiary" is a bad design,difficult to understand,large

size,there are too many methods in a class,it affects the performance of our

program.It must be modified,although our entire system will be redesign in the

furture,but,for giving user a better experience of visiting our website,it

needs a quick fix.

为了改善网站的性能,减少内存占用,第一步是将LearnDiaryDB.java按对象和功能拆分开。

接下来...,再说。

parameter的使用

  在导航系统的编码中,在parameter的使用上走了一点弯路,记之以备忘。

  1、不用在request中检查参数是否存在,可以直接把参数值写入url,如果这个参数为null,那么它就以“null”字符串写入url,不会影响程序的正常使用。这可以偷点懒。但是,为了url短点,把无效的参数检测一下,在url中剔除它为最好。

String searchDiaryIDStr = request.getParameter("searchDiaryID");

firstPageStr =

" <a href=\""

+ url

+ ";jsessionid="

+ sessionID

+ "?searchDiaryID=" + searchDiaryIDStr + "&pageNum="

+ firstPage

+ "&naviStr="

+ naviStr

+ "\">首页</a>";

  2、同样,在*.jsp文件中也可以这样偷点懒,request中没有这个参数它会处理成空字符串,如:

  <html-el:link action="disDiaryContentAction.do?searchDiaryID=${param['searchDiaryID']}&goalID=${aArticleInfo.articleID}&naviStr=${requestScope['naviStr']}" target="diaDisDiary}">

  在这里,就用不着用<logic:present></logic:present>或<logic:notPresent></logic:notPresent>来检测“searchDiaryID”在request中是否存在。

基本完成导航系统的编码

  实现了我想像中的全部功能,还额外的实现了检索日记的目标内容及所在的目标的日记列表的上一条,下一条的导航功能(这个功能可费了我不少神,不知道到底它有没有用)。

  接下来,要实现导航参数如果缺失或者不正确的默认参数,还要实现目标内容和目标的日记列表的互相跳转链接。

分析学习日记横向导航及开几个窗口的思路

今天,已经把层次导航系统完成(如:所有目标>>我进行中的目标>>撰写目标"学习日记开发小组需求分析设计区(技术类:开发小组用)"的日记),下面将进行横向导航的设计(上一条,下一条)。这里把系统开几个窗口的问题与横向导航的设计结合起来设计。

我考虑了一下,凡是可以横向导航的地方都只开一个窗口,例如,现在我在查看一篇目标的内容,我

要查看另一篇目标的内容就不要再开一个窗口了。这样,也会横向导航的设计相一致了(横向导航的

上一条和下一条内容都在原窗口中打开)。

一、下面把横向导航的需要列个表:

1、在所有目标列表中:

  1)目标内容;

  2)目标的日记列表(上一条:在这里即上一目标的日记列表);

  3)日记列表中的日记内容;

2、在检索结果页面中:

  1)检索目标列表:

    1》目标内容;

    2》目标的日记列表;

    3》日记列表中的日记内容;  

  2)检索日记列表:

    1》日记内容;(检索日记列表中的日记所有目标内容和日记列表的横向导航均没有意义,

所以在这个页面上不需要横向导航,但是,它们的内容应该各自在一个窗口中打开)

    2》所在目标的日记列表中的日记内容; 

3、您的进行中的目标列表:

  1)目标内容;

  2)目标的全部日记列表;

  3)目标的我的日记列表;

  4)2)和3)中的日记列表中的日记;

二、横向导航的实现方法,得到条目列表的上一条和下一条的goalID,在当前的url中仅仅修改goalID

参数就行了,其它(包括naviStr)一切不变。但是,怎么样才能得到上一条和下一条的goalID呢? 

   1、在所有目标中,需要参数:所有目标的列表,排序方式,当前目标的ID(所在的位置);

  2、在您的进行中的目标列表中,需要参数:同1;

  3、在检索结果页面中,需要检索结果列表,排序方式,当前条目的ID;

上面所有的ID在url参数中均是goalID;

方法:

  LearndiaryDB.getNext(currentID,list)

                                                             2005年10月26日

  我想了一下,把全部记录的ID保存在list中传给程序处理不会增加额外的内存开销,因为在Java中,传递对象实际上传递指向对象的指针。但是要保证这个list能及时销毁。

  因为ID是整数,所以不能保存在list中,但可以保存在array中(在java中,传递array也是传递指针)。

这里,有以下几种处理的方法:

  1)从查询结果集中取出每个ID后,保存在array中,马上关闭数据库连接,减少数据库连接开销。然后在同个方法中取得前面、当前、后面记录的ID。只返回3个元素的array给Pager类处理,这样,可以保证每条数据都是最新的,但是要不停的开启和关闭数据库连接;

  2)把查询结果产生的array全部存在session中,Pager在session中取数据。这样,可以减少数据库的查询,但是存在两个问题,那个比较长的array在session中始终占用内存,还有,取出的数据的排序关系可能是过期的(这时,有人往数据库中增加或修改了数据)。

  我不知道哪种方法可以减轻对网站的压力,决定采用第一种方法。

  另外,在结果集中查询邻近的ID会出现几种结果呢?

  1)在用户查看帖子期间,这篇帖子被删除了,结果返回:{-1,-1,-1};

  2)只有一篇符合要求的帖子,结果返回:{-1,当前帖子ID,-1};

  3)当前帖子是第一篇帖子,结果返回:{-1,当前帖子ID,下一条帖子ID};

  4)当前帖子是最后一篇帖子,结果返回:{上一篇帖子ID,当前帖子ID,-1};

  5)当前帖子前后都有帖子,结果返回:{上一篇帖子ID,当前帖子ID,上一篇帖子ID};

  写if语句时把最有可能的情况放在前面,于是为:

  if 5 {

    }else if 4{

    }else if 3{

    }else if 2{

    }else{

    }

  在朋友数据缓存思想的灵感下,除了上面只取出邻近帖子ID的方法,我也想出了第三种处理方法:一次取出三条帖子的内容,并把这三条帖子统统存在Session中,这样,可以减少数据库连接的次数,但会稍微增加内存的开销,假设一条帖子平均1KB,增加两条帖子的内存增加2KB,10个用户才增加20KB,看来,这种方法也可以试一下吧。但是,一般的用户可能大多数时候还是从上到下的看帖子,也可以只取出当前这条帖子和下一条帖子的内容。

  今天,我先把这个思路记在这里,暂不实现这个方法。先把整个导航系统运行起来。以后,系统优化的时候再统一考虑各种优化问题。否则,局部的优化也许会损害全局的性能也是有可能的吧?    

                                                                 2005年10月27日

昨天,已经把在查看所有目标页面中的查看目标和日记的横向导航完成了。但是,在其它地方的横向导航需要根据导航封装客串得到它是来源于哪

里的,然后再根据这个得到Where clause 和 order by参数。下面对各种情况列一表:

类型  所在页面  导航特征字符串  where                                                                      order

目标  所有目标  a10a3\\d+                  typeID=1(IndexAtion,article表)                                        sortGoalType(1)

目标  进行中的  a10a60a3\\d+           userID=? state=?(ProcessGoalAction,usergoal表)     sortMyProcessGoalType(2)

目标  退出的  a10a70a3\\d+           userID=? state=?(QuitedGoalAction,usergoal表)        sortMyQuitGoalType(3)

目标  完成的  a10a80a3\\d+           userID=? state=?(FinishedGoalAction,usergoal表)    sortMyFinishGoalType(4)

目标  检索的  a10ac0ae0a3\\d+ condition参数在Session中(PostSearchAction,article表) sortSearchGoalType(5)

日记  所有目标    a10a2\\w+                  typeID=2 AND parentID=?(DiaryAction,article表)    sortDiaryType(6)

日记 进行全部日记 a10a60a2\\w+(与所有目标中的日记一样)(退出a10a70a2\\w+)(完成:a10a80a2\\w+)(7)

日记 进行我的日记 a10a60a0\\w+   typeID=2 parentID=? userID=?(MyDiaryAction,article表) sortMyDiaryType(退出a10a70a0\\w+)a80a0\\w+(8)

在退出和完成目标的日记与在进行中目标的日记同样(即退出、完成的全部和我的日记)

日记 检索中的日记 a10ac0ad0a3\\d+  condition参数在Session中(PostSearchAction,article表) sortSearchDiaryType

日记列表 检索  a10ac0ae0a2\\d+  condition参数在Session中(PostSearchAction,article表) sortSearchGoalType(与检索目标内容一样)

日记列表 所有目标 a10a2\\d+               typeID=1(IndexAtion,article表)                                        sortGoalType(与1同)

以下是对应于目标的三种状态:只是把a3变成了a2和a0

日记列表 进行中的 a10a60a2\\d+           userID=? state=?(ProcessGoalAction,usergoal表)     sortMyProcessGoalType

日记列表 退出的  a10a70a2\\d+           userID=? state=?(QuitedGoalAction,usergoal表)        sortMyQuitGoalType

日记列表 完成的  a10a80a2\\d+           userID=? state=?(FinishedGoalAction,usergoal表)    sortMyFinishGoalType

日记列表 进行中的我 a10a60a0\\d+        userID=? state=?(ProcessGoalAction,usergoal表)     sortMyProcessGoalType

日记列表 退出的我  a10a70a0\\d+        userID=? state=?(QuitedGoalAction,usergoal表)        sortMyQuitGoalType

日记列表 完成的我  a10a80a0\\d+        userID=? state=?(FinishedGoalAction,usergoal表)    sortMyFinishGoalType

另外,检索日记中的日记所在目标和日记所在目标的日记列表暂不实现。

花了一晚上来做这个表,这么的罗列总结,是否有悖于计算机的自动化?是否设计思路有问题?我再想想。

                                     10月29日

    (待续)

实现了检索功能的导航模块

  继前两天实现了菜单中:“所有目标  您的目标  添加新目标  公告牌”的导航功能。昨天实现了“检索”功能的导航。并且,提交到了cvs库中。至此,前些天思路中的需要列表已经全部实现。但是,还有一些模块的导航是必须的。然后,需要实现“上一条”、“下一条”形式的横向导航。 

  在导航功能上实现完成后,需要修正一些细节问题,然后把代码进行优化。

cvs库第二次提交:实现户查看所有目标及其日

  实现了导航需要列表中的:1:1)~5)导航需求。

  1、用户查看所有目标及其日记的导航:含有下列路径:

    1)所有目标列表->相关日记列表;(目标ID)

    2)所有目标列表->相关日记列表->显示日记内容;(日记ID)

    3)所有目标列表->相关日记列表->编辑日记内容;(日记ID)

    4)所有目标列表->相关日记列表->显示日记内容->撰写评论;

    5)所有目标列表->相关日记列表->显示日记内容->编辑评论;(评论ID)

  下面继续实现余下的路径。因为已经开好了头,应该不太难,但也可能会有一些拦路虎意外的出现。不过,That's a piece.

  昨天晚上,一个在url中重写sessionID的小问题把我的时间浪费了不少,在jsp中,重写sessionID的格式是如下:

  /indexAction.do;jsessionid=aCxWdbpTejYe?pageNum=2

  我忘了加上"pageNum"前的"?",结果总是"NullOpiontException",把我搞得焦头烂额。为什么这个jsessionid不像其它参数那样(如:/toWriteDiaryAction.do?typeID=2&goalID=485)在action.do的问号后面呢?我搞不懂。