移动、复制页的功能是在设计调查页面的时候须要实现的功能。规则是若是在同一个调查中的话就是移动,若是是在不一样调查中的就是复制。数据库
不管是移动仍是复制,都须要注意一个问题,那就是页面在一个调查中的位置问题,这就须要一个变量来标识该该页面在一个调查中的位置。咱们在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个调查,其中第一个调查设计的最多,有四页的问题。我给第二个调查添加几个页面并添加几个问题以下图所示:
如今我想将第一个调查中的标题为“第一页”的页面复制到第二个调查中的第二页和第三页之间
步骤以下,单击第一个调查的标题为“第一页”的页面中的“复制、移动页”超连接。
而后单击肯定按钮,发现跳转到了调查二,同时原页面已经被复制到了指定的位置。