Extjs 學習筆記1

學習筆記javascript

 

 

 

 

 

目   錄前端

 

1 ExtJs 4java

1.1 常見錯誤處理 4面試

1.1.1 多個js文件中有相同的控件,切換時沒法正常顯示 4ajax

1.1.2 Store的使用方法 4數據庫

1.1.3 gridPanel單元格添加按鈕或連接,響應函數 4編程

1.1.4 對界面中控件進行處理的方法 8json

1.1.5 Ajax異步請求處理的方法 8後端

1.1.6 Store的load()與add()方法的區別 10數組

1.1.7 控件操做規則 11

1.1.8 Msg消息框事件處理 11

1.1.9 Gridpanel所列的數據記錄集獲取 12

1.1.10 ColumnModel()的應用 12

1.1.11 PagingToolbar控件的翻頁處理 13

1.1.12 ExtJs中打開新的網頁 14

1.1.13 動態更新TextField的fieldLabel 15

1.1.14 IE瀏覽器顯示界面出錯 16

1.1.15 向後臺發送請求時出錯 17

1.1.16 建立gridpanel時的錯誤 18

1.1.17 查詢結果以excel形式輸出 19

2 Hibernate 21

2.1 多表查詢 21

2.1.1 查詢語句 21

2.1.2 獲取多表join返回的多個對象 21

2.1.3 動態生成grid表格頭部 22

2.1.4 對加載成功的store數據處理 22

2.1.5 事務處理 24

2.1.5.1 中文亂碼問題?? 25

2.2 常見錯誤處理 26

2.2.1 Transcation not successful started 26

2.2.2 對於Hibernate中的對象轉爲json,最終轉爲string返回客戶端 26

2.2.2.1 對於返回單個對象的處理方法: 26

2.2.2.2 對於對象集合的處理方法 27

2.2.2.3 會話對象的應用 27

2.2.2.4 建立並保存包含其它外鍵關聯對象 28

2.2.2.5 排序的通用實現方法 29

2.2.2.6 獲取上傳文件的方法 30

2.2.2.7 sessionFactory類沒法建立時排錯方法 31

2.2.2.8 上傳文件的處理方法 32

2.2.2.9 Java類自定義的數據類型使用方法 38

 

 

 

 

 

 

 

 

 

 

 

1 ExtJs

1.1 常見錯誤處理

1.1.1 多個js文件中有相同的控件,切換時沒法正常顯示

檢查一下這些控件的屬性id是否相同,最好分配一個全局的id。

 

1.1.2 Store的使用方法

//指定批次的職位類型記錄store  

PMS.OffcialExam.StatisticsReport.score.positionTypeStore = new Ext.data.JsonStore({

url:'./PositionInfo',

baseParams: {action:'getPositionAndType',data:'{batchId:0}'},

root : 'data',

totalProperty : 'count',            

successProperty : 'success',

fields : PMS.OffcialExam.StatisticsReport.score.positionAndTypeRecord,

listeners:{

 'beforeload':function(){

      msgTip = Ext.MessageBox.show({

               title:'提示',

                  width : 250,

                  msg:'報表統計信息刷新中,請稍後......'

      });

             }

    }

});

其中PMS.OffcialExam.StatisticsReport.score.positionAndTypeRecord是程序中定義的store記錄結構對象

1.1.3 gridPanel單元格添加按鈕或連接,響應函數

function showUrl(_values) 

{

return "<button title='' value='' class=''>增長</button>"+"   "+"<a href='#' onclick=''>修改</a>"+"   "+"<a href='#' onclick=''>刪除</a>";

}

 

改成按鈕時的代碼

// return "<button title='' value='' class=''>生成</button>"+"   "+"<button title='' value='' class=''>分配准考證</button>";

 

不論renderer中生成的是連接,仍是其餘的內容好比button,都是通用的,代碼以下

首先給grid添加一個cellclick事件的響應函數

grid.on('cellclick', grid.onCellClick, grid);

響應函數中作以下處理

    onCellClick: function (grid, rowIndex, columnIndex, e) {
        if (e.getTarget().innerHTML === '查看') { //藉助事件的target來判斷,這裏是連接能夠這樣判斷,其餘方式亦可
            var record = grid.getStore().getAt(rowIndex);  // Get the Record
            var fieldName = grid.getColumnModel().getDataIndex(columnIndex); // Get field name
            var data = record.get(fieldName);//這個data就是點擊的單元格的數據了,必定有用的
            
            if (fieldName == 'this_column') {
                //若是是這一列,作這個事
            }
            
            if (fieldName === 'that_column') {
                //若是是另一列,作另外的事
            }
        }
    }


這個方法,不只能夠處理連接,簡化一下就是處理某個單元格點擊,onCellClick的做用域仍是grid,這個是重點,onCellClick仍是在grid這個組件以內,而沒有產生全局調用,另外點擊onclick的響應函數,只能接收字面參數,想傳遞一個對象是不可能的,若是應用上述方法,便可解決

 

代碼例子:

 

//渲染器  (生成,分配准考證)

function opeatorRender() 

{

return "<button title='' value='' class=''>生成</button>"+"   "+"<button title='' value='' class=''>分配准考證</button>";

};

 

PMS.OffcialExam.ExamSiteManage.assignExamRoom.siteAssign_cm = new Ext.grid.ColumnModel([msm,

          {header: '考區號', dataIndex:'examAreaCode'},

          {header: '考區名稱', dataIndex:'examAreaName'},

          {header: '考點號', dataIndex: 'examSiteCode'},

          {header: '考點名稱', dataIndex: 'examSiteName'},

          {header: '考點地址', dataIndex: 'examSiteAddress'},

          {header: '考場數量', dataIndex: 'examRoomAmount'},

          {header: '使用考場數', dataIndex: 'applyExamRoomNumber'},

          {header: '每考場人數', dataIndex: 'actualPersonNumber'},

          {header: '是否分配准考證', dataIndex: 'isMakeRegisteration'},

  {header:'操做',dataIndex:'work',sortable:true,renderer:opeatorRender}            

 

]);

 

 

PMS.OffcialExam.ExamSiteManage.assignExamRoom.siteAssign_store = new Ext.data.JsonStore({

url : './ExamRoomAssignInfo',

baseParams: {action:'getExamSiteAssignData'},

root : 'data',

totalProperty : 'count',

successProperty :  'success',

fields : PMS.OffcialExam.ExamSiteManage.assignExamRoom.assignListRecord

        /*[{name : 'examSiteInfo_Id'},       

          {name : 'examAreaCode'},

          {name : 'examAreaName'},

  {name : 'examSiteCode'},

          {name : 'examSiteName'},

          {name : 'examSiteAddress'},

          {name : 'examRoomAmount'},

          {name : 'applyExamRoomNumber'},

          {name : 'actualPersonNumber'},

          {name : 'isMakeRegisteration'}

          ]*/

 

}); 

PMS.OffcialExam.ExamSiteManage.assignExamRoom.siteAssign_store.load();

 

PMS.OffcialExam.ExamSiteManage.assignExamRoom.examDistributeList = new Ext.grid.GridPanel({

title     : '考場分配列表',

border    : false,

hidden    : true,

autoScroll: true,

viewConfig: {

forceFit: true

},

height  : 150,

store   : PMS.OffcialExam.ExamSiteManage.assignExamRoom.siteAssign_store,

cm      : PMS.OffcialExam.ExamSiteManage.assignExamRoom.siteAssign_cm,

sm: msm,

loadMask: {

  msg : '加載中....'

},

bbar: new Ext.PagingToolbar({

pageSize   : 10,

store      : PMS.OffcialExam.ExamSiteManage.assignExamRoom.siteAssign_store,

displayInfo: true,

displayMsg : '顯示{0}-{1}條,共{2}',

emptyMsg   : '沒有記錄',

items:['-',{

text   : '刪除所選',

iconCls: 'delete'

},'-',{

text: '分配准考證號',

handler: function() {

for(var i = 0; i < PMS.OffcialExam.ExamSiteManage.assignExamRoom.mainPanel.items.length; i++){

PMS.OffcialExam.ExamSiteManage.assignExamRoom.mainPanel.items.items[i].hide();

}

//顯示後從新佈局一次

PMS.OffcialExam.ExamSiteManage.assignExamRoom.queryDefine.show().collapse();

 PMS.OffcialExam.ExamSiteManage.assignExamRoom.admissionCardInfo.show();

}

}]

}),

listeners:{

'cellclick':function(grid, rowIndex, columnIndex, e){       //單擊含生成,分配准考證操做的單元格響應函數

if (e.getTarget().innerHTML === '生成') {               //根據事件的target判斷是哪一種操做

             var record = grid.getStore().getAt(rowIndex);       // 得到所選記錄

             var fieldName = grid.getColumnModel().getDataIndex(columnIndex); // Get field name

             var data = record.get(fieldName);//這個data就是點擊的單元格的數據了,必定有用的

            

var roomrecords = PMS.OffcialExam.ExamSiteManage.assignExamRoom.examDetailGrid.getStore().getRange();

for(var j = 0;j<roomrecords.length;j++){     

PMS.OffcialExam.ExamSiteManage.assignExamRoom.doSave(roomrecords[j]);

}

 

 

                alert("cellclick result"+fieldName);

 

            }

            if(e.getTarget().innerHTML === '分配准考證'){

var fieldName = grid.getColumnModel().getDataIndex(columnIndex); // Get field name

alert("cellclick add result"+fieldName);

}

 

}

 

}

});

1.1.4 對界面中控件進行處理的方法

例子:將生成按鈕置爲不可用

(按鈕idPMS.OffcialExam.ExamSiteManage.assignExamRoom.genButton)

 Ext.getCmp('PMS.OffcialExam.ExamSiteManage.assignExamRoom.genButton').disable();

1.1.5 Ajax異步請求處理的方法

發送請求,以及數據,同時要求返回對象(集合):

var para = {};

para.data = "{tTExamSiteInfo_id:" + grid.getStore().getAt(rowindex).get('examSiteInfo_Id') + "}"; 

para.action = 'getExamSiteDetailData';

PMS.OffcialExam.ExamSiteManage.assignExamRoom.examDetailList_store.load({params:para,

callback:function(records, options, success){

if(success){

PMS.OffcialExam.ExamSiteManage.assignExamRoom.examDetailGrid.show();

 

}

},

scrop:store

});

發送請求,以及數據,但只要求返回處理結果,如插入,修改或刪除記錄處理:

function(abatchid,areaid,siteid){

    var para = {};

para.data = "{tTExamBatch_id:" + abatchid + ",tTExamAreaCode_id:" + areaid + ",tTExamSiteInfo_id:" + siteid+ "}";

para.action = "getRegisterationNumber";

 

Ext.Ajax.request({

url:'./ExamRoomAssignInfo',

params:para,

success:function(response,config){

var result = Ext.decode(response.responseText);

if(!result.success){

Ext.Msg.show({

title:'提示',

msg:'准考證分配失敗',

modal:true,

icon:Ext.Msg.ERROR,

buttons:Ext.Msg.OK

});

}else{

Ext.Msg.show({

title:'提示',

msg:'准考證分配成功',

modal:true,

icon:Ext.Msg.INFO,

buttons:Ext.Msg.OK

});

//在此後可再加發新請求

 

 

}

},

failure:function(){

Ext.Msg.show({

title:'錯誤',

msg:'鏈接服務器出錯',

modal:true,

icon:Ext.Msg.ERROR,

buttons:Ext.Msg.OK

});

}

});

 

 

};

1.1.6 Storeload()add()方法的區別

定義好store結構後,可經過定義url, baseParams,然後利用load()直接裝載store中的數據記錄;若是使用add()方法,須要首先定義record結構,並建立record記錄對象(空對象),而對該對象的各屬性賦值,然後調用add(record)方可。

使用add()方法的例子:

var localrecords = [];

var siteRecord = new PMS.OffcialExam.ExamSiteManage.assignExamRoom.examSiteRecord({

 id:'',

 tTExamBatch_id:'',

 tTExamSiteInfo_id:'',

     examSiteCode:'',

 examSiteName:''                                                                    

                                                                              

        });

siteRecord.set('id',records[0].get('id'));

siteRecord.set('tTExamBatch_id',records[0].get('tTExamBatch_id'));

siteRecord.set('tTExamSiteInfo_id',records[0].get('tTExamSiteInfo_id'));

siteRecord.set('examSiteCode',records[0].get('examSiteCode'));

siteRecord.set('examSiteName',records[0].get('examSiteName'));

localrecords[0] = siteRecord;

PMS.OffcialExam.ExamSiteManage.assignExamRoom.examSiteInfoStore.add(localrecords);

1.1.7 控件操做規則

對於容器(gridpanel)中的控件(button未單獨定義,textfield單獨定義)操做時,若該控件未單獨定義,則須要經過Ext.getCmp(‘控件id’)進行,例如,設置id爲assignButton某個button爲不可用:

Ext.getCmp('assignButton').disable();

反之,則可直接操做,如:

examSiteDetail_areaNameField = new Ext.form.TextField({

anchor:'90%',

fieldLabel : '考區名稱'

});

讀取其中的值:examSiteDetail_areaNameField.getValue();

1.1.8 Msg消息框事件處理

Ext.Msg.show({

     title:'提示',

     msg:result.message,

     icon:Ext.Msg.INFO,

     buttons:Ext.Msg.OK,

     fn:function(btn){

                          //單擊「肯定」按鈕後,要處理的代碼

}

});

1.1.9 Gridpanel所列的數據記錄集獲取

在編程中,有時須要在容器(gridpanel)對象以外對其中的數據進行處理,能夠經過容器(gridpanel)對象中的store對象直接讀取其中的記錄或具體字段。例如,下面例子是從某個gridpanel對象的store對象(PMS.OffcialExam.ScoreManage.scoreImport.store)讀取記錄或字段:

//獲取成績處理信息列表中指定職位的全部記錄我的id   

   PMS.OffcialExam.ScoreManage.scoreImport.getSelectedPersonId = function()

   {

var selectedRecordId = "";

var datas= PMS.OffcialExam.ScoreManage.scoreImport.store.data;

//將所選的記錄ID組合成以「=」分隔的字符串

for(var i = 0;i < datas.length;i++){

selectedRecordId += (String)(datas.items[i].data.pId) ; 

if(i < datas.length-1){

selectedRecordId += "=";

}

}

return selectedRecordId;

};

1.1.10  ColumnModel()的應用

控件gridpanel的表格列(字段)定義方式有兩種,一種直接定義列模式對象中,另外一種則是先定義記錄類型,再將該記錄類型賦於列模式對象。

1. 直接定義方式

PMS.OffcialExam.ScoreManage.generationInterviewList_cm =

     new Ext.grid.ColumnModel([

PMS.OffcialExam.DataInitalize.examSubject.sm,

    {header:'id',dataIndex:'id',sortable:true,align:'center',hidden:true},

    {header : '科目類別',align:'center',sortable:true,dataIndex : 'subjectType',renderer:function(value){ if (value == '1') {return "公共科目";} else {return "專業科目"; } }},

     {header : '科目代碼',align:'center',sortable:true, dataIndex : 'subjectCode'},

      {header : '科目名稱', align:'center',sortable:true,dataIndex : 'subjectName'},

      {header : '考試時間(分鐘)', align:'center',sortable:true,dataIndex : 'examTimeLength'},

  {header : '備註', align:'center',sortable:true,dataIndex : 'content'}

1.1.11 PagingToolbar控件的翻頁處理

控件PagingToolbar的下一頁按鈕被單擊時,將調用方法doLoad()加載下一頁的數據,具體用法:

1.定義gridpanel控件

generationInterviewList.listing = new Ext.grid.GridPanel({

title : String.format(PMS.constant.panelTitle,'面試人員列表'),

height:190,

collapsible : true,

titleCollapse: true,

buttonAlign : 'center',

store : generationInterviewList.store,

cm : generationInterviewList_cm,

sm : generationInterviewList.sm,

bbar : generationInterviewList.bbar,

viewConfig : {

forceFit : true     //自動填充

},

getPageData: function(bbar){     //重寫getPageData方法,獲取分頁工具條活動頁的頁號等數據

 var total = bbar.store.getTotalCount();

 return {

   total: total,

   activePage: total != 0 && bbar.cursor == 0 ? 1 : Math.ceil(bbar.cursor / bbar.pageSize),

   pages: total !=0 && total < bbar.pageSize ? 1 : Math.ceil(total / bbar.pageSize)

        };

}

 

2.定義PagingToolbar控件

GenerationInterviewList.bbar = new Ext.PagingToolbar({

displayMsg : '顯示{0} - {1}條,共{2}',

  emptyMsg : '沒有記錄',

  pageSize : 5,//一頁顯示5

  store : generationInterviewList.store,

  displayInfo : true,

  listeners : {

         'change' : function(bbar, pageData){

         if(pageData.activePage>1){

          var grid = bbar.ownerCt;  

                 var store = grid.getStore();

                 grid.getSelectionModel().selectFirstRow();

                 var start = pageData.activePage;                   

      }

      }

     },

3.在程序須要的地方調用getPageData方法,獲取當前頁對象,便可人工觸發下一頁事件

//調用gridpanel中的getPageData獲取包含當前活動頁頁號等屬性的對象

var d = generationInterviewList.listing.getPageData(generationInterviewList.bbar);

//分頁工具條向後翻頁,加載下一頁的數據 generationInterviewList.bbar.doLoad(Math.min(d.pages, d.activePage + 1));

1.1.12 ExtJs中打開新的網頁

在前端界面中打開新的網頁,具體用法:

//ExtJs界面的事件處理中調用打開新網頁

listeners: {

'click' : function() {

var username = 'admin';

var password = 'pass';

openPostWindow("/yjExamB/ExamSituationInfo?action=loginCheck", username, password);

}

//打開新頁面的方法

function openPostWindow(url, username, password)//, name)    

var str_form_head = '<form name="tempForm" action="' + url + '" method="post" style="display:none">';

var str_form_foot = '</form>';

var str_form_f1 = '<input type="hidden" name="username" value=' + username + ' />';

var str_form_f2 = '<input type="hidden" name="password" value=' + password + ' />';

var str_javascript_execute = '<script type="text/javascript">document.tempForm.submit();</script>';

 

var arr_data = new Array();

arr_data.push('<h3>Please wait ...</h3>');

arr_data.push(str_form_head);

arr_data.push(str_form_f1);

arr_data.push(str_form_f2);

arr_data.push(str_form_foot);

arr_data.push(str_javascript_execute);

var oWin = window.open('');

oWin.document.write(arr_data.join(''));

return oWin;

 

1.1.13 動態更新TextField的fieldLabel

動態更改TextField的fieldLabel方法時,因ExtJs自己未提供這個方法,可用Firebug來查看ExtJs的TextField在運行時被解析成什麼樣的HTML標籤,而後用Dom操做來修改它的標題。 例如:

var textField = new Ext.form.TextField({
        fieldLabel: "輸入框標題",
        id: "textfieldId"
    }); 

上面的一個TextField在運行時被解析成的HTML爲: 

<div tabindex="-1" class="x-form-item " id="ext-gen117"> 

<label class="x-form-item-label" for="textfieldId" id="ext-gen118">輸入框標題:</label> 

<div style="padding-left: 105px;" id="x-form-el-netprice1" class="x-form-element"> 

<input type="text" name="textfieldId" id="textfieldId" autocomplete="off" class=" x-form-text x-form-field x-form-num-field"  title=""> 

</div> 

<div class="x-form-clear-left"></div> 

</div> 

從上面的HTML能夠看出,輸入框(text)和它的標題(label)的Dom關係是:label是text的叔叔 ,因此,咱們可使用以下代碼來更改它的標題: 

document.getElementById("textfieldId").parentNode.previousSibling.innerHTML ="輸入框標題改變了:";                                                 (1

其中previousSibling屬性:可返回某節點以前緊跟的節點(處於同一樹層級)

ExtJs中每一個控件自己也能夠獲取其DOM對象,語句(1)也可寫爲:

Ext.getCmp("textfieldId").el.dom.parentNode.previousSibling.innerHTML ="輸入框標題改變了:";

1.1.14  IE瀏覽器顯示界面出錯

瀏覽器顯示出錯,如圖:

 

問題:在items:[]定義中對象定義的個數與所描述的不對應,即items[a,b,]表示有三個控件項,但實際只定義了二個,將會在IE八、9等瀏覽器運行時,報出如上圖錯誤

1.1.15  向後臺發送請求時出錯

 

 

問題:發送請求時的參數對象未正確設置,如:

//報考職位代碼store

PEXAM.ExamSiteManage.assignExamRoom.positionStore = new Ext.data.JsonStore({

proxy: new Ext.data.HttpProxy({url:'./PositionInfo'}), 

baseParams: {action: 'getPositionCodeByBatch'},

idProperty: 'id',

    root : 'data',

totalProperty : 'count',            //getCount();     totalCount   getTotalCount()

successProperty : 'success',

fields : PEXAM.ExamSiteManage.assignExamRoom.positionRecord

});

 

//報考職位數據加載

var para = {};

var data1 = {};

data1.abatchid = PEXAM.Common.currentBatch.abid;

para.data = Ext.encode(data1);

PEXAM.ExamSiteManage.assignExamRoom.positionStore.removeAll();

PEXAM.ExamSiteManage.assignExamRoom.positionLocalStore.removeAll();

PEXAM.ExamSiteManage.assignExamRoom.positionStore.load({params : para,

 callback: function(records,options,success){

 if(success)

 if(records.length>0)

 PEXAM.ExamSiteManage.assignExamRoom.positionLocalStore.add(records);

 }

});

若紅色字體部分的參數未加入,或是未定義para都會出現上述錯誤

1.1.16 建立gridpanel時的錯誤

若建立gridpanel使用的自動擴展列,

this.gridRoomList = {

     xtype            : 'grid',

     id               : 'selectSite_roomlist_grid',

     flex             : 1,

         //height           : this.parent.center.getInnerHeight()-80,

     columns          : this.columnModelRoomList,

     store            : this.storeRoomList,

     bbar             : this.pagingToolbarRoomList,

     loadMask         : true,

     stripeRows       : true,

     autoExpandColumn : 'roomlist_1_col',   //自動擴展列

         ancestor         : this,

     listeners        : {

             rowdblclick    : function(grid, rowIndex) {

              var record = grid.getStore().getAt(rowIndex);

              if (!record){

              }

             },

             rowcontextmenu : Ext.emptyFn

     }

     };

若未能同時在columnmodel中定義這個列,則會出現如下錯誤提示:

this.config[a] is undefined
this.mainBody is undefined

解決辦法:
給autoExpandColumn對應的屬性在ColumnModel中的定義加個id屬性,以下:
{id:’name’,header: 「name」,width: 75, sortable: true, dataIndex: ‘name’},

應該是該列沒有定義或者Id錯誤

1.1.17 查詢結果以excel形式輸出

若要求查詢後直接生成一個excel表,在前端可用腳本生成表單,用隱藏字段傳送參數,用代碼方式提交表單到後臺,前端實現代碼以下:

this.pagingToolbarStatisticSignup = {

             xtype       : 'paging',

             id          : 'statistic_signup_pagingbar',

             ancestor    : this, 

             store       : this.storeStatisticSignup,

             pageSize    : 2000000,

             displayInfo : true,

             items: [

                 {

                     text: '導出到Excel文件',

                 iconCls:'button_icon_add',

                     ancestor: this,

                     handler: function(btn, e){

               var params = {};

               var combo_value = Ext.getCmp('statistic_signup_exambatch_combo').getValue();

               var fields = this.ancestor.selectedFields;

               if (!combo_value) {

               Ext.Msg.alert('操做錯誤', '請首先選擇統計批次.');

               return;

               }

               if(fields==''){

               Ext.Msg.alert('操做錯誤', '請選擇統計選項.');

               return;

               }

               //腳本生成表單

               params.param1 = combo_value;

               params.param2 = fields;

               params.param3 = "excel";     //淡出到EXCEL

                             

              var frm = document.createElement("form");

              frm.action = 'Statistic';

              frm.method = 'post';

             

              var action = document.createElement("input");

              action.setAttribute('name', 'action');

              action.setAttribute('type', 'hidden');

              action.setAttribute('value', 'signup');

              frm.appendChild(action);

             

              var data = document.createElement("input");

              data.setAttribute('name', 'data');

              data.setAttribute('type', 'hidden');

              data.setAttribute('value', Ext.util.JSON.encode(params));

              frm.appendChild(data);

             

              document.body.appendChild(frm);

             

              frm.submit();

             

              document.body.removeChild(frm);

                     }

                 }

             ]

        };

 

 

參考網站:

http://www.myext.cn

 

 

2 Hibernate

2.1 多表查詢

2.1.1 查詢語句

select e.id,e.signUpTime,e.auditStatus,e.auditResult,e.auditTime,e.paymentStatus,e.paymentTime,e.regPrintStatus,e.regPrintTime,p.personName,i.positionCode,i.positionName  from TExamSituationInfo  e inner join  e.tTPersonInfo_id  p inner join e.tTPositionInfo_id i where e.tTExamBatch_id = " + aBatchId + " and p.personID = '"+ c[2] +"' and i.positionCode = '"+ c[0] +"'";      //當前考試批次,職位代碼,身份證爲組合條件具體需求描述

與SQL SERVER中不一樣:

select e.id,p.id,i.id from (TExamSituationInfo  e inner join  TPersonInfo  p on  e.tTExamBatch_id_id =4 and e.tTPersonInfo_id_id = p.id and p.personID = 'p002') inner join TPositionInfo i  on e.tTPositionInfo_id_id = i.id and i.positionCode ='001'

 

2.1.2 獲取多表join返回的多個對象

List dl =null;

HibernateUtil.beginSession(session);

Query query = session.createQuery("from TExamSituationInfo  e inner join  e.tTPersonInfo_id  p inner join e.tTPositionInfo_id i " +

"where e.tTExamBatch_id = " + aBatchId);

//因查詢將返回多個對象,list()不強制轉換爲某個hibernate

dl = query.list();

Iterator<Object[]> iter = dl.iterator();    //迭代器返回的是對象數組

//數組中包含了三個hibernate對象

TExamSituationInfo d1 = (TExamSituationInfo)d[0];  //數組中的第一個元素

TPersonInfo d2 = (TPersonInfo)d[1];                 //數組中的第二個元素

TPersonInfo d3 =(TPositionInfo)d[2];                //數組中的第三個元素

d1.getAuditStatus()   //經過hibernate對象的get 方法獲取該對象中屬性

2.1.3 動態生成grid表格頭部

//建立頭部字段對象

var headerObject1 ={};

headerObject1.header ='序號',

headerObject1.dataIndex = 'sequence';

var headerObject2 ={};

headerObject2.header ='報考系統代碼',

headerObject2.dataIndex = 'systemCode';

var headerObject3 ={};

headerObject3.header ='職位代碼',

headerObject3.dataIndex = 'positionCode';

var headerObject4 ={};

headerObject4.header ='職位名稱',

headerObject4.dataIndex = 'positionName';

var headerObject5 ={};

headerObject5.header ='用人單位',

headerObject5.dataIndex = 'unitName';

var headerObject6 ={};

headerObject6.header ='計劃錄用人數',

headerObject6.dataIndex = 'recruitingNumbers';

//將全部字段對象加入數組

var arrys = [];

arrys.push(headerObject1);

arrys.push(headerObject2);

arrys.push(headerObject3);

arrys.push(headerObject4);

arrys.push(headerObject5);

arrys.push(headerObject6);

//建立空的列模式

PMS.OffcialExam.StatisticsReport.position.cm = 

new Ext.grid.ColumnModel([]);

//將對象數組加入列模式

PMS.OffcialExam.StatisticsReport.position.cm.setConfig(arrys,true);

2.1.4 對加載成功的store數據處理

當客戶端經過load()方法加載數據到store後,沒法便可獲取所加載的數據,其緣由是未判斷異步加載是否已完成,若對其加以判斷,則可對加載的數據便可處理。

//定義加載數據store

PMS.OffcialExam.StatisticsReport.position.store = new Ext.data.JsonStore({

url : './PositionInfo',

root : 'data',

totalProperty : 'count',

successProperty :  'success',

fields : [

          {name : 'sequence'},

          {name : 'systemCode'},

          {name : 'positionCode'},

          {name : 'positionName'},

  {name : 'unitCode'},

          {name : 'unitName'},

          {name : 'recruitingNumbers'}           

          ]

 

});

//定義統計信息記錄類型(保存從store中獲得的數據,用於動態加載新store)

PMS.OffcialExam.StatisticsReport.position.staticstRecord = Ext.data.Record.create([

{name : 'sequence'},

{name : 'systemCode'},

{name : 'positionCode'},

{name : 'positionName'},

{name : 'unitName'},

{name : 'recruitingNumbers'}

]);

//定義動態加載信息列表store

PMS.OffcialExam.StatisticsReport.position.listStore = new Ext.data.JsonStore({

proxy : new Ext.data.MemoryProxy({}),

reader: new Ext.data.ArrayReader({},

PMS.OffcialExam.StatisticsReport.position.staticstRecord)

});

var obtainRecords = [];

//統計選項

PMS.OffcialExam.StatisticsReport.position.condition = new Ext.form.FormPanel({

title : '錄用職位計劃統計選項',

border : false,

collapsible : true,//可收縮

    height : 275,

    layout : {

     type : 'hbox',

     align : 'stretch',

     padding : '20px 10px 0px 30px'

    },

    defaults : {

border : false

},

    items : [//其它控件代碼(略)

     xtype : 'button',

       text : '統計',

       handler : function() {

     var para = {};

     para.data = "{aBatchId:4}";

 para.action = 'positionStatisticsJson';  PMS.OffcialExam.StatisticsReport.position.store.load({

params: para,

                             //加載後執行的回調函數中success屬性可判斷是否加載完畢

callback: function(records, options, success){

if(success) obtainRecords = records;

},

scrop: store

});                          

         }

//其它控件代碼(略)

 

//將返回的記錄集 用於動態加載的數據顯示 

PMS.OffcialExam.StatisticsReport.position.hh = function(){

PMS.OffcialExam.StatisticsReport.position.listStore.removeAll();

PMS.OffcialExam.StatisticsReport.position.listStore.add(obtainRecords);

};

2.1.5 事務處理

在一個DAO類中,若類中的方法A調用方法B,且方法A中有啓動事務,則被方法B中不可從新啓動事務,不然會出現「transaction not started」錯誤,即事務沒法正常啓動。

public List<ISituationExamResult> getSituationPositionScoreData(Long batch) throws Exception{

try{

HibernateUtil.beginSession(session);

Query query = session.createQuery("select p.id from TPositionInfo p inner join p.tTPositionType_id t where p.tTExamBatch_id.id =:p1 and p.positionCode =:p2 and t.positionTypeCode =:p3 ");

         ……

         this.getById();   //調用本類中的方法

         ……

     }catch(){

}

return null;

}

public void getById() throws Exception {

try{

        HibernateUtil.beginSession(session);  //再次啓動事務,調用時將報錯

Query query = session.createQuery("select * from ……");

        ……

}

所以

getById()方法中應去掉事務啓動和提交的語句HibernateUtil.beginSession(session);和if(commit) HibernateUtil.commitSession(session);

同時爲了不其它類調用此方法,去未啓動事務,可將此方法設置爲內部方法。

 

2.1.5.1 中文亂碼問題??

store帶參數加載數據,由於ext中的ajax用的是UTF-8,因此直接傳的話會出現亂碼,咱們能夠用Extjs的encodeURIComponent先把中文編碼,而後在後臺用java的java.net.URLDecoder再解碼就能夠解決,示例以下:

stroe加載:

store.baseParams={

euser:encodeURIComponent(euser)

batName:encodeURIComponent(batName)   //編碼

};

store.load();

後臺解碼:

if(!Util.isEmpty(euser))

euser=URLDecoder.decode(euser,"UTF-8");   //解碼轉中文

if(!Util.isEmpty(batName)) batName=URLDecoder.decode(batName,"UTF-8"); //解碼轉中文

2.2 常見錯誤處理

2.2.1 Transcation not successful started

當一個類中方法A中有beginSession(session),

commitTranscation(session), rollbacktranscation(session),即應用了事務,此時在方法A中調用方法B,而方法B 也有應用事務,且與方法A在同一個類中,將會出現上述錯誤。

解決方法:可將方法B中沒必要再使用事務了,或是將方法B放到另外一個類中。

2.2.2 對於Hibernate中的對象轉爲json,最終轉爲string返回客戶端

2.2.2.1  對於返回單個對象的處理方法:

IExamRoomAssignInfo i =new IExamRoomAssignInfo();

……//對於i對象賦值

 

JsonObject jo = new JsonObject();

if(i != null){

jo.addProperty("success", true);

JsonObject data = (JsonObject)gson.toJsonTree(i);//獲得單個對象的jsonobject

jo.add("data", data);

}else{

jo.addProperty("success", false);

jo.addProperty("message", "數據不存在");

}

 

String result = gson.toJson(jo);

response.setContentType("text/plain");

response.setCharacterEncoding("utf-8");

PrintWriter pw = response.getWriter();

pw.print(result);

2.2.2.2  對於對象集合的處理方法

List<IExamRoomAssignInfo> il = new ArrayList<IExamRoomAssignInfo>();

……//il集合賦值

 

JsonObject jo = new JsonObject();

if(il != null){

jo.addProperty("success", true);

JsonArray data = (JsonArray)gson.toJsonTree(il);

jo.add("data", data);

}else{

jo.addProperty("success", false);

jo.addProperty("message", "數據不存在");

}

 

String result = gson.toJson(jo);

response.setContentType("text/plain");

response.setCharacterEncoding("utf-8");

PrintWriter pw = response.getWriter();

pw.print(result);

在獲取data時,若返回的是對象,或字符串時將以下處理:

////JsonObject data = (JsonObject)gson.toJsonTree(i);//獲得單個對象的jsonobject

////String data = gson.toJson(flag);//獲得單個對象的jsonobject

 

 

2.2.2.3 會話對象的應用

當處理多個相關表的數據操做時,可將先一個會話對象傳至下一個DAO對象中,可將相關表的處理聚集在同一個會話事務中,不然會報出錯誤信息:illegal attempted a proxy with two session。

 

try{

HibernateUtil.beginSession(session);

//查詢指定考點的全部考場

Query query = session.createQuery("from TExamRoomAssignInfo e where e.tTExamBatch_id.id =:p1 " +

"and e.tTExamAreaCode_id.id =:p2 and e.tTExamSiteInfo_id.id =:p3");

query.setLong("p1", aBatchId);

query.setLong("p2", areaId);

query.setLong("p3", siteId);

 

//寫入TRegisterationAssignInfo

DAORegisterationAssignInfo daodr = null;

try{

daodr = new DAORegisterationAssignInfo(session);

//保存准考證號分配信息,變動相關表的准考證分配狀態

daodr.saveRegisterationAssignData(r);

}catch(Exception e){

throw e;

}finally{

if(daodr != null) daodr.close();

}

2.2.2.4 建立並保存包含其它外鍵關聯對象

當一個對象中有外鍵,在建立這個對象並對其所屬性賦值時,其外鍵屬性的賦值方式爲:

原對象的外鍵屬性((外鍵類名)session.get(外鍵類.class,外鍵對象ID))

例如,

public void UpdatePracticeScoreScore(IExamResultInfo i)throws Exception

{

TExamResultInfo r = new TExamResultInfo();

TExamSubject tes1 = daos.getPracticeID();

ContentClone.copy(i, r, exclude);

r.setIsAbsent("");

r.setIsPublic("");

r.setScore(i.practiceScore);

r.settTExamBatch_id(tac.gettTExamBatch_id());

r.settTPersonInfo_id((TPersonInfo)session.get(TPersonInfo.class, i.tTPersonInfo_id));

r.settTPositionInfo_id((TPositionInfo) session.get(TPositionInfo.class, i.tTPositionInfo_id));

r.settTExamSubject_id(tes1);

if(i.practiceScore!=null) session.save(r);

……

2.2.2.5  排序的通用實現方法

Collections的排序方法sort(),能夠經過實現其接口comparator來自定義比較器,並且經過使用泛型實現更爲通用的方法

import java.util.Comparator;

import java.util.Collections;

import java.util.List;

import java.lang.reflect.Method;

import java.lang.reflect.InvocationTargetException;

 

 

public class ListSortUtil<T> {

@SuppressWarnings({ "unchecked", "rawtypes" })

public void Sort(List<T> list, final String method, final String sortType){

Collections.sort(list, new Comparator() {

public int compare(Object a ,Object b){

int ret = 0;

try{

//method的參數類型,此時該方法無參數,若是有則寫爲某個具體對象

Class[] param_1 = {};        

Object[] param_2 = {};

Method m1 = ((T)a).getClass().getMethod(method, param_1);

Method m2 = ((T)b).getClass().getMethod(method, param_1);

if(sortType != null&&sortType.equals("desc")){

ret = m2.invoke(((T)b), param_2).toString().compareTo(m1.invoke(((T)a), param_2).toString());

}else if(sortType.equals("asc")){

ret = m1.invoke(((T)a), param_2).toString().compareTo(m2.invoke(((T)b),param_2).toString());

}

 

}catch(NoSuchMethodException me){

me.printStackTrace();

}catch(IllegalAccessException le){

le.printStackTrace();

}catch(InvocationTargetException ie){

ie.printStackTrace();

}

return ret;

}

});

              

        }

}

排序的方法的調用,如list是一個IProduct 類集合對象,則對於list的價格(getPrice())降序排序可寫爲:

ListSortUtil< IProduct >   slist = new ListSortUtil< IProduct >();

Slist.Sort(list,」getPrice」,」desc」)

2.2.2.6  獲取上傳文件的方法

//獲取文件流

@SuppressWarnings("rawtypes")

private InputStream getFile(HttpServletRequest request, HttpServletResponse response) throws IOException{

   //文件較大時,可存於臨時目錄

 // 建立文件處理工廠,它用於生成FileItem對象。

       DiskFileItemFactory difactory = new DiskFileItemFactory();

       //設置緩存大小,若是上傳文件超過緩存大小,將使用臨時目錄作爲緩存。

       difactory.setSizeThreshold(1024 * 1024);

 

       // 設置處理工廠緩存的臨時目錄,此目錄下的文件須要手動刪除。

       String dir = this.getServletContext().getRealPath("/");

       File filedir = new File(dir + "filetemp");

       if (!filedir.exists())

           filedir.mkdir();

       difactory.setRepository(filedir);*/

 

       // 設置文件實際保存的目錄

       String userdir = dir + "files";

       File fudir = new File(userdir);

       if (!fudir.exists())

           fudir.mkdir();

// 建立request的解析器,它會將數據封裝到FileItem對象中。

       ServletFileUpload sfu = new ServletFileUpload(difactory); */

      

 //若通常文件,可直接讀取

// 建立request的解析器,它會將數據封裝到FileItem對象中。

       FileItemFactory factory = new DiskFileItemFactory();

       // 建立request的解析器,它會將數據封裝到FileItem對象中。

       ServletFileUpload sfu = new ServletFileUpload(factory);

       // 解析保存在request中的數據並返回list集合

       List list = null;

       try {

           list = sfu.parseRequest(request);

       } catch (FileUploadException e) {

           e.printStackTrace();

       }

       for (Iterator it = list.iterator(); it.hasNext();) {

        FileItem fi = (FileItem) it.next();

           if (!fi.isFormField()) {//不是表單字段數據

            return fi.getInputStream();

           }

       }

return null;

}

2.2.2.7  sessionFactory類沒法建立時排錯方法

在sessionFactory建立類中設置出錯信息輸出,可快速查找到出錯的具體問題。

public class HibernateUtil {

private static SessionFactory sessionFactory;

static {

try {

sessionFactory = new Configuration().configure().buildSessionFactory();

} catch (Throwable ex) {

ex.printStackTrace();     //顯示問題的輸出語句

throw new ExceptionInInitializerError(ex);

}

}

 

public static SessionFactory getSessionFactory() {

// Alternatively, you could look up in JNDI here

return sessionFactory;

}

 

public static void shutdown() {

// Close caches and connection pools

getSessionFactory().close();

}

 

public static Session getSession()

{

Session session = sessionFactory.openSession();

return session;

}

 

public static void beginSession(Session session)

{

session.getTransaction().begin();

}

 

public static void commitTransaction(Session session)

{

session.getTransaction().commit();

}

 

public static void rollbackTransaction(Session session)

{

Transaction tx = session.getTransaction();

if (tx.isActive())

tx.rollback();

}

}

2.2.2.8  上傳文件的處理方法

在上傳文件時,前端要採用上傳文件組件,後臺則須要以文件流方式讀取。

一、前端:

OEXAM.SystemCodeManage.major.upLoadFileText = new Ext.form.TextField({

id : 'excel_upload',

inputType : 'file',    //輸入類型

    fieldLabel : String.format(OEXAM.constant.labelTextCss,' Excel文件路徑'), 

    allowBlank:false,

blankText:"輸入不可爲空",   

    blankText:'上傳文件不能爲空'

});

 

 

//專業信息導入form    

OEXAM.SystemCodeManage.major.importForm = new Ext.form.FormPanel({

id:'import_form',

fileUpload : true,      //文件上傳組件

items : [OEXAM.SystemCodeManage.major.upLoadFileText

         /*{ 

        inputType : 'file',  

        fieldLabel : String.format(OEXAM.constant.labelTextCss,' Excel文件路徑'), 

        allowBlank:false,

     blankText:"輸入不可爲空",

        xtype : 'textfield',  

        blankText:'上傳文件不能爲空'

}*/],

buttons : [{

text : String.format(OEXAM.constant.buttonTextCss,"肯定"),

iconCls: 'yes',

handler : function (){

if(!Ext.getCmp("import_form").getForm().isValid()){

Ext.Msg.show({

title:'舒適提示',

msg:'您還未選擇文件!',

     modal:true,

     icon   : Ext.Msg.INFO,

buttons: Ext.Msg.OK

});

return;

}

var para = {};

para.action = 'importExcel';

Ext.getCmp("import_form").getForm().submit({   //提交方式

                    clienValidation:true,  

                    waitMsg:'正在上傳,請稍候',  

                    waitTitle:'提示:',  

                    url:'./MajorInfo',              

                    params :para,

                    method:'POST',

                   // timeout : 2000,

                    success:function(form,action){  

                     var res = action.result;

                     if(res.success){

                     if(res.message == 1){

                     Ext.Msg.show({

             title:'提示',

             msg:'專業信息導入成功',

             modal:true,

             icon:Ext.Msg.INFO,

             buttons:Ext.Msg.OK

             });

                             Ext.getCmp('import_form').getForm().reset();

                             OEXAM.SystemCodeManage.major.importWin.hide();

                             if(OEXAM.SystemCodeManage.major.listing.store.data.items != ""){

                             OEXAM.SystemCodeManage.major.majorList_store.removeAll();                         

                             }

                             OEXAM.SystemCodeManage.major.form.getForm().reset();

                             OEXAM.SystemCodeManage.major.store.reload();   //從新加載查詢條件中的專業信息  

                     }else if(res.message == 0){

                         Ext.Msg.show({

             title:'提示',

             msg:'專業信息導入失敗,請與系統管理員聯繫。',

             modal:true,

             icon:Ext.Msg.INFO,

             buttons:Ext.Msg.OK

             });

                         }else if(res.message == -1){

                         Ext.Msg.show({

             title:'提示',

             msg:'請上傳.xls格式的文件。',

             modal:true,

             icon:Ext.Msg.INFO,

             buttons:Ext.Msg.OK

             });

                         OEXAM.SystemCodeManage.major.upLoadFileText.setValue('');

                         }

                         

                     }

                                   

                    },  

                    failure:function(action,form){  

                        Ext.MessageBox.show({

title : '服務器錯誤',

msg : action.result.message,

buttons : Ext.MessageBox.OK,

icon : Ext.MessageBox.ERROR

});  

                    }  

               });

}

},{

text : String.format(OEXAM.constant.buttonTextCss,'重置'),

handler : function(){

Ext.getCmp('import_form').getForm().reset();

}

}]

});

 二、後臺

經過servlet中的protected void handleMultipartRequest(HttpServletRequest request, HttpServletResponse response) throws IOException方法獲得前端請求。代碼以下:

(1)若是是讀取文本類文件 

protected void handleMultipartRequest(HttpServletRequest request, HttpServletResponse response) throws IOException

{

 // 建立文件處理工廠,它用於生成FileItem對象。     

       FileItemFactory factory = new DiskFileItemFactory();

       // 建立request的解析器,它會將數據封裝到FileItem對象中。

       ServletFileUpload sfu = new ServletFileUpload(factory);     

       // 解析保存在request中的數據並返回list集合

       List<FileItem> list = null;

       HashMap<String, String> hmpara = new HashMap<String, String>();

       try {

           list = sfu.parseRequest(request);    //獲得請求中的上傳文件列表

       } catch (FileUploadException e) {

           this.logAndOutprintException(e, request, response);

           return;

       }

       InputStream ins = null;

       for (Iterator<FileItem> it = list.iterator(); it.hasNext();) {

        FileItem fi = (FileItem) it.next();

           if (!fi.isFormField()) {//不是表單字段數據

            ins = fi.getInputStream();                 //獲得上傳文件流

            hmpara.put(fi.getFieldName(), fi.getName());        //獲得文件上傳文件框控件的標記,上傳文件名

           }else{

            hmpara.put(fi.getFieldName(), fi.getString("utf-8"));  //獲得表單中action

           }

       }

       String action = hmpara.get("action");

       if("importExcel".equals(action)){

        importExcel(ins, hmpara, request,response);

       }else

{

this.logAndOutprintException(new Exception(CommonData.ERROR_ACTION), request, response);

}

 

return;

}

 

(2)若是是讀取圖片文件,能夠字節數組方式獲得,以便與數據庫中圖片字段相對應

protected void handleMultipartRequest(HttpServletRequest request, HttpServletResponse response) throws IOException

{

request.setCharacterEncoding("utf-8");

 

FileItemFactory factory = new DiskFileItemFactory();

ServletFileUpload upload = new ServletFileUpload(factory);

 

List<FileItem> items = null;

try {

items = upload.parseRequest(request);

}

catch(Exception e)

{

this.logAndOutprintException(e, request, response);

return;

}

 

Iterator<FileItem> iter = items.iterator();

HashMap<String, String> hms = new HashMap<String, String>();

HashMap<String, byte[]> hmb = new HashMap<String, byte[]>();  //定義存放圖片的數據結構

while (iter.hasNext()) 

{

    FileItem item = (FileItem)iter.next();

 

    if (item.isFormField()) 

    {

         hms.put(item.getFieldName(), item.getString("utf-8"));

    }

    else 

    {     

       String fieldName = item.getFieldName();

      String fileName = item.getName();

    

         int pos = fileName.lastIndexOf("/");

        if (pos == -1) pos = fileName.lastIndexOf("\\");

          if (pos != -1)

       fileName = fileName.substring(pos+1);

    

       hms.put(fieldName, fileName);

       hmb.put(fileName, item.get());   //獲得圖片的字節數組

    }

}

 

String action = hms.get("action");

 

if ("updatePersonPhoto".equalsIgnoreCase(action))

{

            //調用圖片存入的方法,其中可直接將圖片的字節數組賦值給數據表中的圖片字段(byte[]

updatePersonPhoto(hms, hmb, request, response);

}

else

{

this.logAndOutprintException(new Exception(CommonData.ERROR_ACTION), request, response);

}

 

   return;

}

在上傳文件時,有可能出現如下錯誤信息:

純文本文件的字符編碼未聲明。若是該文件包含 US-ASCII 範圍以外的字符,該文件將在某些瀏覽瀏覽器配置中呈現爲亂碼。該文件的字符編碼須要在傳輸協議層聲明,或者在文件中加入一個 BOM(字節順序標記)。

處理方法:重啓eclipes,同時經過瀏覽器清空cookie

2.2.2.9  Java類自定義的數據類型使用方法

在後端能夠自定義一些經常使用的狀態,字段值較少的可採用這種方法,如:性別、身份等,代碼:

public class Code2MeaningConstant {

private static String JSString = "Code2MeaningConstant = {};" + "\n\n";

 

 

//打印狀態

public static TreeMap<String, String> TPrintStatus = new TreeMap<String, String>();

static {

TPrintStatus.put("PRINTED", "已打印");

TPrintStatus.put("UNPRINT", "未打印");

createJSString("TPrintStatus", TPrintStatus);

}……

身份等,代碼在前端可定義store,來獲取這些數據:

UNIT.Common.Data.TPrintStatus =new Ext.data.JsonStore({

data:Code2MeaningConstant.TPrintStatus,

   fields:['code','meaning']

});

在前端須要的地方,則可讀取這些字段數據,如:

//打印狀態  代碼——中文

var convertPrintStatus = function(sourceCode) {

var str = sourceCode;

for (var i = 0; i < UNIT.Common.Data.TPrintStatus.data.length; i++) {

var code = UNIT.Common.Data.TPrintStatus.data.items[i].json.code;

if (sourceCode == code) {

str = UNIT.Common.Data.TPrintStatus.data.items[i].json.meaning;

break;

}

}

相關文章
相關標籤/搜索