移動、複製頁的功能是在設計調查頁面的時候須要實現的功能。規則是若是在同一個調查中的話就是移動,若是是在不一樣調查中的就是複製。數據庫
不管是移動仍是複製,都須要注意一個問題,那就是頁面在一個調查中的位置問題,這就須要一個變量來標識該該頁面在一個調查中的位置。咱們在Page對象中添加一個成員變量orderNo,該變量是float類型的變量,默認值和pageId相同,在設置pageId的同時設置好orderNo,咱們使用該變量來對一個調查中的全部頁面進行排序。ide
移動、複製頁的流程就是:this
在設計調查頁面中的頁面上給出一個超連接:」移動、複製頁「->Action查找到全部的Survey並將全部Survey中的全部頁面顯示出來,用戶選擇在頁面以前仍是以後並提交->Action根據原頁面和目標頁面進行判斷是須要進行移動頁面仍是複製頁面,並調用相應的方法進行移動、複製頁->重定向到設計調查頁面上。spa
移動頁面的實現相對來講要簡單不少。首先,移動頁面必定是在同一個調查中,因此咱們只須要將原頁面的orderNo進行相應的更改便可,更改以後重定向到設計調查頁面上查看更改是否生效。設計
複製頁面相對移動頁面來講要複雜的多,首先複製頁面不是在同一個調查中,並且須要將原來的頁面進行拷貝,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關鍵字對其進行修飾是最最快最省事的方法。內存
我在這裏設置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 }
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 }
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,這兩個字段和如今的問題徹底沒有關係,可是在以後的參與調查中的導航功能有密切的關係。
在第一個調查中移動有四頁,並且頁面都按照順序進行了排序。如今想要將第一頁移動到第三頁和第四頁之間。
首先,單擊第一頁旁邊的」移動、複製頁「超連接,跳轉到選擇位置的界面上去,該界面顯示了全部的調查中的全部的頁面。並且原頁面使用了重色標註出來了。
咱們單擊第三頁的」以後「單選按鈕,而後點擊以後的肯定,直接跳轉到設計調查頁面上去了,同時咱們發現,第一頁真的到了第三頁和第四頁之間,同時第一頁原來的位置被第二頁所取代。
其實想要實現這個效果有兩種方式能夠是西安,第一種是放到放到第三頁以後,第二種是放到第四頁以前,這裏選擇一種便可。
如今我一共建立了6個調查,其中第一個調查設計的最多,有四頁的問題。我給第二個調查添加幾個頁面並添加幾個問題以下圖所示:
如今我想將第一個調查中的標題爲「第一頁」的頁面複製到第二個調查中的第二頁和第三頁之間
步驟以下,單擊第一個調查的標題爲「第一頁」的頁面中的「複製、移動頁」超連接。
而後單擊肯定按鈕,發現跳轉到了調查二,同時原頁面已經被複制到了指定的位置。