改进编辑和删除功能,对于会影响多余记录的情况,提示用户并可选择是否继续执行

This commit is contained in:
datagear 2018-12-04 13:55:16 +08:00
parent bc0538caa5
commit 64c47afe57
10 changed files with 178 additions and 72 deletions

View File

@ -232,6 +232,8 @@ public class UpdatePersistenceOperation extends AbstractExpressionModelPersisten
}
}
boolean propertyUpdated = false;
List<UpdateInfoForAutoKeyUpdateRule> updateInfoForAutoKeyUpdateRules = new ArrayList<UpdateInfoForAutoKeyUpdateRule>();
// 先处理删除属性值它不会受外键约束的影响
@ -255,8 +257,13 @@ public class UpdatePersistenceOperation extends AbstractExpressionModelPersisten
if (updatePropertyValue == null)
{
if (originalPropertyValue != null)
deletePersistenceOperation.deletePropertyTableData(cn, dialect, table, model, originalCondition,
property, relationMapper, null, false);
{
int myCount = deletePersistenceOperation.deletePropertyTableData(cn, dialect, table, model,
originalCondition, property, relationMapper, null, false);
if (propertyUpdated == false && myCount > 0)
propertyUpdated = true;
}
else
;
}
@ -280,14 +287,17 @@ public class UpdatePersistenceOperation extends AbstractExpressionModelPersisten
if (propertyKeyUpdateRule == null || propertyKeyUpdateRule.isManually())
{
int myUpdateCount = updatePropertyTableData(cn, dialect, table, model, originalCondition,
int myCount = updatePropertyTableData(cn, dialect, table, model, originalCondition,
property, pmm, originalPropertyValue, updatePropertyValue, updateObj, false,
expressionEvaluationContext);
if (myUpdateCount == 0)
insertPersistenceOperation.insertPropertyTableData(cn, dialect, table, model, updateObj,
property, pmm, new Object[] { updatePropertyValue }, null,
if (myCount == 0)
myCount = insertPersistenceOperation.insertPropertyTableData(cn, dialect, table, model,
updateObj, property, pmm, new Object[] { updatePropertyValue }, null,
expressionEvaluationContext);
if (propertyUpdated == false && myCount > 0)
propertyUpdated = true;
}
else
{
@ -298,8 +308,11 @@ public class UpdatePersistenceOperation extends AbstractExpressionModelPersisten
}
else
{
deletePersistenceOperation.deletePropertyTableData(cn, dialect, table, model, originalCondition,
property, pmm, null, false);
int myCount = deletePersistenceOperation.deletePropertyTableData(cn, dialect, table, model,
originalCondition, property, pmm, null, false);
if (propertyUpdated == false && myCount > 0)
propertyUpdated = true;
}
}
}
@ -318,18 +331,25 @@ public class UpdatePersistenceOperation extends AbstractExpressionModelPersisten
{
Object updatePropertyValue = updateInfo.getUpdatePropertyValue();
int myUpdateCount = updatePropertyTableData(cn, dialect, table, model, updateCondition,
int myCount = updatePropertyTableData(cn, dialect, table, model, updateCondition,
updateInfo.getProperty(), updateInfo.getPropertyModelMapper(),
originalPropertyValues[updateInfo.getPropertyIndex()], updatePropertyValue, null, false,
expressionEvaluationContext);
if (myUpdateCount == 0)
insertPersistenceOperation.insertPropertyTableData(cn, dialect, table, model, updateObj,
if (myCount == 0)
myCount = insertPersistenceOperation.insertPropertyTableData(cn, dialect, table, model, updateObj,
updateInfo.getProperty(), updateInfo.getPropertyModelMapper(),
new Object[] { updatePropertyValue }, null, expressionEvaluationContext);
if (propertyUpdated == false && myCount > 0)
propertyUpdated = true;
}
}
// 仅修改了复合属性值时也应该返回1
if (count < 0 && propertyUpdated)
count = 1;
return count;
}

View File

@ -246,6 +246,8 @@ public abstract class AbstractController
if (traceException)
operationMessage.setThrowable(throwable);
operationMessage.setData(messageArgs);
WebUtils.setOperationMessage(request, operationMessage);
}

View File

@ -80,6 +80,8 @@ public class DataController extends AbstractSchemaModelController
{
public static final byte[] BLOB_TO_BYTES_PLACEHOLDER = new byte[] { 0x00 };
public static final String PARAM_IGNORE_DUPLICATION = "ignoreDuplication";
@Autowired
private PersistenceManager persistenceManager;
@ -427,7 +429,9 @@ public class DataController extends AbstractSchemaModelController
@ResponseBody
public ResponseEntity<OperationMessage> saveEdit(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model springModel, @PathVariable("schemaId") String schemaId,
@PathVariable("tableName") String tableName) throws Throwable
@PathVariable("tableName") String tableName,
@RequestParam(value = PARAM_IGNORE_DUPLICATION, required = false) final Boolean ignoreDuplication)
throws Throwable
{
final Object originalDataParam = getParamObj(request, "originalData");
final Object dataParam = getParamMap(request, "data");
@ -446,8 +450,7 @@ public class DataController extends AbstractSchemaModelController
int count = persistenceManager.update(cn, model, originalData, data, false);
if (count > 1)
throw new DuplicateRecordException(1, count);
checkDuplicateRecord(1, count, ignoreDuplication);
ResponseEntity<OperationMessage> responseEntity = buildOperationMessageSaveCountResponseEntity(request,
count);
@ -464,7 +467,9 @@ public class DataController extends AbstractSchemaModelController
@ResponseBody
public ResponseEntity<OperationMessage> delete(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model springModel, @PathVariable("schemaId") String schemaId,
@PathVariable("tableName") String tableName) throws Throwable
@PathVariable("tableName") String tableName,
@RequestParam(value = PARAM_IGNORE_DUPLICATION, required = false) final Boolean ignoreDuplication)
throws Throwable
{
final Object dataParam = getParamObj(request, "data");
@ -481,8 +486,7 @@ public class DataController extends AbstractSchemaModelController
int count = persistenceManager.delete(cn, model, datas);
if (count > datas.length)
throw new DuplicateRecordException(datas.length, count);
checkDuplicateRecord(datas.length, count, ignoreDuplication);
ResponseEntity<OperationMessage> responseEntity = buildOperationMessageDeleteCountResponseEntity(
request, count);
@ -718,7 +722,9 @@ public class DataController extends AbstractSchemaModelController
public ResponseEntity<OperationMessage> saveEditSinglePropValue(HttpServletRequest request,
HttpServletResponse response, org.springframework.ui.Model springModel,
@PathVariable("schemaId") String schemaId, @PathVariable("tableName") String tableName,
@RequestParam("propertyPath") final String propertyPath) throws Throwable
@RequestParam("propertyPath") final String propertyPath,
@RequestParam(value = PARAM_IGNORE_DUPLICATION, required = false) final Boolean ignoreDuplication)
throws Throwable
{
final Object dataParam = getParamMap(request, "data");
final Object propValueParam = getParamMap(request, "propValue");
@ -741,8 +747,7 @@ public class DataController extends AbstractSchemaModelController
int count = persistenceManager.updateSinglePropValue(cn, model, data, propertyPathInfo, propValue);
if (count > 1)
throw new DuplicateRecordException(1, count);
checkDuplicateRecord(1, count, ignoreDuplication);
ResponseEntity<OperationMessage> responseEntity = buildOperationMessageSaveCountResponseEntity(request,
count);
@ -1101,7 +1106,9 @@ public class DataController extends AbstractSchemaModelController
public ResponseEntity<OperationMessage> saveEditMultiplePropValueElement(HttpServletRequest request,
HttpServletResponse response, org.springframework.ui.Model springModel,
@PathVariable("schemaId") String schemaId, @PathVariable("tableName") String tableName,
@RequestParam("propertyPath") final String propertyPath) throws Throwable
@RequestParam("propertyPath") final String propertyPath,
@RequestParam(value = PARAM_IGNORE_DUPLICATION, required = false) final Boolean ignoreDuplication)
throws Throwable
{
final Object dataParam = getParamMap(request, "data");
final Object propValueElementParam = getParamMap(request, "propValue");
@ -1123,8 +1130,7 @@ public class DataController extends AbstractSchemaModelController
int count = persistenceManager.updateMultiplePropValueElement(cn, model, data, propertyPathInfo,
propValueElement);
if (count > 1)
throw new DuplicateRecordException(1, count);
checkDuplicateRecord(1, count, ignoreDuplication);
ResponseEntity<OperationMessage> responseEntity = buildOperationMessageSaveCountResponseEntity(request,
count);
@ -1142,15 +1148,18 @@ public class DataController extends AbstractSchemaModelController
public ResponseEntity<OperationMessage> deleteMultiplePropValueElements(HttpServletRequest request,
HttpServletResponse response, org.springframework.ui.Model springModel,
@PathVariable("schemaId") String schemaId, @PathVariable("tableName") String tableName,
@RequestParam("propertyPath") final String propertyPath) throws Throwable
@RequestParam("propertyPath") final String propertyPath,
@RequestParam(value = PARAM_IGNORE_DUPLICATION, required = false) final Boolean ignoreDuplication)
throws Throwable
{
final Object dataParam = getParamMap(request, "data");
final Object propValueElementsParam = getParamMap(request, "propValueElements");
int count = new ReturnExecutor<Integer>(request, response, springModel, schemaId, tableName, false)
ResponseEntity<OperationMessage> responseEntity = new ReturnExecutor<ResponseEntity<OperationMessage>>(request,
response, springModel, schemaId, tableName, false)
{
@Override
protected Integer execute(HttpServletRequest request, HttpServletResponse response,
protected ResponseEntity<OperationMessage> execute(HttpServletRequest request, HttpServletResponse response,
org.springframework.ui.Model springModel, Schema schema, Model model) throws Throwable
{
Connection cn = getConnection();
@ -1163,17 +1172,16 @@ public class DataController extends AbstractSchemaModelController
int count = persistenceManager.deleteMultiplePropValueElement(cn, model, data, propertyPathInfo,
propValueElements);
if (count > propValueElements.length)
throw new DuplicateRecordException(propValueElements.length, count);
checkDuplicateRecord(propValueElements.length, count, ignoreDuplication);
return count;
ResponseEntity<OperationMessage> responseEntity = buildOperationMessageDeleteCountResponseEntity(
request, count);
responseEntity.getBody().setData(count);
return responseEntity;
}
}.execute();
ResponseEntity<OperationMessage> responseEntity = buildOperationMessageDeleteCountResponseEntity(request,
count);
responseEntity.getBody().setData(count);
return responseEntity;
}
@ -1416,6 +1424,13 @@ public class DataController extends AbstractSchemaModelController
return model.getProperty(propertyPath);
}
protected void checkDuplicateRecord(int expectedCount, int actualCount, Boolean ignoreDuplication)
throws DuplicateRecordException
{
if (actualCount > expectedCount && !Boolean.TRUE.equals(ignoreDuplication))
throw new DuplicateRecordException(expectedCount, actualCount);
}
/**
* 判断请求是否是客户端操作
*

View File

@ -22,9 +22,11 @@ saveSuccess=\u4FDD\u5B58\u6210\u529F
saveSuccess.withCount=\u4FDD\u5B58\u6210\u529F\uFF0C\u4FDD\u5B58\u4E86[{0}]\u6761\u8BB0\u5F55
saveSuccess.noChange=\u4FDD\u5B58\u5FFD\u7565\uFF0C\u672A\u505A\u4EFB\u4F55\u4FEE\u6539
saveFail.zeroCount=\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BB0\u5F55\u672A\u627E\u5230
save.continueIgnoreDuplicationTemplate=\u662F\u5426\u8981\u7EE7\u7EED\u4FDD\u5B58\u5168\u90E8[#{actual}]\u6761\u8BB0\u5F55\uFF1F\uFF08\u671F\u671B[#{expected}]\u6761\uFF0C\u5B9E\u9645[#{actual}]\u6761\uFF09
deleteSuccess=\u5220\u9664\u6210\u529F
deleteSuccess.withCount=\u5220\u9664\u6210\u529F\uFF0C\u5220\u9664\u4E86[{0}]\u6761\u8BB0\u5F55
deleteFail.zeroCount=\u5220\u9664\u5931\u8D25\uFF0C\u8BB0\u5F55\u672A\u627E\u5230
delete.continueIgnoreDuplicationTemplate=\u662F\u5426\u8981\u7EE7\u7EED\u5220\u9664\u5168\u90E8[#{actual}]\u6761\u8BB0\u5F55\uFF1F\uFF08\u671F\u671B[#{expected}]\u6761\uFF0C\u5B9E\u9645[#{actual}]\u6761\uFF09
uploadSuccess=\u4E0A\u4F20\u6210\u529F
pleaseSelectOnlyOneRow=\u8BF7\u4EC5\u9009\u62E9\u4E00\u6761\u8BB0\u5F55
pleaseSelectAtLeastOneRow=\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u6761\u8BB0\u5F55

View File

@ -106,17 +106,22 @@ boolean batchSet = ("true".equalsIgnoreCase(getStringValue(request, "batchSet"))
var thisForm = this;
var param = $.extend(formParam, {"data" : data, "originalData" : pageObj.originalData});
$(thisForm).modelform("disableOperation");
$.ajax(pageObj.url(pageObj.submitAction),
pageObj.ajaxSubmitForHandleDuplication(pageObj.submitAction, param, "<fmt:message key='save.continueIgnoreDuplicationTemplate' />",
{
"data" : param,
"success" : function(operationMessage)
beforeSend : function()
{
$(thisForm).modelform("disableOperation");
},
success : function(operationMessage)
{
var $form = $(thisForm);
var batchSubmit = $form.modelform("isBatchSubmit");
var isDialogPinned = $form.modelform("isDialogPinned");
$form.modelform("enableOperation");
pageObj.refreshParent();
if(batchSubmit)
;
else
@ -130,28 +135,19 @@ boolean batchSet = ("true".equalsIgnoreCase(getStringValue(request, "batchSet"))
if(pageParam && pageParam.afterSave)
close = (pageParam.afterSave(operationMessage.data) != false);
var pageObjParent = pageObj.parent();
if(pageObjParent && pageObjParent.refresh)
pageObjParent.refresh();
if(close && !isDialogPinned)
pageObj.close();
}
},
"complete" : function()
error : function()
{
var $form = $(thisForm);
var batchSubmit = $form.modelform("isBatchSubmit");
$form.modelform("enableOperation");
var batchSubmit = $form.modelform("isBatchSubmit");
if(batchSubmit)
{
var pageObjParent = pageObj.parent();
if(pageObjParent && pageObjParent.refresh)
pageObjParent.refresh();
}
pageObj.refreshParent();
}
});
}

View File

@ -121,9 +121,12 @@ List<PropertyPathDisplayName> conditionSource = (List<PropertyPathDisplayName>)r
{
var data = {"data" : rows};
$.post(pageObj.url("delete"), data, function()
pageObj.ajaxSubmitForHandleDuplication("delete", data, "<fmt:message key='delete.continueIgnoreDuplicationTemplate' />",
{
pageObj.refresh();
"success" : function()
{
pageObj.refresh();
}
});
}
});

View File

@ -117,17 +117,22 @@ boolean isPrivatePropertyModel = ModelUtils.isPrivatePropertyModelTail(propertyP
var thisForm = this;
var param = $.extend(formParam, { "data" : pageObj.data, "propertyPath" : pageObj.propertyPath, "propValue" : propValue });
$(thisForm).modelform("disableOperation");
$.ajax(pageObj.url(pageObj.submitAction),
pageObj.ajaxSubmitForHandleDuplication(pageObj.submitAction, param, "<fmt:message key='save.continueIgnoreDuplicationTemplate' />",
{
"data" : param,
"success" : function(operationMessage)
beforeSend : function()
{
$(thisForm).modelform("disableOperation");
},
success : function(operationMessage)
{
var $form = $(thisForm);
var batchSubmit = $form.modelform("isBatchSubmit");
var isDialogPinned = $form.modelform("isDialogPinned");
$form.modelform("enableOperation");
pageObj.refreshParent();
if(batchSubmit)
;
else
@ -139,28 +144,19 @@ boolean isPrivatePropertyModel = ModelUtils.isPrivatePropertyModelTail(propertyP
if(pageParam && pageParam.afterSave)
close = (pageParam.afterSave(operationMessage.data) != false);
var pageObjParent = pageObj.parent();
if(pageObjParent && pageObjParent.refresh)
pageObjParent.refresh();
if(close && !isDialogPinned)
pageObj.close();
}
},
"dataType" : "json",
"complete" : function()
error : function()
{
var $form = $(thisForm);
var batchSubmit = $form.modelform("isBatchSubmit");
$form.modelform("enableOperation");
var batchSubmit = $form.modelform("isBatchSubmit");
if(batchSubmit)
{
var pageObjParent = pageObj.parent();
if(pageObjParent && pageObjParent.refresh)
pageObjParent.refresh();
}
pageObj.refreshParent();
}
});
}

View File

@ -322,9 +322,13 @@ boolean isPrivatePropertyModel = ModelUtils.isPrivatePropertyModelTail(propertyP
else
{
var options = pageObj.buildActionOptions(property, propertyModel, {"propValueElements" : rows}, null);
$.post(pageObj.url("deleteMultiplePropValueElements"), options.data, function()
pageObj.ajaxSubmitForHandleDuplication("deleteMultiplePropValueElements", options.data, "<fmt:message key='delete.continueIgnoreDuplicationTemplate' />",
{
pageObj.refresh();
"success" : function()
{
pageObj.refresh();
}
});
}
}

View File

@ -4,6 +4,7 @@
*/
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="org.datagear.web.controller.DataController" %>
<%@ include file="../../include/page_js_obj.jsp" %>
<script type="text/javascript">
(function(pageObj)
@ -52,6 +53,60 @@
}
$.model.on(this.schemaId, tableName, callback);
},
/**
* 提交可处理重复记录的请求。
*/
ajaxSubmitForHandleDuplication : function(action, data, messageTemplate, ajaxOptions, ignoreDuplication)
{
var errorCallback = function(jqXHR, textStatus, errorThrown)
{
var callResult = undefined;
if(ajaxOptions.error)
callResult = ajaxOptions.error.call(this, jqXHR, textStatus, errorThrown);
if(!ignoreDuplication)
{
var operationMessage = $.getResponseJson(jqXHR);
if(operationMessage.code = "error.DuplicateRecordException")
{
var expected = (operationMessage.data && operationMessage.data.length > 0 ? operationMessage.data[0] : "???");
var actual = (operationMessage.data && operationMessage.data.length > 0 ? operationMessage.data[1] : "???");
var message = messageTemplate.replace( /#\{expected\}/g, "" + expected).replace( /#\{actual\}/g, "" + actual);
pageObj.confirm(message,
{
"confirm" : function()
{
$.closeTip();
pageObj.ajaxSubmitForHandleDuplication(action, data, messageTemplate, ajaxOptions, true);
},
"cancel" : function()
{
$.closeTip();
}
});
}
}
return callResult;
};
var url;
if(ignoreDuplication)
url = pageObj.url("", action, "<%=DataController.PARAM_IGNORE_DUPLICATION%>=true");
else
url = pageObj.url(action);
var options = $.extend({}, ajaxOptions, { data : data, error : errorCallback, type : "POST" });
$.ajax(url, options);
}
};

View File

@ -163,6 +163,19 @@ pageObj.clientOperation = undefined;
pageObj.open(pageObj.url("downloadSinglePropertyValueFile"), options);
};
pageObj.refreshParent = function()
{
var pageObjParent = pageObj.parent();
if(pageObjParent && pageObjParent.refresh && $.isFunction(pageObjParent.refresh))
{
try
{
pageObjParent.refresh();
}
catch(e){}
}
};
})
(${pageId});
</script>