【Java EE 學習 72 下】【數據採集系統第四天】【移動/複製頁分析】【使用串行化技術實現深度複製】

1、移動、複製頁的邏輯實現

移動、複製頁的功能是在設計調查頁面的時候須要實現的功能。規則是若是在同一個調查中的話就是移動,若是是在不一樣調查中的就是複製。數據庫

不管是移動仍是複製,都須要注意一個問題,那就是頁面在一個調查中的位置問題,這就須要一個變量來標識該該頁面在一個調查中的位置。咱們在Page對象中添加一個成員變量orderNo,該變量是float類型的變量,默認值和pageId相同,在設置pageId的同時設置好orderNo,咱們使用該變量來對一個調查中的全部頁面進行排序。ide

移動、複製頁的流程就是:this

在設計調查頁面中的頁面上給出一個超連接:」移動、複製頁「->Action查找到全部的Survey並將全部Survey中的全部頁面顯示出來,用戶選擇在頁面以前仍是以後並提交->Action根據原頁面和目標頁面進行判斷是須要進行移動頁面仍是複製頁面,並調用相應的方法進行移動、複製頁->重定向到設計調查頁面上。spa

1.移動頁面的實現分析

移動頁面的實現相對來講要簡單不少。首先,移動頁面必定是在同一個調查中,因此咱們只須要將原頁面的orderNo進行相應的更改便可,更改以後重定向到設計調查頁面上查看更改是否生效。設計

2.複製頁面的實現分析

複製頁面相對移動頁面來講要複雜的多,首先複製頁面不是在同一個調查中,並且須要將原來的頁面進行拷貝,Page對象中有幾個成員變量,特別是questions成員變量更應該着重考慮。複製頁面很是容易被誤導成變量的引用複製,實際上不是這樣,所謂複製就是將原來的對象原本來本的拷貝一份,即便原來的對象不存在了,拷貝的那份對象也可以毫無影響的繼續運做。code

這裏藉助串行化技術實現對對象的深度複製。串行化使用到的技術主要是對象流和內存流。對象序列化以後寫入內存,讓後再從內存中取出來造成新的對象。這樣就完成了對對象的深度複製。實現深度複製的代碼以下:對象

 1 //實現深度複製的方法
 2     //在實現深度複製以前必須修改Bean類中的相關字段,
 3     //好比Page類中的pageId必須加上transient修飾,還有Question類中的questionId字段也必須加上transient修飾
 4     private Serializable copyPage(Page oldPage) {
 5         oldPage.getQuestions().size();
 6         try {
 7             ByteArrayOutputStream baos=new ByteArrayOutputStream();
 8             ObjectOutputStream oos=new ObjectOutputStream(baos);
 9             oos.writeObject(oldPage);
10             ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());
11             ObjectInputStream ois=new ObjectInputStream(bais);
12             Serializable serializable=(Serializable) ois.readObject();
13             return serializable;
14         } catch (IOException e) {
15             e.printStackTrace();
16         } catch (ClassNotFoundException e) {
17             e.printStackTrace();
18         }
19         return null;
20     }

實現深度複製須要注意幾點:blog

  (1).在進行深度複製以前,必須解決懶加載可能出現的異常。以上的代碼中,接收了一個Page對象,首先調用了該對象的getQuestions().size();這麼作是爲了防止出現懶加載異常的狀況。若是不這麼作的話會出現什麼狀況呢?在複製該對象以前,因爲Page對象的questions成員變量默認啓用了懶加載策略。因此並不會到數據庫中查詢Question對象填充questions成員變量。這樣一來深度複製以後的Page對象中的questions對象就沒有實際的值。一旦調用該成員變量就會出現懶加載異常。排序

  (2).深度複製以前必須修改Bean中的定義。將Page類中的pageId使用transient關鍵字修飾,一樣,也須要對Question類中的questionId使用transient關鍵字修飾。transient關鍵的做用就是在串行化對象的時候忽略該字段。這樣獲得的深度複製後的頁面對象中的相應字段就是null。好比Page對象,它的pageId爲NULL,同時該對象中的全部questions列表中的Question對象中的questionId也是NULL。由於須要從新保存到數據庫,若是不這麼作就會報錯,由於不管是Page對象仍是Question對象都是主鍵自動增加的。固然咱們可以手動設置pageId和questionId爲NULL,可是並無論用,緣由未明,因此直接使用transient關鍵字對其進行修飾是最最快最省事的方法。內存

3.orderNo的設置問題。

  我在這裏設置orderNo值越小,排名越靠前,反之排名越靠後。

  若是是須要放到第一頁的前面,則將目標也的orderNo的值設置爲比第一頁的orderNo小0.01,若是放置到最後一頁的後面,則設置目標頁的orderNo的值爲最後一頁的orderNo大0.01,其餘狀況下使用二者的平均值。 

  全部的orderNo的值都保留兩位小數點。

由於須要知道頁面中的最大頁碼和最小頁碼,因此在PageService中就須要提供兩個方法判斷獲取最大值和最小值的方法。

 1     @Override
 2     public boolean isLastPage(Page page) {
 3         String hql="from Page where survey.surveyId=? order by orderNo desc";
 4         List<Page>pages=this.pageDao.findEntitysByHQL(hql,page.getSurvey().getSurveyId());
 5         return pages.get(0).getPageId()==page.getPageId();
 6     }
 7     @Override
 8     public boolean isFirstPage(Page page) {
 9         String hql="from Page where survey.surveyId=? order by orderNo asc";
10         List<Page>pages=this.pageDao.findEntitysByHQL(hql,page.getSurvey().getSurveyId());
11         return pages.get(0).getPageId()==page.getPageId();
12     }

4.實現移動頁的代碼

 1 /**
 2      * 移動的規則就是:
 3      * 若是是最前面的頁面,則將頁面的orderNo設置爲第一個頁面的orderNo-0.01,
 4      * 若是是最後面的一個頁面,則將頁面的orderNo設置爲最後一個頁面的orderN+0.01,
 5      * 若是是中間的一個頁面,則使用兩邊orderNo的平均值
 6      * 
 7      * @param position
 8      * @param oldPage
 9      * @param newPage
10      */
11     private void doMovePage(String position, Page oldPage, Page newPage) {
12         //第一種狀況是position是0,表明是放到目標頁的前面
13         if("0".equals(position)){
14             //若是是放到目標頁的前面的話,須要考慮目標頁是否是第一頁的狀況
15             if(isFirstPage(newPage)){
16                 //是第一頁的話使用第一頁的orderNo-0.01
17                 oldPage.setOrderNo(newPage.getOrderNo()-0.01F);
18             }else{
19                 //不然的話取平均值
20                 oldPage.setOrderNo((this.getPrePage(newPage).getOrderNo()+newPage.getOrderNo())/2);
21             }
22         }else if("1".equals(position)){//第二種狀況是position是1,帶包是放到目標頁的後面
23             //若是是放到目標頁的後面,須要考慮目標頁是否是最後一頁的狀況
24             if(isLastPage(newPage)){
25                 oldPage.setOrderNo(newPage.getOrderNo()+0.01F);
26             }else{
27                 //不然的話取平均值
28                 oldPage.setOrderNo((this.getNextPage(newPage).getOrderNo()+newPage.getOrderNo())/2);
29             }
30         }
31         pageService.updatePage(oldPage);
32     }

5.實現複製頁的代碼:

 1 //不一樣頁面之間使用頁面複製,深度複製
 2     private void doCopyPage(String position, Page oldPage, Page newPage) {
 3         Page copyPage=(Page) this.copyPage(oldPage);
 4         //第一種狀況是position是0,表明是放到目標頁的前面
 5         if("0".equals(position)){
 6             //若是是放到目標頁的前面的話,須要考慮目標頁是否是第一頁的狀況
 7             if(isFirstPage(newPage)){
 8                 //是第一頁的話使用第一頁的orderNo-0.01
 9                 copyPage.setOrderNo(newPage.getOrderNo()-0.01F);
10             }else{
11                 //不然的話取平均值
12                 copyPage.setOrderNo((this.getPrePage(newPage).getOrderNo()+newPage.getOrderNo())/2);
13             }
14         }else if("1".equals(position)){//第二種狀況是position是1,帶包是放到目標頁的後面
15             //若是是放到目標頁的後面,須要考慮目標頁是否是最後一頁的狀況
16             if(isLastPage(newPage)){
17                 copyPage.setOrderNo(newPage.getOrderNo()+0.01F);
18             }else{
19                 //不然的話取平均值
20                 copyPage.setOrderNo((this.getNextPage(newPage).getOrderNo()+newPage.getOrderNo())/2);
21             }
22         }
23         float temp=copyPage.getOrderNo();
24         copyPage.setSurvey(newPage.getSurvey());
25         pageService.addNewPage(copyPage);
26         copyPage.setOrderNo(temp);
27         pageService.updatePage(copyPage);
28         for(Question question:copyPage.getQuestions()){
29             questionService.saveQuestion(question);
30         }
31     }
32     //實現深度複製的方法
33     //在實現深度複製以前必須修改Bean類中的相關字段,
34     //好比Page類中的pageId必須加上transient修飾,還有Question類中的questionId字段也必須加上transient修飾
35     private Serializable copyPage(Page oldPage) {
36         oldPage.getQuestions().size();
37         try {
38             ByteArrayOutputStream baos=new ByteArrayOutputStream();
39             ObjectOutputStream oos=new ObjectOutputStream(baos);
40             oos.writeObject(oldPage);
41             ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());
42             ObjectInputStream ois=new ObjectInputStream(bais);
43             Serializable serializable=(Serializable) ois.readObject();
44             return serializable;
45         } catch (IOException e) {
46             e.printStackTrace();
47         } catch (ClassNotFoundException e) {
48             e.printStackTrace();
49         }
50         return null;
51     }

以前曾經在Survey對象中添加了量個字段,minOrderno和maxOrderno,這兩個字段和如今的問題徹底沒有關係,可是在以後的參與調查中的導航功能有密切的關係。

2、移動頁的實現演示

在第一個調查中移動有四頁,並且頁面都按照順序進行了排序。如今想要將第一頁移動到第三頁和第四頁之間。

  首先,單擊第一頁旁邊的」移動、複製頁「超連接,跳轉到選擇位置的界面上去,該界面顯示了全部的調查中的全部的頁面。並且原頁面使用了重色標註出來了。

咱們單擊第三頁的」以後「單選按鈕,而後點擊以後的肯定,直接跳轉到設計調查頁面上去了,同時咱們發現,第一頁真的到了第三頁和第四頁之間,同時第一頁原來的位置被第二頁所取代。

其實想要實現這個效果有兩種方式能夠是西安,第一種是放到放到第三頁以後,第二種是放到第四頁以前,這裏選擇一種便可。

3、複製頁的實現演示

如今我一共建立了6個調查,其中第一個調查設計的最多,有四頁的問題。我給第二個調查添加幾個頁面並添加幾個問題以下圖所示:

如今我想將第一個調查中的標題爲「第一頁」的頁面複製到第二個調查中的第二頁和第三頁之間

步驟以下,單擊第一個調查的標題爲「第一頁」的頁面中的「複製、移動頁」超連接。

 

而後單擊肯定按鈕,發現跳轉到了調查二,同時原頁面已經被複制到了指定的位置。

相關文章
相關標籤/搜索