hibernate:unsave-value

理解Hibernate unsaved-value
本文详细解析了Hibernate中unsaved-value的作用及配置方法,包括不同主键类型下的应用策略。
http://forum.javaeye.com/viewtopic.php?t=1604&highlight=unsaved-value

当你显式的使用session.save()或者session.update()操作一个对象的时候,实际上是用不到unsaved-value的。某些情况下(父子表关联保存),当你在程序中并没有显式的使用save或者update一个持久对象,那么Hibernate需要判断被操作的对象究竟是一个已经持久化过的持久对象,是一个尚未被持久化过的内存临时对象。例如:

java代码:

Session session = ...;
Transaction tx = ...;

Parent parent = (Parent) session.load(Parent.class, id);

Child child = new Child();
child.setParent(parent);
child.setName("sun");

parent.addChild(child);
s.update(parent);

s.flush();
tx.commit();
s.close();



在上例中,程序并没有显式的session.save(child); 那么Hibernate需要知道child究竟是一个临时对象,还是已经在数据库中有的持久对象。如果child是一个新创建的临时对象(本例中就是这种情况),那么Hibernate应该自动产生session.save(child)这样的操作,如果child是已经在数据库中有的持久对象,那么Hibernate应该自动产生session.update(child)这样的操作。

因此我们需要暗示一下Hibernate,究竟child对象应该对它自动save还是update。在上例中,显然我们应该暗示Hibernate对child自动save,而不是自动update。那么Hibernate如何判断究竟对child是save还是update呢?它会取一下child的主键属性 child.getId() ,这里假设id是 java.lang.Integer类型的。如果取到的Id值和hbm映射文件中指定的unsave-value相等,那么Hibernate认为child是新的内存临时对象,发送save,如果不相等,那么Hibernate认为child是已经持久过的对象,发送update。

unsaved-value="null" (默认情况,适用于大多数对象类型主键 Integer/Long/String/...)

当Hibernate取一下child的Id,取出来的是null(在上例中肯定取出来的是null),和unsaved-value设定值相等,发送save(child)

当Hibernate取一下child的id,取出来的不是null,那么和unsaved-value设定值不相等,发送update(child)

例如下面的情况:

java代码:

Session session = ...;
Transaction tx = ...;

Parent parent = (Parent) session.load(Parent.class, id);
Child child = (Child) session.load(Child.class, childId);

child.setParent(parent);
child.setName("sun");

parent.addChild(child);
s.update(parent);

s.flush();
tx.commit();
s.close();



child已经在数据库中有了,是一个持久化的对象,不是新创建的,因此我们希望Hibernate发送update(child),在该例中,Hibernate取一下child.getId(),和unsave-value指定的null比对一下,发现不相等,那么发送update(child)。

BTW: parent对象不需要操心,因为程序显式的对parent有load操作和update的操作,不需要Hibernate自己来判断究竟是save还是update了。我们要注意的只是child对象的操作。另外unsaved-value是定义在Child类的主键属性中的。

java代码:

<class name="Child" table="child">
<id column="id" name="id" type="integer" unsaved-value="null">
<generator class="identity"/>
</id>
...
</class>



如果主键属性不是对象型,而是基本类型,如int/long/double/...,那么你需要指定一个数值型的unsaved-value,例如:

java代码:

unsaved-null="0"



在此提醒大家,很多人以为对主键属性定义为int/long,比定义为Integer/Long运行效率来得高,认为基本类型不需要进行对象的封装和解构操作,因此喜欢把主键定义为int/long的。但实际上,Hibernate内部总是把主键转换为对象型进行操作的,就算你定义为int/long型的,Hibernate内部也要进行一次对象构造操作,返回给你的时候,还要进行解构操作,效率可能反而低也说不定。因此大家一定要扭转一个观点,在Hibernate中,主键属性定义为基本类型,并不能够比定义为对象型效率来的高,而且也多了很多麻烦,因此建议大家使用对象型的Integer/Long定义主键。

unsaved-value="none"和
unsaved-value="any"

主主要用在主键属性不是通过Hibernate生成,而是程序自己setId()的时候。

在这里多说一句,强烈建议使用Hibernate的id generator,或者你可以自己扩展Hibernate的id generator,特别注意不要使用有实际含义的字段当做主键来用!例如用户类User,很多人喜欢用用户登陆名称做为主键,这是一个很不好的习惯,当用户类和其他实体类有关联关系的时候,万一你需要修改用户登陆名称,一改就需要改好几张表中的数据。偶合性太高,而如果你使用无业务意义的id generator,那么修改用户名称,就只修改user表就行了。

由这个问题引申出来,如果你严格按照这个原则来设计数据库,那么你基本上是用不到手工来setId()的,你用Hibernate的id generator就OK了。因此你也不需要了解当

unsaved-value="none"和
unsaved-value="any"

究竟有什么含义了。如果你非要用assigned不可,那么继续解释一下:

unsaved-value="none" 的时候,由于不论主键属性为任何值,都不可能为none,因此Hibernate总是对child对象发送update(child)

unsaved-value="any" 的时候,由于不论主键属性为任何值,都肯定为any,因此Hibernate总是对child对象发送save(child)

大多数情况下,你可以避免使用assigned,只有当你使用复合主键的时候不得不手工setId(),这时候需要你自己考虑究竟怎么设置unsaved-value了,根据你自己的需要来定。

BTW: Gavin King强烈不建议使用composite-id,强烈建议使用UserType。

因此,如果你在系统设计的时候,遵循如下原则:

1、使用Hibernate的id generator来生成无业务意义的主键,不使用有业务含义的字段做主键,不使用assigned。

2、使用对象类型(String/Integer/Long/...)来做主键,而不使用基础类型(int/long/...)做主键

3、不使用composite-id来处理复合主键的情况,而使用UserType来处理该种情况。

那么你永远用的是unsaved-value="null" ,不可能用到any/none/..了。
<!-- 任务令扣账管理 --> <template> <div style="overflow: hidden;" class="deduction-config"> <title>{{$route.name}}</title> <h1>{{$route.name}}</h1> <aui-form id="editForm"> <div class="first-field" :class="isShowMore?'showMore':'hideMore'"> <aui-form-item label="工厂全称"> <aui-dropdown size="small" v-model="searchForm.factoryCodeListStr" :op="factoryFullNameOp" ref="factoryDropDown"></aui-dropdown> </aui-form-item> <aui-form-item label="发布状态"> <aui-dropdown size="small" v-model="searchForm.releaseStatusListStr" :op="releaseStatusOp"></aui-dropdown> </aui-form-item> <aui-form-item label="任务令"> <aui-input v-model="searchForm.workOrderNameStr" :op="workOrderNameOp"></aui-input> </aui-form-item> <aui-form-item label="产品型号"> <aui-input v-model="searchForm.prodModelCodeStr" :op="prodModelCodeOp"></aui-input> </aui-form-item> <aui-form-item label="编码"> <aui-input v-model="searchForm.itemCodeStr" :op="itemCodeStrOp"></aui-input> </aui-form-item> <aui-form-item label="扣账时间起" label-width="80px"> <aui-datepicker size="small" v-model="searchForm.startTimeStr" :op="startTimeOp"></aui-datepicker> </aui-form-item> <aui-form-item label="扣账时间止" label-width="80px"> <aui-datepicker size="small" v-model="searchForm.endTimeStr" :op="endTimeOp"></aui-datepicker> </aui-form-item> <aui-form-item label="扣账进度"> <aui-dropdown v-model="searchForm.deductionProgress" :op="deductionProgressOp"></aui-dropdown> </aui-form-item> <aui-form-item class="first-field-btn" label-width="0px"> <i v-show="isTriangleIconShow" class="hae-icon" :class="isShowMore?'icon-down':'icon-left-o'" @click="isShowMore = !isShowMore "></i> <aui-button hue="primary" round="true" size="small" @click="search">查询</aui-button> <aui-button hue="primary" round="true" size="small" @click="reset">重置</aui-button> </aui-form-item> </div> </aui-form> <!-- 导入导出功能 :发布 --> <aui-row class="gridTopImportBtns"> <aui-button size="small" v-show="isReleaseShowFlag" @click="release">发布</aui-button> <i class="hae-icon icon-setup" @click.stop="toolBoxShow = !toolBoxShow"> <div v-show="toolBoxShow"> <aui-fileupload round="true" size="small" :mini-mode="true" class='hae-btn' :op="importop">导入</aui-fileupload> <aui-button round="true" size="small" @click="dynamicExportClick">导出头表数据</aui-button> <aui-button round="true" size="small" @click="recodrDynamicExportClick">导出发料明细</aui-button> <aui-button round="true" size="small" @click="downloadFile" resetTime='5000' style="margin-top: 5px">导入模板下载</aui-button> </div> </i> </aui-row> <!-- 扣账记录页面 --> <aui-dialog-box title="发料明细" v-model="showRecord" width="95%" top="10%" :dragable="true"> <!-- 发料明细导出 --> <aui-row style="margin-top:-4px;"> <aui-button size="small" @click="oneRecodrDynamicExportClick">导出</aui-button> </aui-row> <deduction-record v-bind:selectData="clickRowData" v-if="showRecord" :isChange="isChange"></deduction-record> </aui-dialog-box> <div class="grid-head-config"> <aui-grid ref="grid" :op="gridOp" class="dataArea-field"></aui-grid> </div> </div> </template> <script> import { initHtml } from '../unit/js/html.js' import DeductionRecord from '../unit/wave/WaveWorkOrderDeductionRecord.vue' import { downloadFun } from '../unit/js/fileDownload.js' import { Grid, Form, FormItem, Row, Input, Dropdown, Button, Hae, Pager, DialogBox, Datepicker, Fileupload, $, } from '@aurora/ui3' import { publicFun } from '@/components/unit/js/public.js' export default { components: { AuiButton: Button, AuiDialogBox: DialogBox, AuiGrid: Grid, AuiForm: Form, AuiFormItem: FormItem, AuiRow: Row, AuiInput: Input, AuiDropdown: Dropdown, AuiDatepicker: Datepicker, AuiFileupload: Fileupload, DeductionRecord }, data() { let that = this let curDate = new Date() curDate.setDate(curDate.getDate() - 30) let endDate = new Date() endDate.setDate(curDate.getDate() + 1) return { showRecord: false, // 是否弹出记录页面 clickRowData: {}, // 被双击的数据 saveList: [], // 用于记录刚刚保存的数据,方便打钩 timer: 0, // 定义双击事件的次数 isChange: Math.ceil(publicFun.getSecurityRandom() * 100), // 新版是否显示更多条件 toolBoxShow: false, isShowMore: true, isTriangleIconShow: true, // 发布按钮显示控制 isReleaseShowFlag: false, // 初始化查询对象 searchForm: { releaseStatusListStr: '1', startTimeStr: curDate, endTimeStr: endDate }, // 部门名称 factoryFullNameOp: { id: 'factoryFullNameOp', showClearBtn: true, autoSelect: true, alwaysLoad: true, multi: true, editable: true, textField: 'factoryFullName', valueField: 'factoryCode', placeHolder: '-----请选择-----', dataset: { source: { type: 'post', url: 'services/factoryInfoService/getAllFactoryInfoList' } }, emptyDataMsg: '-----没有数据-----' }, releaseStatusOp: { showClearBtn: true, autoSelect: true, multi: true, editable: true, textField: 'releaseStatusName', valueField: 'releaseStatus', placeHolder: '-----请选择-----', dataset: { value: [ { releaseStatus: 1, releaseStatusName: '待发布' }, { releaseStatus: 2, releaseStatusName: '发布中' }, { releaseStatus: 3, releaseStatusName: '发布成功' }, { releaseStatus: 4, releaseStatusName: '发布失败' } ] }, emptyDataMsg: '-----没有数据-----' }, // 任务令 workOrderNameOp: { id: 'workOrderNameOp', showClearBtn: true, editable: true, placeHolder: '-----可模糊查询-----' }, // 产品型号 prodModelCodeOp: { id: 'prodModelCodeOp', showClearBtn: true, editable: true, placeHolder: '-----可模糊查询-----' }, deductionProgressOp: { showClearBtn: true, autoSelect: false, multi: false, editable: false, textField: 'deductionProgressName', valueField: 'deductionProgress', placeHolder: '-----请选择-----', dataset: { value: [ { deductionProgress: 'all', deductionProgressName: '全部扣账' }, { deductionProgress: 'part', deductionProgressName: '部分扣账' } ] }, emptyDataMsg: '-----没有数据-----' }, // 编码 itemCodeStrOp: { id: 'itemCodeStrOp', showClearBtn: true, editable: true, placeHolder: '-----可模糊查询-----' }, // 扣账时间(起) startTimeOp: { id: 'startTimeOp', dateFormat: 'yyyy-MM-dd', dbDateFormat: 'yyyy-MM-dd 00:00:00', valueField: 'startTimeStr', placeHolder: '-----请选择-----' }, // 扣账时间(止) endTimeOp: { id: 'endTimeOp', dateFormat: 'yyyy-MM-dd', dbDateFormat: 'yyyy-MM-dd 23:59:59', valueField: 'endTimeStr', placeHolder: '-----请选择-----' }, // 导入控件 importop: {}, gridOp: { name: 'baseGrid', // name值,配置个性化customSetting/customized id: 'deductionGrid', showTip: true, tipOp: { type: 'normal' }, customized: true, // 是否打开隐藏列功能(动态列不能打开) allowFreeze: true, // 冻结选项 allowResize: true, allowSort: true, percentWidth: false, showStatus: false, showPager: true, // 展示分页 autoLoad: true, // 自动加载 showSeq: false, // 展示序号 cssName: 'text-center', editMode: true, pagerOp: { mode: 'number', pageSizes: [40, 50, 100], pageVO: { curPage: 1, pageSize: 40 } }, dataset: { value: [] }, operation: { insert: { mode: 'top' // 每次新增数行时,都在表格首行的上方依次添加(可选:top | bottom) }, save: { onBeforeSave(ajax, optOp, grid) { let changeList = grid.data let addList = grid.data.items2Create let updateList = grid.data.items2Update if (addList.length === 0 && updateList.length === 0) { Hae.topBox('未选择要保存的数据', 'error', false, 2000) return false } // 校验新增数据字段是否通过 if (addList.length > 0) { let checkResult = that.checkSaveData(addList) if (!checkResult) { return false } } Hae.ajax({ url: 'services/waveWorkorderDeductionService/saveHeadTableData', type: 'post', async: false, data: { addList, updateList }, dataType: 'text', success(result) { if (result === 'SUCCESS') { Hae.topBox('保存成功!', 'successful', false, 2000) let gridWidger = that.$refs.grid.widget that.search() that.saveList = that.saveList.concat(addList) that.saveList = that.saveList.concat(updateList) } else { Hae.topBox(result, 'error', false, 5000) } } }) return false } }, delete: { icon: 'hae-icon icon-del', text: '删除', onClick: this.delete } }, columns: [ { multi: true, columnType: 'select' }, { field: 'wbrdId', header: 'id', hidden: true, editable: false }, { field: 'factoryCode', header: '工厂全称', width: '130', cssName: 'text-center', headCss: 'text-center', textField: 'factoryFullName', valueField: 'factoryCode', freezable: false, editable: false }, { field: 'workorderName', header: '任务令', width: '110', editable: true, cssName: 'text-center', headCss: 'text-center', alwaysLoad: true, freezable: false, rule: { required: true } }, { field: 'prodModelCode', header: '产品型号', editable: false, width: '120', cssName: 'text-center', headCss: 'text-center', freezable: false }, { field: 'itemCode', header: '编码', width: '110', editable: false, cssName: 'text-center', headCss: 'text-center', freezable: false }, { field: 'workorderQty', header: '任务令数量', editable: false, width: '110', cssName: 'text-center', headCss: 'text-center', freezable: false }, { field: 'planStartTime', header: '计划开工时间', width: '120', editable: false, cssName: 'text-center', headCss: 'text-center', freezable: false, type: 'dateTime' }, { field: 'planOnlineTime', header: '计划上线时间', width: '120', editable: false, cssName: 'text-center', headCss: 'text-center', freezable: false, type: 'dateTime' }, { field: 'planCompleteTime', header: '计划完工时间', width: '120', editable: false, cssName: 'text-center', headCss: 'text-center', freezable: false, type: 'dateTime' }, { field: 'actStartDate', header: '实际开工时间', width: '120', editable: false, cssName: 'text-center', headCss: 'text-center', freezable: false, type: 'dateTime' }, { field: 'deductionDate', header: '扣账时间', editable: true, width: '120', cssName: 'text-center', headCss: 'text-center', freezable: false, type: 'dateTime', rule: { required: true }, editorOp: { conf: { onShow: () => { setTimeout(() => { $('.hae-popup .input-editable input').removeAttr('readonly') }, 500) } } } }, { field: 'batchNo', header: '扣账批次号', editable: true, cssName: 'text-center', headCss: 'text-center', freezable: false, width: '100', type: 'integer', rule: { required: true, custom: { regular: function(value, ruleOp) { let reg = /^[1-9]\d{0,7}$/ return reg.test(value) }, msg: '请输入不超过8位数字的正整数', priority: 1000 } } }, { field: 'ddiQty', header: '本次扣账数量', editable: true, cssName: 'text-center', headCss: 'text-center', freezable: false, width: '120', type: 'integer', rule: { required: false, custom: { regular: function(value, ruleOp) { if (publicFun.isNull(value)) { return true } let reg = /^[1-9]\d*$/ return reg.test(value) }, msg: '请输入正整数', priority: 1000 } } }, { field: 'ddiQtyHis', header: '历史已扣账数量', editable: false, width: '120', cssName: 'text-center', headCss: 'text-center', freezable: false }, // 是否冻结列 { field: 'isFreezeStr', header: '是否冻结', editable: true, width: '100', cssName: 'text-center', headCss: 'text-center', freezable: false, type: 'dropdown', rule: { required: false // 非必填 }, editorOp: { conf: { dataset: { value: [ { value: 'Y', text: '是' }, { value: 'N', text: '否' } ] }, textField: 'text', valueField: 'value' } } }, // 冻结时间列 { field: 'freezeDate', header: '冻结时间', editable: true, width: '150', cssName: 'text-center', headCss: 'text-center', freezable: false, type: 'dateTime', rule: { required: false // 非必填 } }, { header: '发布状态', field: 'releaseStatusName', width: '110', editable: false, cssName: 'text-center', headCss: 'text-center', freezable: false }, { header: '生产指令进度', field: 'ppoProgressCode', width: '110', editable: false, cssName: 'text-center', headCss: 'text-center', freezable: false }, { field: 'errorMessage', header: '失败原因', width: '160', editable: false, cssName: 'text-center', headCss: 'text-center', freezable: false, showTip: true }, { field: 'releaseBy', header: '发布用户', width: '120', editable: false, cssName: 'text-center', headCss: 'text-center', freezable: false }, { field: 'releaseDate', header: '发布时间', width: '120', type: 'dateTime', editable: false, cssName: 'text-center', headCss: 'text-center', freezable: false } ], // 双击事件 onRowClick(rowData, tr, e) { // 只能点击已发布的数据看发料记录 if (rowData.releaseStatusName === '发布成功') { that.timer++ if (that.timer >= 2) { // 校验是否有发料明细数据 let haveDataInSystem = true Hae.ajax({ url: 'services/waveWorkorderDeductionService/getReleaseRecordList/page/40/1', type: 'post', async: false, data: { workOrderNameStr: rowData.workorderName }, dataType: 'text', success(result) { let resultVo = JSON.parse(result) if (resultVo.result === undefined || resultVo.result.length == '0') { Hae.topBox(`任务令:${rowData.workorderName} 暂无发料数据`, 'error', false, 2000) haveDataInSystem = false return false } else { haveDataInSystem = true } } }) if (haveDataInSystem) { that.timer = 0 // 清空计数器 that.showRecord = true that.clickRowData = rowData } } setTimeout(() => { that.timer = 0 }, 300) } }, // 编辑完后,自动计算数据 onAfterEdit(value, rowData, td, col, oldValue) { let { widget } = that.$refs.grid let row = widget.getCellRow(td) // 单元格所在行jQuery对象 // 1.根据任务令带出相关数据信息 if (col.header === '任务令') { if (publicFun.isNull(value)) { Hae.topBox('任务令必填', 'error', false, 2000) return false } let responseStr = '' Hae.ajax({ url: 'services/waveWorkorderDeductionService/getWorkOrderInfoByWorkOrderName', type: 'post', async: false, data: { workorderName: value }, dataType: 'text', success(result) { let response = JSON.parse(result) if (result === undefined || publicFun.isNull(response.workorderName)) { Hae.topBox(`任务令:[${value}]信息不存在`, 'error', false, 2000) rowData.fieldCheckFlag = false return false } else if (publicFun.isNull(response.factoryCode)) { rowData.fieldCheckFlag = false Hae.topBox(`用户暂无任务令:${value} 对应的工厂权限`, 'error', false, 2000) return false } else { rowData.fieldCheckFlag = true responseStr = result } } }) if (responseStr !== undefined && publicFun.isNoNull(responseStr)) { let response = JSON.parse(responseStr) // 根据任务令反查工厂全称 that.setColValueNew(rowData, td, 'factoryCode', response.factoryCode, response.factoryFullName) // 根据任务令反查产品型号 that.setColValueNew(rowData, td, 'prodModelCode', response.prodModelCode, response.prodModelCode) // 根据任务令反查编码 that.setColValueNew(rowData, td, 'itemCode', response.itemCode, response.itemCode) // 根据任务令反任务令数量 that.setColValueNew(rowData, td, 'workorderQty', response.workorderQty, response.workorderQty) // 根据任务令反查历史已扣账数量 that.setColValueNew(rowData, td, 'ddiQtyHis', response.ddiQtyHis, response.ddiQtyHis) // 根据任务令反查计划开工时间 that.setColValueNew(rowData, td, 'planStartTime', Hae.Date.format(response.planStartTime, 'yyyy-MM-dd hh:mm'), Hae.Date.format(response.planStartTime, 'yyyy-MM-dd hh:mm')) // 根据任务令反查计划上线时间 that.setColValueNew(rowData, td, 'planOnlineTime', Hae.Date.format(response.planOnlineTime, 'yyyy-MM-dd hh:mm'), Hae.Date.format(response.planOnlineTime, 'yyyy-MM-dd hh:mm')) // 根据任务令反查计划完工时间 that.setColValueNew(rowData, td, 'planCompleteTime', Hae.Date.format(response.planCompleteTime, 'yyyy-MM-dd hh:mm'), Hae.Date.format(response.planCompleteTime, 'yyyy-MM-dd hh:mm')) } } }, onBeforeEdit: (cellValue, rowData, td, col) => { let { releaseStatusName } = rowData if (releaseStatusName == '待发布' || releaseStatusName == '发布失败') { // 存量数据只能修改待发布、发布失败的数据 if (col.header !== '扣账时间' && col.header !== '本次扣账数量'&& col.header !== '是否冻结'&& col.header !== '冻结时间') { return false } } else if (publicFun.isNoNull(releaseStatusName)) { return false } }, onRenderRow(tr, rowData, rowIdx) { // 表格中的数据加载完成后触发的事件 if (rowData.releaseStatusName === '发布失败') { tr.css('background', 'rgb(241, 127, 123)') } else if (rowData.releaseStatusName === '发布成功') { tr.css('background', 'rgb(214, 252, 214)') } else if (rowData.releaseStatusName === '发布中') { tr.css('background', 'rgb(247, 214, 152)') } }, onBeforeBindData: (op, data, widget) => { let that = this // 页面保存的数据自动打钩 if (that.saveList.length > 0) { let recodeList = that.saveList for (let i = 0; i < data.length; i++) { recodeList.forEach(item => { if (item.workorderName === data[i].workorderName) { widget.setRecordSelected(data[i]) } }) } } }, onSelected(tr, rowData, selected) { // 取消选择的数据从saveList中删除 if (!selected && publicFun.isNoNull(that.saveList)) { for (let a = that.saveList.length - 1; a >= 0; a--) { let row = that.saveList[a] if (row.workorderName === rowData.workorderName && !selected) { that.saveList.splice(a, 1) } } } }, onBeforeSelect(tr, rowData, selected) { if (rowData.releaseStatusName == '发布失败' || rowData.releaseStatusName == '待发布' || publicFun.isNull(rowData.releaseStatusName) ) { return true } else { return false } }, // 组件渲染完成时执行的事件。 onRender(grid) { let fromDom = $('#editForm') initHtml.gridAutoHeight(fromDom) } } } }, created() { let that = this that.importop = publicFun.getImportOp('tmas.waveWorkOrderDeduction', Hae) }, mounted() { // 注册全局单机事件隐藏导入按钮栏 document.addEventListener('click', e => { setTimeout(() => { if ( !$(e.target).hasClass('icon-setup') || !$(e.target).hasClass('gridTopBtnDiv') ) { this.toolBoxShow = false // 收起导入导出按钮 } }, 300) }) this.initUserReleaseMenu() // 判断是否有更多条件显示隐藏小三角 let editFormHeight = $('.first-field').outerHeight() this.isTriangleIconShow = !(editFormHeight < 38) this.isShowMore = false }, methods: { // 判断用户是否有发布权限 initUserReleaseMenu() { let that = this Hae.ajax({ url: 'services/waveWorkorderDeductionService/getReleaseUserInfo', type: 'post', async: false, data: {}, dataType: 'json', success(result) { if (publicFun.isNoNull(result)) { that.isReleaseShowFlag = true } } }) }, setSelect(rowData, a) { let { widget } = this.$refs.grid let row = widget.getRow(rowData) widget.rowSelected(row, true, false) }, // 设置单元格值New setColValueNew(rowData, td, fieldName, valueField, textField) { let { widget } = this.$refs.grid let row = widget.getCellRow(td) // 根据编辑的单元格所在行jQuery对象 let rowCell = widget.getRowCell(row, fieldName) // 获取FieldName需要被设置数据的表格对象 rowData[fieldName] = valueField // 表格数据赋值 rowCell.children().html(textField) // 修改页面表格内容 rowCell.attr('val', textField) }, // 校验搜索 search() { Hae.validForm($('#editForm'), result => { if (result === false) { return false } else { // 查询数据 this.findClick() return true } }) }, // 保存数据校验 checkSaveData(list) { let checkFlag = true list.forEach(element => { if (!element.fieldCheckFlag) { Hae.topBox(`任务令:${element.workorderName} 不存在!`, 'error', false, 2000) checkFlag = false return false } if (publicFun.isNull(element.deductionDate)) { Hae.topBox('页面新增数据时“扣账时间”必填', 'error', false, 2000) checkFlag = false return false } if (publicFun.isNoNull(element.ddiQty) && Number(element.ddiQty) > Number(element.workorderQty)) { Hae.topBox('本次扣账数量不能大于任务令数量', 'error', false, 2000) checkFlag = false return false } }) return checkFlag }, // 判断是否正数 reset() { let curDate = new Date() curDate.setDate(curDate.getDate() - 30) let endDate = new Date() endDate.setDate(curDate.getDate() + 1) this.searchForm = { factoryCodeListStr: '', releaseStatusListStr: '1', workOrderNameStr: '', prodModelCodeStr: '', itemCodeStr: '', startTimeStr: curDate, endTimeStr: endDate, deductionProgress: '' } }, findClick() { let that = this let { searchForm } = that let newcol = { dataset: { source: { data: searchForm, // 带条件的查询 type: 'post', url: 'services/waveWorkorderDeductionService/getHeadTableList/page/{{pageSize}}/{{curPage}}' } } } that.$refs.grid.widget.reInit(newcol) }, delete() { let that = this let { widget } = this.$refs.grid let selectList = widget.getSelectedRecords() if (selectList.length === 0) { Hae.topBox('未选择数据,或未选择有效数据', 'warning', false, 2000) return } selectList.forEach(item => { if (item.releaseStatusName === '发布成功' || item.releaseStatusName === '发布中') { Hae.topBox(`任务令:${item.workorderName} ${item.releaseStatusName},不允许删除`, 'warning', false, 2000) } }) Hae.confirm('是否删除该数据?', function(bool) { if (bool) { // 删除新增但未保存的数据 let unSaveList = [] for (let i = selectList.length - 1; i >= 0; i--) { if (selectList[i]._$index < 0) { let currRow = widget.getRowData(selectList[i]._$index) let unSaveDataJQuery = widget.getRow(currRow) unSaveList.push(unSaveDataJQuery) selectList.splice(i, 1) } } if (unSaveList.length > 0) { unSaveList.forEach(item => { widget.removeRows(item) }) if (!selectList.length > 0) { return false } } // 删除数据已存在的数据 Hae.ajax({ url: 'services/waveWorkorderDeductionService/deleteHeadTableData', type: 'post', async: false, data: { list: selectList }, dataType: 'text', success(result) { if (result === 'SUCCESS') { Hae.topBox('删除成功!', 'successful', false, 2000) that.$refs.grid.widget.reInit() } else { Hae.topBox(result, 'error', false, 2000) } } }) } }) }, release() { let that = this let { widget } = this.$refs.grid let selectList = widget.getSelectedRecords() if (selectList.length === 0) { Hae.topBox('未选择数据,或未选择有效数据', 'warning', false, 2000) return } let changeList = widget.getChangedRecords() if (publicFun.isNoNull(changeList)) { let unSaveList = [] unSaveList = unSaveList.concat(changeList.insertedRecords) unSaveList = unSaveList.concat(changeList.updatedRecords) // 未保存的数据不能释放 let unSave = '' if (unSaveList != undefined && unSaveList.length > 0) { unSaveList.forEach(item => { let key = item.workorderName selectList.forEach(selectVo => { if (key === selectVo.workorderName) { unSave += `${key};` } }) }) } if (publicFun.isNoNull(unSave)) { Hae.topBox(`任务令:${unSave.substring(0, unSave.length - 1)} 未保存,不能发布!`, 'error', false, 2000) return false } } let releaseStatus = true let sendID = [] selectList.forEach(item => { // 只能发布待发布、发布失败的数据 if (item.releaseStatusName !== '待发布' && item.releaseStatusName !== '发布失败') { Hae.topBox(`任务令:${item.workorderName}当前状态不能发布`, 'warning', false, 2000) releaseStatus = false } else { sendID.push(item.wbrdId) } }) if (!releaseStatus) { return true } let gridWidger = that.$refs.grid.widget Hae.confirm('是否提交已选择数据', (bool) => { if (bool) { Hae.ajax({ url: 'services/waveWorkorderDeductionService/publishData', data: { ids: sendID }, type: 'post', dataType: 'text', success: (result) => { if (result === 'SUCCESS') { Hae.topBox('任务令发布成功', 'successful', false, 2000) publicFun.jumpFormerPage(gridWidger) // 保存成功的数据从saveList中移除 that.saveList = [] } else { Hae.topBox(result, 'error', false, 2000) publicFun.jumpFormerPage(gridWidger) } } }) } }) }, // 导出 dynamicExportClick() { Hae.validForm($('#editForm'), result => { if (result === false) { Hae.topBox('必填查询条件不能为空', 'error', false, 2000) return false } else { // 查询数据 this.export() return true } }) }, export() { let { searchForm } = this Hae.ajax({ url: 'services/exportFileUtilService/exportWaveWorkOrderDeduction', data: searchForm, type: 'post', success(data) { Hae.confirm( '导出任务已开始,你可以进入[我的导入导出>导出查询]中查看任务状态并下载导出文件!', function(bool) { if (bool) { window.open('#/ListExport') } } ) } }) }, // 发料明细单条任务令导出 oneRecodrDynamicExportClick() { let clickDatExport = this.clickRowData let searchFormExport = this.searchForm searchFormExport.workOrderNameStr = clickDatExport.workorderName Hae.ajax({ url: 'services/exportFileUtilService/exportWaveWorkOrderDeductionRecord', data: searchFormExport, type: 'post', success(data) { Hae.confirm( '导出任务已开始,你可以进入[我的导入导出>导出查询]中查看任务状态并下载导出文件!', function(bool) { if (bool) { window.open('#/ListExport') } } ) } }) }, recodrDynamicExportClick() { let { searchForm } = this Hae.confirm('为避免大批量数据导出,是否已精确查询条件?', (bool) => { if (bool) { Hae.validForm($('#editForm'), result => { if (result) { Hae.ajax({ url: 'services/exportFileUtilService/exportWaveWorkOrderDeductionRecord', data: searchForm, type: 'post', success(data) { Hae.confirm( '导出任务已开始,你可以进入[我的导入导出>导出查询]中查看任务状态并下载导出文件!', function(bool) { if (bool) { window.open('#/ListExport') } } ) } }) } else { Hae.topBox('必填查询条件不能为空', 'error', false, 2000) } }) } }) }, // 下载导入模板 downloadFile() { downloadFun.getID('任务令扣账管理', '导入') // 功能模块,类型 } } } </script> <style scoped src='./../unit/css/newModelPublic.css'> </style> <style scoped> .gridTopImportBtns { width: 200px; position: absolute; top: 111px; left: 285px; /**6px 84px 174px 266px**/ z-index: 30; } .deduction-config { height: 100%; } .grid-head-config { height: 100%; } .deduction-config :deep(#deductionGrid .grid-body) { height: calc(100% - 48px) !important; } #deductionGrid { height: calc(100% - 120px); } .deduction-config :deep(#deductionGrid .hae-grid-body) { height: 100%; } </style> 中是否冻结的选项框是Y和N
最新发布
09-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值