فهرست منبع

优化saveOrUpdate

zhouhao 6 سال پیش
والد
کامیت
481ad838cf

+ 2 - 5
hsweb-system/hsweb-system-dynamic-form/hsweb-system-dynamic-form-api/src/main/java/org/hswebframework/web/service/form/DynamicFormOperationService.java

@@ -14,8 +14,6 @@ import java.util.List;
  * @since 3.0
  */
 public interface DynamicFormOperationService {
-    String idProperty = "id";
-
     <T> PagerResult<T> selectPager(String formId, QueryParamEntity paramEntity);
 
     <T> T selectSingle(String formId, QueryParamEntity paramEntity);
@@ -30,13 +28,12 @@ public interface DynamicFormOperationService {
 
     <T> T insert(String formId, T entity);
 
-    <T> T saveOrUpdate(String formId, T entity);
-
     int delete(String formId, DeleteParamEntity paramEntity);
 
     int deleteById(String formId, Object id);
 
-    <T>T selectById(String formId, Object id);
+    <T> T saveOrUpdate(String formId, T data);
 
+    <T> T selectById(String formId, Object id);
 
 }

+ 82 - 15
hsweb-system/hsweb-system-dynamic-form/hsweb-system-dynamic-form-local/src/main/java/org/hswebframework/web/service/form/simple/SimpleDynamicFormOperationService.java

@@ -1,12 +1,16 @@
 package org.hswebframework.web.service.form.simple;
 
 import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
 import org.hswebframework.ezorm.core.Delete;
 import org.hswebframework.ezorm.core.Insert;
 import org.hswebframework.ezorm.core.Update;
 import org.hswebframework.ezorm.rdb.RDBDatabase;
 import org.hswebframework.ezorm.rdb.RDBQuery;
 import org.hswebframework.ezorm.rdb.RDBTable;
+import org.hswebframework.ezorm.rdb.meta.RDBColumnMetaData;
+import org.hswebframework.ezorm.rdb.meta.RDBTableMetaData;
+import org.hswebframework.web.BusinessException;
 import org.hswebframework.web.NotFoundException;
 import org.hswebframework.web.bean.FastBeanCopier;
 import org.hswebframework.web.commons.entity.PagerResult;
@@ -34,6 +38,7 @@ import java.util.Objects;
 
 @Service("dynamicFormOperationService")
 @Transactional(rollbackFor = Throwable.class)
+@Slf4j
 public class SimpleDynamicFormOperationService implements DynamicFormOperationService {
 
     @Autowired
@@ -55,6 +60,16 @@ public class SimpleDynamicFormOperationService implements DynamicFormOperationSe
         return database.getTable(form.getDatabaseTableName());
     }
 
+    protected RDBDatabase getDatabase(String formId) {
+        DynamicFormEntity form = dynamicFormService.selectByPk(formId);
+        if (null == form || Boolean.FALSE.equals(form.getDeployed())) {
+            throw new NotFoundException("表单不存在");
+        }
+        return StringUtils.isEmpty(form.getDataSourceId()) ?
+                databaseRepository.getDefaultDatabase() :
+                databaseRepository.getDatabase(form.getDataSourceId());
+    }
+
     @Override
     @Transactional(readOnly = true)
     @SneakyThrows
@@ -118,22 +133,68 @@ public class SimpleDynamicFormOperationService implements DynamicFormOperationSe
         return entity;
     }
 
-    @Override
+    private String getIdProperty(RDBTableMetaData tableMetaData) {
+        return tableMetaData.getColumns()
+                .stream()
+                .filter(RDBColumnMetaData::isPrimaryKey)
+                .findFirst()
+                .map(RDBColumnMetaData::getAlias)
+                .orElseThrow(() -> new BusinessException("表[" + tableMetaData.getComment() + "]未设置主键字段"));
+    }
+
     @SneakyThrows
-    public <T> T saveOrUpdate(String formId, T entity) {
+    protected <T> Object getExistingDataId(String formId, T data) {
+        RDBTable<T> table = getTable(formId);
+        String triggerName = "check-data-existing";
+
+        boolean useTrigger = table.getMeta().triggerIsSupport(triggerName);
+        String idProperty = getIdProperty(table.getMeta());
+
+        if (useTrigger) {
+            Map<String, Object> triggerContext = new HashMap<>();
+            triggerContext.put("table", table);
+            triggerContext.put("database", getDatabase(formId));
+            triggerContext.put("data", data);
+            Object result = table.getMeta().on(triggerName, triggerContext);
+            if (result instanceof String) {
+                return result;
+            }
+            if (result instanceof Map) {
+                Object id = ((Map) result).get(idProperty);
+                if (id == null) {
+                    log.error("触发器返回了数据:{},但是不包含主键字段:{}", data, idProperty);
+                    throw new BusinessException("数据错误,请联系管理员");
+                }
+                return id;
+            }
+        } else {
+            Map<String, Object> mapData = FastBeanCopier.copy(data, new HashMap<>());
+            Object id = mapData.get(idProperty);
+            if (null == id) {
+                return null;
+            }
+            Object existing = selectSingle(formId, QueryParamEntity.single(idProperty, id).includes(idProperty));
+            if (null != existing) {
+                mapData = FastBeanCopier.copy(data, new HashMap<>());
+                return mapData.get(idProperty);
+            }
+        }
 
-        Map<String, Object> map = FastBeanCopier.copy(entity, new HashMap<>(), FastBeanCopier.include(idProperty));
+        return null;
 
-        Object id = map.get(idProperty);
-        if (id == null) {
-            return insert(formId, entity);
-        }
-        int total = getTable(formId).createQuery().where(idProperty, id).total();
-        if (total > 0) {
-            return updateById(formId, String.valueOf(id), entity);
-        }
+    }
 
-        return insert(formId, entity);
+    @Override
+    @SneakyThrows
+    public <T> T saveOrUpdate(String formId, T data) {
+        Objects.requireNonNull(formId, "表单ID不能为空");
+        Object id = getExistingDataId(formId, data);
+        if (null == id) {
+            insert(formId, data);
+        } else {
+            updateById(formId, id, data);
+        }
+        return data;
     }
 
     @Override
@@ -152,7 +213,9 @@ public class SimpleDynamicFormOperationService implements DynamicFormOperationSe
     public int deleteById(String formId, Object id) {
         Objects.requireNonNull(id, "主键不能为空");
         RDBTable table = getTable(formId);
-        return table.createDelete().where(idProperty, id).exec();
+        return table.createDelete()
+                .where(getIdProperty(table.getMeta()), id)
+                .exec();
     }
 
     @Override
@@ -160,7 +223,9 @@ public class SimpleDynamicFormOperationService implements DynamicFormOperationSe
     public <T> T selectById(String formId, Object id) {
         Objects.requireNonNull(id, "主键不能为空");
         RDBTable<T> table = getTable(formId);
-        return table.createQuery().where(idProperty, id).single();
+        return table.createQuery()
+                .where(getIdProperty(table.getMeta()), id)
+                .single();
     }
 
     @Override
@@ -168,10 +233,12 @@ public class SimpleDynamicFormOperationService implements DynamicFormOperationSe
     public <T> T updateById(String formId, Object id, T data) {
         Objects.requireNonNull(id, "主键不能为空");
         RDBTable<T> table = getTable(formId);
+
         eventPublisher.publishEvent(new FormDataUpdateBeforeEvent<>(formId, table, data, id));
+
         table.createUpdate()
                 .set(data)
-                .where(idProperty, id)
+                .where(getIdProperty(table.getMeta()), id)
                 .exec();
         return data;
     }