学习笔记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
检查一下这些控件的属性id是否相同,最好分配一个全局的id。
//指定批次的职位类型记录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记录结构对象
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);
}
}
}
});
例子:将生成按钮置为不可用
(按钮id为PMS.OffcialExam.ExamSiteManage.assignExamRoom.genButton)
Ext.getCmp('PMS.OffcialExam.ExamSiteManage.assignExamRoom.genButton').disable();
发送请求,以及数据,同时要求返回对象(集合):
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
});
}
});
};
定义好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);
对于容器(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();
Ext.Msg.show({
title:'提示',
msg:result.message,
icon:Ext.Msg.INFO,
buttons:Ext.Msg.OK,
fn:function(btn){
//单击“肯定”按钮后,要处理的代码
}
});
在编程中,有时须要在容器(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;
};
控件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'}
控件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));
在前端界面中打开新的网页,具体用法:
//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;
动态更改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 ="输入框标题改变了:";
浏览器显示出错,如图:
问题:在items:[]定义中对象定义的个数与所描述的不对应,即items[a,b,]表示有三个控件项,但实际只定义了二个,将会在IE八、9等浏览器运行时,报出如上图错误
问题:发送请求时的参数对象未正确设置,如:
//报考职位代码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都会出现上述错误
若建立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错误
若要求查询后直接生成一个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
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'
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 方法获取该对象中属性
//建立头部字段对象
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);
当客户端经过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);
};
在一个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);
同时为了不其它类调用此方法,去未启动事务,可将此方法设置为内部方法。
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"); //解码转中文
当一个类中方法A中有beginSession(session),
commitTranscation(session), rollbacktranscation(session),即应用了事务,此时在方法A中调用方法B,而方法B 也有应用事务,且与方法A在同一个类中,将会出现上述错误。
解决方法:可将方法B中没必要再使用事务了,或是将方法B放到另外一个类中。
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);
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
当处理多个相关表的数据操做时,可将先一个会话对象传至下一个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();
}
当一个对象中有外键,在建立这个对象并对其所属性赋值时,其外键属性的赋值方式为:
原对象的外键属性((外键类名)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);
……
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”)
//获取文件流
@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;
}
在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();
}
}
在上传文件时,前端要采用上传文件组件,后台则须要以文件流方式读取。
一、前端:
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。
在后端能够自定义一些经常使用的状态,字段值较少的可采用这种方法,如:性别、身份等,代码:
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;
}
}