@@ -1,6 +1,7 @@ | |||||
package cc.smtweb.framework.core; | package cc.smtweb.framework.core; | ||||
import cc.smtweb.framework.core.cache.CacheManager; | import cc.smtweb.framework.core.cache.CacheManager; | ||||
import cc.smtweb.framework.core.db.impl.DatabaseUtil; | |||||
import cc.smtweb.framework.core.mvc.controller.scan.ApplicationScanner; | import cc.smtweb.framework.core.mvc.controller.scan.ApplicationScanner; | ||||
import cc.smtweb.framework.core.systask.TaskStartEvent; | import cc.smtweb.framework.core.systask.TaskStartEvent; | ||||
import cc.smtweb.framework.core.systask.WebStartedEvent; | import cc.smtweb.framework.core.systask.WebStartedEvent; | ||||
@@ -24,10 +25,13 @@ public class CoreApplicationStartedListener implements ApplicationListener<Appli | |||||
applicationContext.publishEvent(new TaskStartEvent()); | applicationContext.publishEvent(new TaskStartEvent()); | ||||
//包扫描 | //包扫描 | ||||
ApplicationScanner.scan(applicationContext); | ApplicationScanner.scan(applicationContext); | ||||
//初始化数据库 | |||||
new DatabaseUtil(true, false).checkDb(); | |||||
//初始化缓存 | //初始化缓存 | ||||
CacheManager.getIntance().init(); | CacheManager.getIntance().init(); | ||||
// 通知 controller 正式使用 | // 通知 controller 正式使用 | ||||
applicationContext.publishEvent(new WebStartedEvent()); | applicationContext.publishEvent(new WebStartedEvent()); | ||||
System.out.println("start end============="); | |||||
} | } | ||||
} | } |
@@ -109,9 +109,11 @@ public abstract class AbstractCache<T extends Serializable> implements ISwCache< | |||||
*/ | */ | ||||
protected void init() { | protected void init() { | ||||
if (RedisManager.getInstance().exists(getIdent())) { | if (RedisManager.getInstance().exists(getIdent())) { | ||||
log.info("从redis同步缓存!(" + getTitle() + ")"); | |||||
//从缓存服务器下载到本地 | //从缓存服务器下载到本地 | ||||
syncCache(); | syncCache(); | ||||
} else if (!lazy) { | } else if (!lazy) { | ||||
log.info("从数据库同步缓存!(" + getTitle() + ")"); | |||||
refresh(); | refresh(); | ||||
} | } | ||||
} | } | ||||
@@ -96,6 +96,11 @@ public interface SwEnum { | |||||
this.defaultValue = defaultValue; | this.defaultValue = defaultValue; | ||||
this.editor = editor; | this.editor = editor; | ||||
} | } | ||||
public String getSqlTypeCreate() { | |||||
if (dataLength > 0) return sqlType + "(" + dataLength + ")"; | |||||
return sqlType; | |||||
} | |||||
} | } | ||||
/** | /** | ||||
@@ -139,6 +144,36 @@ public interface SwEnum { | |||||
} | } | ||||
/** | /** | ||||
* 数据字段类型Bean | |||||
*/ | |||||
class IndexTypeBean extends AbstractEnum.StrEnumBean { | |||||
public String fullName; | |||||
public IndexTypeBean(String value, String name, String fullName) { | |||||
super(value, name); | |||||
this.fullName = fullName; | |||||
} | |||||
} | |||||
class IndexType extends AbstractEnum<String, IndexTypeBean> { | |||||
public static IndexType instance = new IndexType(); | |||||
public static IndexTypeBean PK = instance.addEnum("P", "主键", "prim-key"); | |||||
public static IndexTypeBean I = instance.addEnum("I", "一般索引", ""); | |||||
public static IndexTypeBean U = instance.addEnum("U", "唯一索引", "unique"); | |||||
@Override | |||||
protected IndexTypeBean buildBean(String value, String name) { | |||||
return null; | |||||
} | |||||
public IndexTypeBean addEnum(String value, String name, String fullName) { | |||||
final IndexTypeBean bean = new IndexTypeBean(value, name, fullName); | |||||
mapAll.put(value, bean); | |||||
return bean; | |||||
} | |||||
} | |||||
/** | |||||
* 表类型 | * 表类型 | ||||
*/ | */ | ||||
class TableType extends IntEnum { | class TableType extends IntEnum { | ||||
@@ -149,7 +184,6 @@ public interface SwEnum { | |||||
public static AbstractEnum.IntEnumBean TYPE_CODE = instance.addEnum(2, "编码表"); | public static AbstractEnum.IntEnumBean TYPE_CODE = instance.addEnum(2, "编码表"); | ||||
public static AbstractEnum.IntEnumBean TYPE_ABSTRACT = instance.addEnum(3, "虚拟抽象表"); | public static AbstractEnum.IntEnumBean TYPE_ABSTRACT = instance.addEnum(3, "虚拟抽象表"); | ||||
public static AbstractEnum.IntEnumBean TYPE_VIEW = instance.addEnum(4, "视图"); | public static AbstractEnum.IntEnumBean TYPE_VIEW = instance.addEnum(4, "视图"); | ||||
} | } | ||||
/** | /** | ||||
@@ -1,13 +1,11 @@ | |||||
package cc.smtweb.framework.core.db; | package cc.smtweb.framework.core.db; | ||||
import cc.smtweb.framework.core.db.impl.BaseBean; | |||||
import cc.smtweb.framework.core.db.impl.DefaultEntity; | import cc.smtweb.framework.core.db.impl.DefaultEntity; | ||||
import cc.smtweb.framework.core.db.jdbc.IdGenerator; | import cc.smtweb.framework.core.db.jdbc.IdGenerator; | ||||
import cc.smtweb.framework.core.db.jdbc.JdbcEngine; | import cc.smtweb.framework.core.db.jdbc.JdbcEngine; | ||||
import cc.smtweb.framework.core.mvc.controller.scan.BeanManager; | import cc.smtweb.framework.core.mvc.controller.scan.BeanManager; | ||||
import cc.smtweb.framework.core.util.SpringUtil; | import cc.smtweb.framework.core.util.SpringUtil; | ||||
import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||
import org.springframework.jdbc.core.JdbcTemplate; | |||||
import org.springframework.jdbc.core.ResultSetExtractor; | import org.springframework.jdbc.core.ResultSetExtractor; | ||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; | ||||
@@ -38,4 +38,9 @@ public class ModelDatabaseCache extends AbstractCache<ModelDatabase> { | |||||
public final ModelDatabase getByName(String key) { | public final ModelDatabase getByName(String key) { | ||||
return getByKey(mk, key); | return getByKey(mk, key); | ||||
} | } | ||||
public final String getName(long id) { | |||||
ModelDatabase db = get(id); | |||||
return db != null ? db.getName() : ""; | |||||
} | |||||
} | } |
@@ -0,0 +1,556 @@ | |||||
package cc.smtweb.framework.core.db.impl; | |||||
import cc.smtweb.framework.core.common.SwEnum; | |||||
import cc.smtweb.framework.core.db.DbEngine; | |||||
import cc.smtweb.framework.core.db.cache.ModelTableCache; | |||||
import cc.smtweb.framework.core.db.vo.ModelField; | |||||
import cc.smtweb.framework.core.db.vo.ModelIndex; | |||||
import cc.smtweb.framework.core.db.vo.ModelTable; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.apache.commons.lang3.StringUtils; | |||||
import java.text.MessageFormat; | |||||
import java.util.*; | |||||
/** | |||||
* Created with IntelliJ IDEA. | |||||
* User: AKhh | |||||
* Date: 12-12-21 下午2:41 | |||||
* 启动时检查数据库并自动建表、字段、索引; | |||||
*/ | |||||
@Slf4j | |||||
@SuppressWarnings("UnusedDeclaration") | |||||
public class DatabaseUtil { | |||||
private static final int INDEX_NAME_MAX_LENGTH = 30; //索引名称长度; | |||||
private static final String MODULE = DatabaseUtil.class.getName(); | |||||
private IDatabaseInfo databaseInfo; | |||||
//是否需要根据实体定义清理数据库字段 | |||||
private boolean is_db_clean_field = false; | |||||
//是否需要根据实体定义清理数据库表 | |||||
private boolean is_db_clean_table = false; | |||||
public DatabaseUtil(boolean is_db_clean_field, boolean is_db_clean_table) { | |||||
this.is_db_clean_field = is_db_clean_field; | |||||
this.is_db_clean_table = is_db_clean_table; | |||||
this.databaseInfo = new DefaultDatabaseInfoImpl(); | |||||
} | |||||
/** | |||||
* 检测数据库结构和配置是否一致,根据配置增加表或字段信息; | |||||
*/ | |||||
public void checkDb() { | |||||
UtilTime timer = new UtilTime(); | |||||
timer.setLog(true); | |||||
timer.timerString("Start - 开始获取连接的数据库的元信息!"); | |||||
this.databaseInfo.printDatabaseInfo(); | |||||
// get ALL tables from this database | |||||
Map<String, IDatabaseInfo.TableCheckInfo> tableNames = this.databaseInfo.getTables(); | |||||
//Set<IDatabaseInfo.TableCheckInfo> fkTableNames = (tableNames == null ? null : new HashSet<IDatabaseInfo.TableCheckInfo>(tableNames.values())); | |||||
//Set<IDatabaseInfo.TableCheckInfo> indexTableNames = (tableNames == null ? null : new HashSet<IDatabaseInfo.TableCheckInfo>(tableNames.values())); | |||||
if (tableNames == null) { | |||||
String message = "不能从数据库获取表名信息,将被跳过..."; | |||||
log.error(message, MODULE); | |||||
return; | |||||
} | |||||
timer.timerString("已从数据库获取所有的表名信息!"); | |||||
// get ALL column info, put into hashmap by table name | |||||
Map<String, List<IDatabaseInfo.ColumnCheckInfo>> colInfo = this.databaseInfo.getColumnInfo(tableNames); | |||||
if (colInfo == null) { | |||||
String message = "不能从数据库获取字段列信息,将被跳过..."; | |||||
log.error(message, MODULE); | |||||
return; | |||||
} | |||||
timer.timerString("已获取所有的数据库字段列信息。"); | |||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> | |||||
timer.timerString("开始检查表,列定义信息....................................."); | |||||
Collection<ModelTable> ModelTableDefList = ModelTableCache.getInstance().getAll(); | |||||
Iterator<ModelTable> ModelTableIter = ModelTableDefList.iterator(); | |||||
int curEnt = 0; | |||||
int totalEnt = ModelTableDefList.size(); | |||||
List<ModelTable> entitiesAdded = new LinkedList<>(); // 数据库中没有的实体, 通过建表 | |||||
// 数据库中有表, 也有对应的实体 | |||||
Map<IDatabaseInfo.TableCheckInfo, ModelTable> entitiesExist = new HashMap<>(); | |||||
while (ModelTableIter.hasNext()) { | |||||
curEnt++; | |||||
ModelTable entity = ModelTableIter.next(); | |||||
String entMessage = "(" + timer.timeSinceLast() + "ms) Checking #" + curEnt + "/" + totalEnt + " Entity " + entity.getName(); | |||||
log.info(entMessage, MODULE); | |||||
String k = entity.getName(); //表名 | |||||
// -make sure all entities have a corresponding table | |||||
if (tableNames.containsKey(k)) { | |||||
IDatabaseInfo.TableCheckInfo table = tableNames.remove(k); | |||||
entitiesExist.put(table, entity); | |||||
if (colInfo != null) { | |||||
List<String> delCols = new ArrayList<>(); | |||||
Map<String, ModelField> fieldColNames = new HashMap<>(); | |||||
for (int fnum = 0, len = entity.getFields().size(); fnum < len; fnum++) { | |||||
ModelField field = entity.getFields().get(fnum); | |||||
fieldColNames.put(field.getName().toUpperCase(), field); // XML读出来是小写,数据库读取来是大写. | |||||
} | |||||
List<IDatabaseInfo.ColumnCheckInfo> colList = colInfo.get(entity.getName()); | |||||
int numCols = 0; | |||||
if (colList != null) { | |||||
for (; numCols < colList.size(); numCols++) { | |||||
IDatabaseInfo.ColumnCheckInfo ccInfo = colList.get(numCols); | |||||
ccInfo.columnName = ccInfo.columnName.toUpperCase(); | |||||
// -list all columns that do not have a corresponding field | |||||
if (fieldColNames.containsKey(ccInfo.columnName)) { | |||||
ModelField field = fieldColNames.remove(ccInfo.columnName); | |||||
SwEnum.DataTypeBean modelFieldType = SwEnum.DataType.instance.getByValue(field.getDataType()); | |||||
if (modelFieldType != null) { | |||||
// make sure each corresponding column is of the correct type | |||||
if (!ccInfo.typeName.equalsIgnoreCase(modelFieldType.sqlType)) { | |||||
String message = "警告: 表[" + entity.getName() + "]字段[" + ccInfo.columnName + "] 字段类型不一致:::数据库:[" + ccInfo.typeName + "], " + | |||||
"实体定义:[" + modelFieldType.sqlType + "]!"; | |||||
log.error(message, MODULE); | |||||
} | |||||
if (modelFieldType.dataLength != -1 && ccInfo.columnSize != -1 && modelFieldType.dataLength != ccInfo.columnSize) { | |||||
String message = "警告: 表[" + entity.getName() + "]字段[" + ccInfo.columnName + "] 字段长度不一致:::数据库:[" + ccInfo.columnSize + "], " + | |||||
"实体定义:[" + modelFieldType.dataLength + "]!"; | |||||
log.debug(message, MODULE); | |||||
} | |||||
/*if (decimalDigits != -1 && decimalDigits != ccInfo.decimalDigits) { | |||||
String message = "警告: 表[" + entity.getName() + "]字段[" + ccInfo.columnName + "] 小数位数不一致:::数据库:[" + ccInfo.decimalDigits + "], " + | |||||
"实体定义:[" + decimalDigits + "]!"; | |||||
log.debug(message, MODULE); | |||||
}*/ | |||||
} else { | |||||
String message = "警告: 表[" + entity.getName() + "]字段[" + ccInfo.columnName + "] 字段类型定义错误[" + field.getDataType() + "]!"; | |||||
log.error(message, MODULE); | |||||
} | |||||
} else { | |||||
String message = "表\"" + entity.getName() + "\"字段\"" + ccInfo.columnName + "\"没有定义!"; | |||||
log.debug(message, MODULE); | |||||
if (is_db_clean_field) { | |||||
delCols.add(ccInfo.columnName); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
// -display message if number of table columns does not match number of entity fields | |||||
if (!is_db_clean_field) { | |||||
if (numCols != entity.getFields().size()) { | |||||
String message = "表[" + entity.getName() + "]定义了" + entity.getFields().size() + "个字段,但数据库有" + numCols + "个字段!"; | |||||
log.debug(message, MODULE); | |||||
} | |||||
} else if (delCols.size() > 0) { | |||||
String errMsg = dropColumn(entity, delCols); | |||||
String message; | |||||
if (errMsg != null && errMsg.length() > 0) { | |||||
message = "清理字段出错,表:\"" + entity.getName() + "\": " + errMsg; | |||||
log.error(message, MODULE); | |||||
} else { | |||||
message = "清理字段成功,表:\"" + entity.getName() + "\""; | |||||
log.debug(message, MODULE); | |||||
} | |||||
} | |||||
// -list all fields that do not have a corresponding column | |||||
for (String colName : fieldColNames.keySet()) { | |||||
ModelField field = fieldColNames.get(colName); | |||||
String message = "Field \"" + field.getName() + "\" of entity \"" + entity.getName() + "\" is missing its corresponding column \"" + field.getName() + "\""; | |||||
log.debug(message, MODULE); | |||||
// add the column | |||||
String errMsg = addColumn(entity, field); | |||||
if (errMsg != null && errMsg.length() > 0) { | |||||
message = "加字段出错,表:\"" + entity.getName() + "\".\"" + field.getName() + "\": " + errMsg; | |||||
log.error(message, MODULE); | |||||
} else { | |||||
message = "加字段成功,表:\"" + entity.getName() + "\".\"" + field.getName() + "\""; | |||||
log.debug(message, MODULE); | |||||
} | |||||
} | |||||
//修复主键 | |||||
if (StringUtils.isEmpty(table.pk)) { | |||||
String errMsg = addPk(entity); | |||||
String message; | |||||
if (errMsg != null && errMsg.length() > 0) { | |||||
message = "修复主键出错,表:\"" + entity.getName() + "\": " + errMsg; | |||||
log.error(message, MODULE); | |||||
} else { | |||||
message = "修复主键成功,表:\"" + entity.getName() + "\""; | |||||
log.debug(message, MODULE); | |||||
} | |||||
} | |||||
} | |||||
} else { | |||||
String message = "数据库没有找到表\"" + entity.getName() + "\""; | |||||
log.debug(message, MODULE); | |||||
// create the table | |||||
String errMsg = createTable(entity); | |||||
if (StringUtils.isNotEmpty(errMsg)) { | |||||
message = "建表\"" + entity.getName() + "\"出错: " + errMsg; | |||||
log.error(message, MODULE); | |||||
} else { | |||||
entitiesAdded.add(entity); | |||||
message = "建表成功\"" + entity.getName() + "\""; | |||||
log.debug(message, MODULE); | |||||
} | |||||
} | |||||
} | |||||
timer.timerString("After Individual Table/Column Check"); | |||||
// -list all tables that do not have a corresponding entity | |||||
Iterator<String> tableNamesIter = tableNames.keySet().iterator(); | |||||
while (tableNamesIter != null && tableNamesIter.hasNext()) { | |||||
String tableName = tableNamesIter.next(); | |||||
if (!is_db_clean_table) { | |||||
String message = "表\"" + tableName + "\"没有实体定义文件!"; | |||||
log.debug(message, MODULE); | |||||
} else { | |||||
String message, errMsg = dropTable(tableNames.get(tableName).catalog, tableName); | |||||
if (StringUtils.isNotEmpty(errMsg)) { | |||||
message = "删除表\"" + tableName + "\"出错: " + errMsg; | |||||
log.error(message, MODULE); | |||||
} else { | |||||
message = "删除表成功\"" + tableName + "\""; | |||||
log.debug(message, MODULE); | |||||
} | |||||
} | |||||
} | |||||
// for each newly added table, add declared indexes | |||||
for (ModelTable curEntity : entitiesAdded) { | |||||
String indErrMsg = this.createDeclaredIndices(curEntity); | |||||
if (indErrMsg != null && indErrMsg.length() > 0) { | |||||
String message = "建索引出错,表\"" + curEntity.getName() + "\": " + indErrMsg; | |||||
log.error(message, MODULE); | |||||
} else { | |||||
String message = "建索引成功,表 \"" + curEntity.getName() + "\""; | |||||
log.debug(message, MODULE); | |||||
} | |||||
} | |||||
// 补充索引 get ALL column info, put into hashmap by table name | |||||
Map<String, Map<String, Set<String>>> tableIndexListMap = this.databaseInfo.getIndexInfo(entitiesExist.keySet(), true); | |||||
for (ModelTable entity : entitiesExist.values()) { | |||||
// 实体未定义索引. | |||||
if (entity.getIndexes().isEmpty()) | |||||
continue; | |||||
// get existing index map for this table | |||||
Map<String, Set<String>> exists_indexes = tableIndexListMap.get(entity.getName()); | |||||
Set<String> setEnabled = new HashSet<>();//有效的索引 | |||||
for (ModelIndex mi: entity.getIndexes()) { | |||||
if (SwEnum.IndexType.PK.value.equalsIgnoreCase(mi.getType())) continue; | |||||
Set<String> dbfields = null; | |||||
String indexName = getDbIndexName(entity, mi); | |||||
if (exists_indexes != null) dbfields = exists_indexes.get(indexName); | |||||
setEnabled.add(mi.getName()); | |||||
if (!hasDiff(mi.getFields(), dbfields)) {//没有变化,不管 | |||||
continue; | |||||
} | |||||
if (dbfields != null) deleteDeclaredIndex(entity.getSchemaTableName(), indexName); | |||||
// 建数据库已经有表的不存在的索引 | |||||
String indErrMsg = this.createDeclaredIndex(entity, mi); | |||||
if (indErrMsg != null && indErrMsg.length() > 0) { | |||||
String message = "建索引出错,表:\"" + entity.getName() + "\".\"" + mi.getName() + "\": " + indErrMsg; | |||||
log.error(message, MODULE); | |||||
} else { | |||||
String message = "Created declared index [" + mi.getName() + "] for entity \"" + entity.getName() + "\""; | |||||
log.debug(message, MODULE); | |||||
} | |||||
} | |||||
for (String indexName : exists_indexes.keySet()) { | |||||
if (!setEnabled.contains(indexName)) deleteDeclaredIndex(entity.getSchemaTableName(), indexName); | |||||
} | |||||
} | |||||
timer.timerString("数据库结构检测和同步完成!"); | |||||
} | |||||
//顺序不一致,也要重建 | |||||
private boolean hasDiff(String fields1, Set<String> fields2) { | |||||
if (StringUtils.isEmpty(fields1) || fields2 == null) return true; | |||||
String[] f1 = fields1.split(","); | |||||
if (fields1.length() != fields2.size()) return true; | |||||
int n = 0; | |||||
for (String s : fields2) { | |||||
if (!s.equalsIgnoreCase(f1[n].toLowerCase())) return true; | |||||
n++; | |||||
} | |||||
return false; | |||||
} | |||||
/** | |||||
* 建表 | |||||
* | |||||
* @param entity ModelTable | |||||
* @return String 错误消息 | |||||
*/ | |||||
public String createTable(ModelTable entity) { | |||||
if (entity == null) { | |||||
return "ModelTable was null and is required to create a table"; | |||||
} | |||||
// entity.setCurCreated(true); | |||||
StringBuilder sqlBuf = new StringBuilder("CREATE TABLE "); | |||||
sqlBuf.append(entity.getSchemaTableName()); | |||||
sqlBuf.append(" ("); | |||||
for (ModelField field : entity.getFields()) { | |||||
SwEnum.DataTypeBean type = SwEnum.DataType.instance.getByValue(field.getDataType()); | |||||
if (type == null) { | |||||
return "Field type [" + field.getDataType() + "] not found for field [" + field.getName() + "] of entity [" + entity.getName() + "], not creating table."; | |||||
} | |||||
sqlBuf.append(field.getName()); | |||||
sqlBuf.append(" "); | |||||
sqlBuf.append(type.getSqlTypeCreate()); | |||||
if (field.getName().equalsIgnoreCase(entity.getIdField())) { | |||||
sqlBuf.append(" NOT NULL , "); | |||||
} else { | |||||
if (!StringUtils.isEmpty(field.getDefaultValue())) { | |||||
sqlBuf.append(" DEFAULT '").append(field.getDefaultValue()).append("'"); | |||||
} | |||||
sqlBuf.append(" , "); | |||||
} | |||||
} | |||||
String pkName = "PK_" + entity.getName(); | |||||
if (pkName.length() > INDEX_NAME_MAX_LENGTH) { | |||||
pkName = pkName.substring(0, INDEX_NAME_MAX_LENGTH); | |||||
} | |||||
sqlBuf.append("CONSTRAINT "); | |||||
sqlBuf.append(pkName); | |||||
sqlBuf.append(" PRIMARY KEY ("); | |||||
sqlBuf.append(entity.getIdField()); | |||||
sqlBuf.append("))"); | |||||
try { | |||||
DbEngine.getInstance().update(sqlBuf.toString()); | |||||
} catch (Exception e) { | |||||
return e.getMessage(); | |||||
} | |||||
addTableComment(entity); | |||||
//加上字段注解: | |||||
for (ModelField field : entity.getFields()) { | |||||
addColumnComment(entity, field); | |||||
} | |||||
return null; | |||||
} | |||||
public String addColumn(ModelTable entity, ModelField field) { | |||||
if (entity == null || field == null) { | |||||
return "ModelTable or ModelField where null, cannot add column"; | |||||
} | |||||
SwEnum.DataTypeBean type = SwEnum.DataType.instance.getByValue(field.getDataType()); | |||||
if (type == null) { | |||||
return "Field type not found for field [" + field.getName() + "] of entity [" + entity.getName() + "], not adding column."; | |||||
} | |||||
StringBuilder sqlBuf = new StringBuilder(128); | |||||
sqlBuf.append(MessageFormat.format("ALTER TABLE {0} ADD {1} {2}", entity.getSchemaTableName(), field.getName(), type.getSqlTypeCreate())); | |||||
if (!StringUtils.isEmpty(field.getDefaultValue())) { | |||||
sqlBuf.append(" DEFAULT '").append(field.getDefaultValue()).append("'"); | |||||
} | |||||
log.debug("正在增加字段" + entity.getName() + "." + field.getName()); | |||||
try { | |||||
DbEngine.getInstance().update(sqlBuf.toString()); | |||||
} catch (Exception e) { | |||||
sqlBuf.setLength(0); | |||||
sqlBuf.append("ALTER TABLE ").append(entity.getSchemaTableName()).append(" ADD COLUMN ").append(field.getName()).append(" ").append(type.getSqlTypeCreate()); | |||||
if (StringUtils.isNotEmpty(field.getDefaultValue())) { | |||||
sqlBuf.append(" DEFAULT '").append(field.getDefaultValue()).append("'"); | |||||
} | |||||
try { | |||||
DbEngine.getInstance().update(sqlBuf.toString()); | |||||
} catch (Exception e1) { | |||||
return e.getMessage(); | |||||
} | |||||
} | |||||
//加上字段注解: | |||||
addColumnComment(entity, field); | |||||
return null; | |||||
} | |||||
public String addPk(ModelTable entity) { | |||||
if (entity == null) { | |||||
return "实体为null!"; | |||||
} | |||||
if (StringUtils.isEmpty(entity.getPkFieldName())) { | |||||
return "表" + entity.getName() + "没有定义主键!"; | |||||
} | |||||
String pkName = "PK_" + entity.getName(); | |||||
if (pkName.length() > INDEX_NAME_MAX_LENGTH) { | |||||
pkName = pkName.substring(0, INDEX_NAME_MAX_LENGTH); | |||||
} | |||||
StringBuilder sqlBuf = new StringBuilder(128); | |||||
sqlBuf.append("ALTER TABLE ").append(entity.getSchemaTableName()).append(" ADD CONSTRAINT ") | |||||
.append(pkName).append(" PRIMARY KEY (").append(entity.getIdField()).append(")"); | |||||
try { | |||||
DbEngine.getInstance().update(sqlBuf.toString()); | |||||
} catch (Exception e) { | |||||
return e.getMessage(); | |||||
} | |||||
return null; | |||||
} | |||||
//删除表列 | |||||
public String dropColumn(ModelTable entity, List<String> delCols) { | |||||
if (delCols.isEmpty()) return null; | |||||
StringBuilder sql = new StringBuilder(128); | |||||
sql.append("ALTER TABLE " + entity.getSchemaTableName()).append("\nDROP COLUMN("); | |||||
for (String col : delCols) { | |||||
sql.append(col).append(","); | |||||
} | |||||
log.debug("正在删除表字段" + entity.getName()); | |||||
try { | |||||
DbEngine.getInstance().update(sql.substring(0, sql.length() - 1) + ")"); | |||||
} catch (Exception e) { | |||||
return e.getMessage(); | |||||
} | |||||
return null; | |||||
} | |||||
//删除表 | |||||
public String dropTable(String catalog, String tableName) { | |||||
if (StringUtils.isNotEmpty(catalog)) tableName = catalog + "." + tableName; | |||||
log.debug("正在删除表" + tableName); | |||||
try { | |||||
DbEngine.getInstance().update("drop table " + tableName); | |||||
} catch (Exception e) { | |||||
return e.getMessage(); | |||||
} | |||||
return null; | |||||
} | |||||
private String addTableComment(ModelTable entity) { | |||||
log.debug("正在增加表说明" + entity.getName()); | |||||
try { | |||||
DbEngine.getInstance().update("ALTER TABLE " + entity.getSchemaTableName() + " COMMENT '" + entity.getTitle() + "'"); | |||||
} catch (Exception e) { | |||||
return e.getMessage(); | |||||
} | |||||
return null; | |||||
} | |||||
private String addColumnComment(ModelTable entity, ModelField field) { | |||||
log.debug("正在增加字段说明" + entity.getName() + "." + field.getName()); | |||||
// comment on column BASE_ENUM.DESCRIPTION is | |||||
SwEnum.DataTypeBean type = SwEnum.DataType.instance.getByValue(field.getDataType()); | |||||
if (type == null) return null; | |||||
try { | |||||
String defValue = StringUtils.isNotEmpty(field.getDefaultValue()) ? "'" + field.getDefaultValue() + "'" : ""; | |||||
String dvs = StringUtils.isNotEmpty(field.getDefaultValue()) ? " DEFAULT '" + field.getDefaultValue() + "'" : ""; | |||||
String sql = "ALTER TABLE " + entity.getSchemaTableName() + " MODIFY COLUMN " + field.getName() + " " + type.getSqlTypeCreate() + dvs + " COMMENT '" + field.getRemark() + "'"; | |||||
DbEngine.getInstance().update(sql); | |||||
} catch (Exception e) { | |||||
return e.getMessage(); | |||||
} | |||||
return null; | |||||
} | |||||
/** | |||||
* 建立索引 | |||||
* | |||||
* @param entity 实体定义对象; | |||||
* @return 错误消息,处理正确会返回null | |||||
*/ | |||||
public String createDeclaredIndices(ModelTable entity) { | |||||
if (entity == null) { | |||||
return "ModelTable was null and is required to create declared indices for a table"; | |||||
} | |||||
StringBuilder retMsgsBuffer = new StringBuilder(); | |||||
// go through the indexes to see if any need to be added | |||||
Iterator<ModelIndex> indexesIter = entity.getIndexes().iterator(); | |||||
for (ModelIndex modelIndex : entity.getIndexes()) { | |||||
String retMsg = createDeclaredIndex(entity, modelIndex); | |||||
if (retMsg != null && retMsg.length() > 0) { | |||||
if (retMsgsBuffer.length() > 0) { | |||||
retMsgsBuffer.append("\n"); | |||||
} | |||||
retMsgsBuffer.append(retMsg); | |||||
} | |||||
} | |||||
if (retMsgsBuffer.length() > 0) { | |||||
return retMsgsBuffer.toString(); | |||||
} else { | |||||
return null; | |||||
} | |||||
} | |||||
private String createDeclaredIndex(ModelTable entity, ModelIndex modelIndex) { | |||||
log.debug("正在创建索引" + entity.getName() + "." + modelIndex.getName() + "....."); | |||||
String createIndexSql = makeIndexClause(entity, modelIndex); | |||||
if (StringUtils.isEmpty(createIndexSql)) return null; | |||||
try { | |||||
DbEngine.getInstance().update(createIndexSql); | |||||
} catch (Exception sqle) { | |||||
return "SQL Exception while executing the following:\n" + createIndexSql + "\nError was: " + sqle.toString(); | |||||
} | |||||
return null; | |||||
} | |||||
/** | |||||
* 构造建立索引的脚本 | |||||
* | |||||
* @param entity 实体 | |||||
* @param modelIndex 索引定义; | |||||
* @return 脚本; | |||||
*/ | |||||
private String makeIndexClause(ModelTable entity, ModelIndex modelIndex) { | |||||
if (SwEnum.IndexType.PK.value.equalsIgnoreCase(modelIndex.getType())) return null; | |||||
SwEnum.IndexTypeBean type = SwEnum.IndexType.instance.getByValue(modelIndex.getType()); | |||||
return "CREATE " + (SwEnum.IndexType.U.value.equalsIgnoreCase(modelIndex.getType()) ? SwEnum.IndexType.U.fullName : "") + | |||||
" INDEX " + entity.getAbbr() + "_" + getDbIndexName(entity, modelIndex) + | |||||
" ON " + entity.getSchemaTableName() + " (" + modelIndex.getFields() + ")"; | |||||
} | |||||
/** | |||||
* 删除已经实体已经定义的索引 | |||||
* | |||||
* @param entity 实体 | |||||
* @return sql | |||||
*/ | |||||
private String deleteDeclaredIndices(ModelTable entity) { | |||||
if (entity == null) { | |||||
return "ModelTable was null and is required to delete foreign keys indices for a table"; | |||||
} | |||||
StringBuilder retMsgsBuffer = new StringBuilder(); | |||||
// go through the relationships to see if any foreign keys need to be added | |||||
for (ModelIndex modelIndex : entity.getIndexes()) { | |||||
String retMsg = deleteDeclaredIndex(entity, modelIndex); | |||||
if (retMsg != null && retMsg.length() > 0) { | |||||
if (retMsgsBuffer.length() > 0) { | |||||
retMsgsBuffer.append("\n"); | |||||
} | |||||
retMsgsBuffer.append(retMsg); | |||||
} | |||||
} | |||||
if (retMsgsBuffer.length() > 0) { | |||||
return retMsgsBuffer.toString(); | |||||
} else { | |||||
return null; | |||||
} | |||||
} | |||||
/** | |||||
* 删除已经定义的索引 | |||||
* | |||||
* @param entity 实体 | |||||
* @param modelIndex 索引; | |||||
* @return sql | |||||
*/ | |||||
private String deleteDeclaredIndex(ModelTable entity, ModelIndex modelIndex) { | |||||
String deleteIndexSql = "DROP INDEX " + entity.getSchemaTableName() + "." + getDbIndexName(entity, modelIndex); | |||||
try { | |||||
DbEngine.getInstance().update(deleteIndexSql); | |||||
} catch (Exception sqle) { | |||||
return "SQL Exception while executing the following:\n" + deleteIndexSql + "\nError was: " + sqle.toString(); | |||||
} | |||||
return null; | |||||
} | |||||
private String deleteDeclaredIndex(String tableName, String indexName) { | |||||
String deleteIndexSql = "DROP INDEX " + indexName + " ON " + tableName; | |||||
try { | |||||
DbEngine.getInstance().update(deleteIndexSql); | |||||
} catch (Exception sqle) { | |||||
return "SQL Exception while executing the following:\n" + deleteIndexSql + "\nError was: " + sqle.toString(); | |||||
} | |||||
return null; | |||||
} | |||||
private String getDbIndexName(ModelTable entity, ModelIndex modelIndex) { | |||||
return entity.getAbbr() + "_" + modelIndex; | |||||
} | |||||
} |
@@ -20,13 +20,13 @@ public interface IDatabaseInfo { | |||||
Map<String, Map<String, Set<String>>> getIndexInfo(Collection<TableCheckInfo> tableNames, boolean include_nounique); | Map<String, Map<String, Set<String>>> getIndexInfo(Collection<TableCheckInfo> tableNames, boolean include_nounique); | ||||
public static class TableCheckInfo { | |||||
class TableCheckInfo { | |||||
public String tableName; | public String tableName; | ||||
public String catalog; | public String catalog; | ||||
public String pk; | public String pk; | ||||
} | } | ||||
public static class ColumnCheckInfo { | |||||
class ColumnCheckInfo { | |||||
public String tableName; | public String tableName; | ||||
public String columnName; | public String columnName; | ||||
public String typeName; | public String typeName; | ||||
@@ -0,0 +1,158 @@ | |||||
package cc.smtweb.framework.core.db.impl; | |||||
/** | |||||
* Created with IntelliJ IDEA. | |||||
* User: AKhh | |||||
* Date: 12-12-21 下午10:04 | |||||
* To change this template use File | Settings | File Templates. | |||||
*/ | |||||
public class UtilTime { | |||||
long realStartTime; | |||||
long startTime; | |||||
long lastMessageTime; | |||||
String lastMessage = null; | |||||
boolean log = false; | |||||
/** | |||||
* Default constructor. Starts the timer. | |||||
*/ | |||||
public UtilTime() { | |||||
lastMessageTime = realStartTime = startTime = System.currentTimeMillis(); | |||||
lastMessage = "Begin"; | |||||
} | |||||
/** | |||||
* Creates a string with information including the passed message, the last passed message and the time since the last call, and the time since the beginning | |||||
* | |||||
* @param message A message to put into the timer String | |||||
* @return A String with the timing information, the timer String | |||||
*/ | |||||
public String timerString(String message) { | |||||
return timerString(message, this.getClass().getName()); | |||||
} | |||||
/** | |||||
* Creates a string with information including the passed message, the last passed message and the time since the last call, and the time since the beginning | |||||
* | |||||
* @param message A message to put into the timer String | |||||
* @param module The debug/log module/thread to use, can be null for root module | |||||
* @return A String with the timing information, the timer String | |||||
*/ | |||||
public String timerString(String message, String module) { | |||||
// time this call to avoid it interfering with the main timer | |||||
long tsStart = System.currentTimeMillis(); | |||||
String retString = "[[" + message + "- total:" + secondsSinceStart() + | |||||
",since last(" + ((lastMessage.length() > 20) ? (lastMessage.substring(0, 17) + "..."): lastMessage) + "):" + | |||||
secondsSinceLast() + "]]"; | |||||
lastMessage = message; | |||||
if (log) { | |||||
System.out.println(retString); | |||||
} | |||||
// have lastMessageTime come as late as possible to just time what happens between calls | |||||
lastMessageTime = System.currentTimeMillis(); | |||||
// update startTime to disclude the time this call took | |||||
startTime += (lastMessageTime - tsStart); | |||||
return retString; | |||||
} | |||||
/** | |||||
* Returns the number of seconds since the timer started | |||||
* | |||||
* @return The number of seconds since the timer started | |||||
*/ | |||||
public double secondsSinceStart() { | |||||
return ((double) timeSinceStart()) / 1000.0; | |||||
} | |||||
/** | |||||
* Returns the number of seconds since the last time timerString was called | |||||
* | |||||
* @return The number of seconds since the last time timerString was called | |||||
*/ | |||||
public double secondsSinceLast() { | |||||
return ((double) timeSinceLast()) / 1000.0; | |||||
} | |||||
/** | |||||
* Returns the number of milliseconds since the timer started | |||||
* | |||||
* @return The number of milliseconds since the timer started | |||||
*/ | |||||
public long timeSinceStart() { | |||||
long currentTime = System.currentTimeMillis(); | |||||
return currentTime - startTime; | |||||
} | |||||
/** | |||||
* Returns the number of milliseconds since the last time timerString was called | |||||
* | |||||
* @return The number of milliseconds since the last time timerString was called | |||||
*/ | |||||
public long timeSinceLast() { | |||||
long currentTime = System.currentTimeMillis(); | |||||
return currentTime - lastMessageTime; | |||||
} | |||||
/** | |||||
* Sets the value of the log member, denoting whether log output is off or not | |||||
* | |||||
* @param log The new value of log | |||||
*/ | |||||
public void setLog(boolean log) { | |||||
this.log = log; | |||||
} | |||||
/** | |||||
* Gets the value of the log member, denoting whether log output is off or not | |||||
* | |||||
* @return The value of log | |||||
*/ | |||||
public boolean getLog() { | |||||
return log; | |||||
} | |||||
/** | |||||
* Creates a string with information including the passed message, the time since the last call, | |||||
* and the time since the beginning. This version allows an integer level to be specified to | |||||
* improve readability of the output. | |||||
* | |||||
* @param level Integer specifying how many levels to indent the timer string so the output can be more easily read through nested method calls. | |||||
* @param message A message to put into the timer String | |||||
* @return A String with the timing information, the timer String | |||||
*/ | |||||
public String timerString(int level, String message) { | |||||
StringBuffer retStringBuf = new StringBuffer(); | |||||
for (int i = 0; i < level; i++) { | |||||
retStringBuf.append("| "); | |||||
} | |||||
retStringBuf.append("("); | |||||
String timeSinceStartStr = String.valueOf(timeSinceStart()); | |||||
// int spacecount = 5 - timeSinceStartStr.length(); | |||||
// for (int i=0; i < spacecount; i++) { retStringBuf.append(' '); } | |||||
retStringBuf.append(timeSinceStartStr + ","); | |||||
String timeSinceLastStr = String.valueOf(timeSinceLast()); | |||||
// spacecount = 4 - timeSinceLastStr.length(); | |||||
// for (int i=0; i < spacecount; i++) { retStringBuf.append(' '); } | |||||
retStringBuf.append(timeSinceLastStr); | |||||
retStringBuf.append(")"); | |||||
int spacecount = 12 + (2 * level) - retStringBuf.length(); | |||||
for (int i = 0; i < spacecount; i++) { | |||||
retStringBuf.append(' '); | |||||
} | |||||
retStringBuf.append(message); | |||||
// lastMessageTime = (new Date()).getTime(); | |||||
lastMessageTime = System.currentTimeMillis(); | |||||
// lastMessage = message; | |||||
return retStringBuf.toString(); | |||||
} | |||||
} |
@@ -4,6 +4,8 @@ import cc.smtweb.framework.core.annotation.SwTable; | |||||
import cc.smtweb.framework.core.common.AbstractEnum; | import cc.smtweb.framework.core.common.AbstractEnum; | ||||
import cc.smtweb.framework.core.common.IntEnum; | import cc.smtweb.framework.core.common.IntEnum; | ||||
import cc.smtweb.framework.core.common.SwEnum; | import cc.smtweb.framework.core.common.SwEnum; | ||||
import cc.smtweb.framework.core.db.DbEngine; | |||||
import cc.smtweb.framework.core.db.cache.ModelDatabaseCache; | |||||
import cc.smtweb.framework.core.db.cache.ModelTableCache; | import cc.smtweb.framework.core.db.cache.ModelTableCache; | ||||
import cc.smtweb.framework.core.db.impl.DefaultEntity; | import cc.smtweb.framework.core.db.impl.DefaultEntity; | ||||
import cc.smtweb.framework.core.util.JsonUtil; | import cc.smtweb.framework.core.util.JsonUtil; | ||||
@@ -16,11 +18,11 @@ import java.util.List; | |||||
@SwTable(value = "ASP_MODEL_TABLE") | @SwTable(value = "ASP_MODEL_TABLE") | ||||
public class ModelTable extends DefaultEntity { | public class ModelTable extends DefaultEntity { | ||||
public final static String DEF_DB_NAME = "sys"; | |||||
public final static String ENTITY_NAME = "ASP_MODEL_TABLE"; | public final static String ENTITY_NAME = "ASP_MODEL_TABLE"; | ||||
/*冗余*/ | /*冗余*/ | ||||
private String idField; | private String idField; | ||||
private String dbName; | |||||
private List<ModelField> fields = new ArrayList<>(); | private List<ModelField> fields = new ArrayList<>(); | ||||
private List<ModelIndex> indexes = new ArrayList<>(); | private List<ModelIndex> indexes = new ArrayList<>(); | ||||
@@ -151,7 +153,7 @@ public class ModelTable extends DefaultEntity { | |||||
} | } | ||||
public String getDbName() { | public String getDbName() { | ||||
return dbName; | |||||
return ModelDatabaseCache.getInstance().getName(getDbId()); | |||||
} | } | ||||
public List<ModelField> getFields() { | public List<ModelField> getFields() { | ||||
@@ -184,7 +186,7 @@ public class ModelTable extends DefaultEntity { | |||||
} | } | ||||
public String fullName() { | public String fullName() { | ||||
return dbName + '.' + getName(); | |||||
return getDbName() + '.' + getName(); | |||||
} | } | ||||
public void addIndex(ModelIndex modelIndex) { | public void addIndex(ModelIndex modelIndex) { | ||||
@@ -270,10 +272,15 @@ public class ModelTable extends DefaultEntity { | |||||
this.fields = bean.fields; | this.fields = bean.fields; | ||||
this.indexes = bean.indexes; | this.indexes = bean.indexes; | ||||
this.caches = bean.caches; | this.caches = bean.caches; | ||||
ModelIndex i = findPrimaryIndex(); | ModelIndex i = findPrimaryIndex(); | ||||
if (i != null) { | if (i != null) { | ||||
this.idField = i.getFields(); | this.idField = i.getFields(); | ||||
} | } | ||||
} | } | ||||
public String getSchemaTableName() { | |||||
String dbName = getDbName(); | |||||
if (StringUtils.isEmpty(dbName) || dbName.equals(DEF_DB_NAME)) return getName(); | |||||
return DbEngine.getInstance().getDbSchema() + "_" + dbName + "." + getName(); | |||||
} | |||||
} | } |
@@ -1,191 +0,0 @@ | |||||
package cc.smtweb.system.bpm.web.design.db; | |||||
import cc.smtweb.framework.core.common.R; | |||||
import cc.smtweb.framework.core.common.SwMap; | |||||
import cc.smtweb.framework.core.annotation.SwBody; | |||||
import cc.smtweb.framework.core.annotation.SwParam; | |||||
import cc.smtweb.framework.core.annotation.SwService; | |||||
import cc.smtweb.framework.core.db.DbEngine; | |||||
import cc.smtweb.framework.core.db.cache.ModelDatabaseCache; | |||||
import cc.smtweb.framework.core.db.cache.ModelTableCache; | |||||
import cc.smtweb.framework.core.db.vo.ModelDatabase; | |||||
import cc.smtweb.framework.core.db.vo.ModelField; | |||||
import cc.smtweb.framework.core.db.vo.ModelTable; | |||||
import cc.smtweb.system.bpm.engine.ui.entity.vo.dataset.FzDatasetPropsVO; | |||||
import cc.smtweb.system.bpm.engine.ui.entity.vo.dataset.FzDatasetVO; | |||||
import cc.smtweb.system.bpm.engine.ui.entity.vo.dataset.FzFieldVO; | |||||
import cc.smtweb.system.bpm.engine.ui.entity.vo.widiget.UiControlPropsVO; | |||||
import cc.smtweb.system.bpm.util.CodeGenUtil; | |||||
import org.apache.commons.lang3.StringUtils; | |||||
import java.sql.ResultSetMetaData; | |||||
import java.sql.Types; | |||||
import java.util.*; | |||||
@SwService | |||||
public class DbQueryDatasetService { | |||||
@SwParam | |||||
private DbEngine dbEngine; | |||||
public R query(@SwBody SwMap body) { | |||||
String sql = body.readString("sql"); | |||||
if (StringUtils.isBlank(sql)) { | |||||
return R.error("sql参数为空"); | |||||
} | |||||
if(!sql.trim().toLowerCase().startsWith("select ")){ | |||||
return R.error("sql必须是查询语句"); | |||||
} | |||||
if (sql.endsWith(";")) { | |||||
return R.error("sql语句需要去掉结束符合';'"); | |||||
} | |||||
ModelDatabase modelDatabase = getModelDatabase(sql); | |||||
FzDatasetVO uiDataset = new FzDatasetVO(); | |||||
uiDataset.setType("fz-dataset"); | |||||
uiDataset.setProps(new FzDatasetPropsVO()); | |||||
dbEngine.query(sql + " limit 1", resultSet -> { | |||||
// 解析数据库中的库名 | |||||
ModelTable modelTable = null; | |||||
ResultSetMetaData rsmd = resultSet.getMetaData(); | |||||
int columnCount = rsmd.getColumnCount(); | |||||
List<FzFieldVO> fields = new ArrayList<>(); | |||||
String masterTableName = null; | |||||
String masterTableLabel = null; | |||||
for (int index = 1; index <= columnCount; ++index) { | |||||
FzFieldVO uiField = new FzFieldVO(); | |||||
UiControlPropsVO props = new UiControlPropsVO(); | |||||
uiField.setProps(props); | |||||
String fieldName = rsmd.getColumnName(index); | |||||
String name = rsmd.getColumnLabel(index); | |||||
int size = rsmd.getColumnDisplaySize(index); | |||||
uiField.setId(name); | |||||
props.put("fieldName", fieldName); | |||||
props.put("name", CodeGenUtil.underlineToHump(name)); | |||||
props.put("length", size); | |||||
switch (rsmd.getColumnType(index)) { | |||||
case Types.BIGINT: | |||||
uiField.setType("fz-field-long"); | |||||
props.put("dataType", "id"); | |||||
break; | |||||
case Types.INTEGER: | |||||
case Types.SMALLINT: | |||||
case Types.TINYINT: | |||||
uiField.setType("fz-field-int"); | |||||
props.put("dataType", "int"); | |||||
break; | |||||
case Types.CHAR: | |||||
case Types.NCHAR: | |||||
case Types.VARCHAR: | |||||
case Types.NVARCHAR: | |||||
uiField.setType("fz-field-string"); | |||||
props.put("dataType", "string"); | |||||
break; | |||||
case Types.FLOAT: | |||||
uiField.setType("fz-field-float"); | |||||
props.put("dataType", "float"); | |||||
break; | |||||
case Types.DATE: | |||||
case Types.TIME: | |||||
case Types.TIMESTAMP: | |||||
uiField.setType("fz-field-date"); | |||||
props.put("dataType", "date"); | |||||
break; | |||||
default: | |||||
throw new IllegalStateException("Unexpected value: " + rsmd.getColumnType(index)); | |||||
} | |||||
String tableName = rsmd.getTableName(index); | |||||
if (modelDatabase != null) { | |||||
modelTable = findModelTable(modelDatabase, modelTable, tableName); | |||||
if (modelTable != null) { | |||||
ModelField modelField = modelTable.findFieldByName(name); | |||||
if (modelField != null) { | |||||
props.put("label", modelField.getTitle()); | |||||
} | |||||
if (masterTableName == null) { | |||||
masterTableName = tableName; | |||||
masterTableLabel = modelTable.getTitle(); | |||||
} | |||||
} | |||||
} | |||||
if (masterTableName == null) { | |||||
masterTableName = tableName; | |||||
masterTableLabel = tableName; | |||||
} | |||||
fields.add(uiField); | |||||
} | |||||
uiDataset.getProps().setFields(fields.toArray(new FzFieldVO[0])); | |||||
uiDataset.getProps().setName(masterTableName); | |||||
uiDataset.getProps().setLabel(masterTableLabel); | |||||
return null; | |||||
}); | |||||
return R.success(uiDataset); | |||||
} | |||||
private ModelDatabase getModelDatabase(String sql) { | |||||
ModelDatabase modelDatabase = null; | |||||
String dbName = extractSqlDbName(sql); | |||||
Long modelId = dbEngine.queryLong("select model_id from sw_bpm.asp_model where model_key=? and model_type=1", dbName); | |||||
if (modelId != null) { | |||||
modelDatabase = ModelDatabaseCache.getInstance().get(modelId); | |||||
} | |||||
return modelDatabase; | |||||
} | |||||
private ModelTable findModelTable(ModelDatabase modelDatabase, ModelTable modelTable, String tableName) { | |||||
if (tableName != null) { | |||||
if (modelTable != null && tableName.equalsIgnoreCase(modelTable.getName())) { | |||||
return modelTable; | |||||
} | |||||
return ModelTableCache.getInstance().getByName(tableName); | |||||
} | |||||
return null; | |||||
} | |||||
private static final Set<String> KEYWORD_SET = new HashSet<String>(){{ | |||||
this.add("from"); | |||||
this.add("join"); | |||||
}}; | |||||
public static String extractSqlDbName(String sql) { | |||||
StringTokenizer st = new StringTokenizer(sql, " "); | |||||
int step = 0; | |||||
while (st.hasMoreTokens()) { | |||||
String token = st.nextToken(); | |||||
if (step == 0) { | |||||
if (KEYWORD_SET.contains(token.toLowerCase())) { | |||||
step = 1; | |||||
} | |||||
} else { | |||||
String[] ary = token.split("\\."); | |||||
if (ary.length > 1) { | |||||
return ary[0]; | |||||
} | |||||
step = 0; | |||||
} | |||||
} | |||||
return null; | |||||
} | |||||
} |
@@ -1,21 +0,0 @@ | |||||
package cc.smtweb.system.bpm.web.design.dict; | |||||
import cc.smtweb.framework.core.common.R; | |||||
import cc.smtweb.framework.core.annotation.SwParam; | |||||
import cc.smtweb.framework.core.annotation.SwService; | |||||
import cc.smtweb.framework.core.db.DbEngine; | |||||
import cc.smtweb.system.bpm.web.design.dict.entity.DictTypePO; | |||||
import java.util.List; | |||||
@SwService | |||||
public class DictTypeListService { | |||||
@SwParam | |||||
private DbEngine dbEngine; | |||||
public R list() { | |||||
List<DictTypePO> list = dbEngine.query("select dt_id, dt_name, dt_desc from sw_user.sys_dict_type order by dt_name", | |||||
DictTypePO.class); | |||||
return R.success(list); | |||||
} | |||||
} |
@@ -1,10 +0,0 @@ | |||||
package cc.smtweb.system.bpm.web.design.dict.entity; | |||||
import lombok.Data; | |||||
@Data | |||||
public class DictTypePO { | |||||
private Long dtId; | |||||
private String dtName; | |||||
private String dtDesc; | |||||
} |
@@ -263,10 +263,12 @@ public class ModelFormHelper { | |||||
for (long id : widgetIds) { | for (long id : widgetIds) { | ||||
ModelForm widgetForm = getFromCache(id); | ModelForm widgetForm = getFromCache(id); | ||||
if (widgetForm == null) throw new SwException("没有找到指定的控件定义!id=" + id); | if (widgetForm == null) throw new SwException("没有找到指定的控件定义!id=" + id); | ||||
SwMap w = new SwMap(); | |||||
widget.put("w" + id, w); | |||||
SwMap widgetOpts = parseFormOption(widgetForm.getOption()); | SwMap widgetOpts = parseFormOption(widgetForm.getOption()); | ||||
widget.put("service", widgetForm.getService()); | |||||
if (widgetOpts != null) widget.putAll(widgetOpts); | |||||
widget.put("define", widgetForm.getContent()); | |||||
w.put("service", widgetForm.getService()); | |||||
if (widgetOpts != null) w.putAll(widgetOpts); | |||||
w.put("define", widgetForm.getContent()); | |||||
} | } | ||||
//构建变量 | //构建变量 | ||||
SwMap mapVar = new SwMap(); | SwMap mapVar = new SwMap(); | ||||
@@ -1,131 +0,0 @@ | |||||
package cc.smtweb.system.bpm.web.design.model; | |||||
import cc.smtweb.framework.core.common.R; | |||||
import cc.smtweb.framework.core.annotation.SwBody; | |||||
import cc.smtweb.framework.core.annotation.SwParam; | |||||
import cc.smtweb.framework.core.annotation.SwService; | |||||
import cc.smtweb.framework.core.db.DbEngine; | |||||
import cc.smtweb.framework.core.db.cache.ModelDatabaseCache; | |||||
import cc.smtweb.framework.core.db.cache.ModelTableCache; | |||||
import cc.smtweb.framework.core.db.sqlbuilder.InsertSqlBuilder; | |||||
import cc.smtweb.framework.core.db.sqlbuilder.SqlBuilder; | |||||
import cc.smtweb.framework.core.db.sqlbuilder.UpdateSqlBuilder; | |||||
import cc.smtweb.framework.core.db.vo.ModelDatabase; | |||||
import cc.smtweb.framework.core.session.UserSession; | |||||
import cc.smtweb.framework.core.util.DateUtil; | |||||
import cc.smtweb.system.bpm.spring.dao.DatasetConfigDao; | |||||
import org.apache.commons.lang3.StringUtils; | |||||
//@Api(tags = "数据库设计") | |||||
@SwService | |||||
public class AspDbCardService { | |||||
@SwParam | |||||
private DbEngine dbEngine; | |||||
@SwParam | |||||
private ModelDatabaseCache bpmDbCache; | |||||
private ModelTableCache bpmTableCache; | |||||
@SwParam | |||||
protected DatasetConfigDao datasetConfigDao; | |||||
// @ApiOperation(value = "读取数据模型数据") | |||||
public R load(@SwParam("id") long id, UserSession us) { | |||||
ModelDatabase db = bpmDbCache.get(id); | |||||
if (db == null) { | |||||
return R.error("没有找到指定数据库定义(" + id + ")!"); | |||||
} | |||||
return R.success(db); | |||||
} | |||||
public R loadByKey(@SwParam("key") String key, @SwParam("type") String type, UserSession us) { | |||||
ModelDatabase db = bpmDbCache.getByName(key); | |||||
if (db == null) { | |||||
return R.error("没有找到指定数据库定义(" + key + ")!"); | |||||
} | |||||
return R.success(db); | |||||
} | |||||
private boolean isNullId(Long id) { | |||||
return id == null || id == 0; | |||||
} | |||||
// @ApiOperation(value = "创建数据模型") | |||||
public R save(@SwBody ModelDatabase modelPo, UserSession us) { | |||||
if (StringUtils.isBlank(modelPo.getName())) { | |||||
return R.error("库名不能为空"); | |||||
} | |||||
if (StringUtils.isBlank(modelPo.getTitle())) { | |||||
return R.error("库标题不能为空"); | |||||
} | |||||
modelPo.setUpdateAt(DateUtil.nowDateTimeLong()); | |||||
// 保存数据到部署表和部署历史表 | |||||
if (isNullId(modelPo.getId())) { | |||||
dbEngine.doTrans(() -> { | |||||
modelPo.setId(dbEngine.nextId()); | |||||
InsertSqlBuilder sqlBuilder = SqlBuilder.createInsert("sw_bpm.asp_model_database"); | |||||
sqlBuilder.add("db_id", modelPo.getId()) | |||||
.add("db_name", modelPo.getName()) | |||||
.add("db_title", modelPo.getTitle()) | |||||
.add("db_status", modelPo.getStatus()) | |||||
.add("db_version", modelPo.getVersion()) | |||||
.add("db_create_at", modelPo.getCreateAt()) | |||||
.add("db_update_at", modelPo.getUpdateAt()) | |||||
.add("db_create_uid", us.getUserId()) | |||||
.add("db_update_uid", us.getUserId()); | |||||
sqlBuilder.update(dbEngine); | |||||
return true; | |||||
}); | |||||
bpmDbCache.put(modelPo); | |||||
return R.success(modelPo.getId()); | |||||
} else { | |||||
modelPo.setVersion(modelPo.getVersion() + 1); | |||||
// 更新数据 | |||||
boolean r = dbEngine.doTrans(() -> { | |||||
UpdateSqlBuilder sqlBuilder = SqlBuilder.createUpdate("sw_bpm.asp_model_database"); | |||||
sqlBuilder.add("db_name", modelPo.getName()) | |||||
.add("db_title", modelPo.getTitle()) | |||||
.add("db_status", modelPo.getStatus()) | |||||
.add("db_version", modelPo.getVersion()) | |||||
.add("db_update_at", modelPo.getUpdateAt()) | |||||
.add("db_update_uid", us.getUserId()); | |||||
int ret = sqlBuilder.update(dbEngine); | |||||
if (ret > 0) { | |||||
bpmDbCache.put(modelPo); | |||||
return true; | |||||
} else { | |||||
bpmDbCache.reset(modelPo); | |||||
} | |||||
return false; | |||||
}); | |||||
return R.error("保存失败,未找到记录"); | |||||
} | |||||
} | |||||
// @ApiOperation(value = "删除数据模型") | |||||
public R delete(@SwBody ModelDatabase modelPo, UserSession us) { | |||||
String sql = "delete from sw_bpm.asp_model_database where model_id=?"; | |||||
if (dbEngine.update(sql, modelPo.getId()) > 0) { | |||||
bpmDbCache.remove(modelPo.getId()); | |||||
return R.success(); | |||||
} | |||||
return R.error("删除失败"); | |||||
} | |||||
} |
@@ -1,306 +0,0 @@ | |||||
package cc.smtweb.system.bpm.web.design.model; | |||||
import cc.smtweb.framework.core.common.R; | |||||
import cc.smtweb.framework.core.annotation.SwBody; | |||||
import cc.smtweb.framework.core.annotation.SwParam; | |||||
import cc.smtweb.framework.core.annotation.SwService; | |||||
import cc.smtweb.framework.core.db.DbEngine; | |||||
import cc.smtweb.framework.core.db.sqlbuilder.InsertSqlBuilder; | |||||
import cc.smtweb.framework.core.db.sqlbuilder.SqlBuilder; | |||||
import cc.smtweb.framework.core.db.sqlbuilder.UpdateSqlBuilder; | |||||
import cc.smtweb.framework.core.session.UserSession; | |||||
import cc.smtweb.framework.core.util.DateUtil; | |||||
import cc.smtweb.system.bpm.core.ui.entity.BpmPage; | |||||
import cc.smtweb.system.bpm.engine.AbstractLoader; | |||||
import cc.smtweb.system.bpm.engine.entity.AspModelPO; | |||||
import cc.smtweb.system.bpm.engine.entity.AspModelTreeVO; | |||||
import cc.smtweb.system.bpm.engine.process.loader.FlowLoader; | |||||
import cc.smtweb.system.bpm.engine.ui.loader.IPageRouter; | |||||
import cc.smtweb.system.bpm.engine.ui.loader.TreePageRouter; | |||||
import cc.smtweb.system.bpm.engine.ui.loader.UiMobileLoader; | |||||
import cc.smtweb.system.bpm.engine.ui.loader.UiPcLoader; | |||||
import cc.smtweb.system.bpm.spring.cache.BpmFlowCache; | |||||
import cc.smtweb.system.bpm.spring.cache.BpmPageCache; | |||||
import cc.smtweb.system.bpm.spring.dao.DatasetConfigDao; | |||||
import cc.smtweb.system.bpm.util.ITreeDataLevelHandler; | |||||
import cc.smtweb.system.bpm.util.TreeDataUtil; | |||||
import org.apache.commons.codec.digest.DigestUtils; | |||||
import org.apache.commons.lang3.StringUtils; | |||||
import java.util.List; | |||||
//@Api(tags = "数据模型") | |||||
@SwService | |||||
public class AspModelCardService { | |||||
@SwParam | |||||
private DbEngine dbEngine; | |||||
@SwParam | |||||
private BpmFlowCache bpmFlowCache; | |||||
@SwParam | |||||
private BpmPageCache bpmPageCache; | |||||
@SwParam | |||||
protected DatasetConfigDao datasetConfigDao; | |||||
// @ApiOperation(value = "读取数据模型数据") | |||||
public R load(@SwParam("id") long id, UserSession us) { | |||||
String sql = "select model_id, model_parent_id, model_mc_id, model_site_id, model_key, model_name, model_status, model_content, model_type, model_version, model_create_uid, model_update_uid, model_create_time, model_last_time from sw_bpm.asp_model" + | |||||
" where model_id=? and model_site_id=?"; | |||||
AspModelPO po = dbEngine.queryEntity(sql, AspModelPO.class, id, us.getSiteId()); | |||||
return R.success(po); | |||||
} | |||||
public R loadByKey(@SwParam("key") String key, @SwParam("type") String type, UserSession us) { | |||||
String sql = "select model_id, model_parent_id, model_mc_id, model_site_id, model_key, model_name, model_status, model_content, model_type, model_version, model_create_uid, model_update_uid, model_create_time, model_last_time from sw_bpm.asp_model" + | |||||
" where model_key=? and model_type=? and model_site_id=?"; | |||||
AspModelPO po = dbEngine.queryEntity(sql, AspModelPO.class, key, type, us.getSiteId()); | |||||
return R.success(po); | |||||
} | |||||
private boolean isNullId(Long id) { | |||||
return id == null || id == 0; | |||||
} | |||||
// @ApiOperation(value = "创建数据模型") | |||||
public R save(@SwParam("commit") boolean commit, @SwBody AspModelPO modelPo, UserSession us) { | |||||
String modelContent = modelPo.getModelContent(); | |||||
if (StringUtils.isBlank(modelContent)) { | |||||
return R.error("内容不能为空"); | |||||
} | |||||
if (commit) { | |||||
// 检查数据 | |||||
AbstractLoader loader = null; | |||||
switch (modelPo.getModelType()) { | |||||
case AspModelPO.TYPE_FLOW: | |||||
loader = new FlowLoader(); | |||||
break; | |||||
case AspModelPO.TYPE_UI_PC: | |||||
loader = new UiPcLoader(loadTree(modelPo.getModelId())); | |||||
break; | |||||
case AspModelPO.TYPE_UI_MOBILE: | |||||
loader = new UiMobileLoader(loadTree(modelPo.getModelId())); | |||||
break; | |||||
default: | |||||
return R.error("error model type: " + modelPo.getModelType()); | |||||
} | |||||
Object page = loader.load(modelContent); | |||||
if (loader.getLastError() != null) { | |||||
return R.error(loader.getLastError()).put("modelErrors", loader.getErrors()); | |||||
} | |||||
// 检测 modern + path | |||||
if (page instanceof BpmPage) { | |||||
// 检测和读取页面目录 | |||||
BpmPage uiPage = (BpmPage)page; | |||||
uiPage.setId(modelPo.getModelId()); | |||||
// uiPage.getForm().setKey(modelPo.getModelKey()); | |||||
// uiPage.getForm().setTitle(modelPo.getModelName()); | |||||
// uiPage.setParentId(modelPo.getModelParentId()); | |||||
List<String> names = datasetConfigDao.loadPagePath(uiPage, true); | |||||
modelPo.setModelFullName(String.join(".", names)); | |||||
} | |||||
modelPo.setModelStatus(0); | |||||
// 计算签名 | |||||
modelPo.setModelContentSign(DigestUtils.sha256Hex(modelContent) + "," + modelContent.length()); | |||||
} else { | |||||
modelPo.setModelStatus(-1); | |||||
} | |||||
modelPo.setModelLastTime(DateUtil.nowDateTimeLong()); | |||||
// 保存数据到部署表和部署历史表 | |||||
if (isNullId(modelPo.getModelId())) { | |||||
if (isNullId(modelPo.getModelMcId()) && isUiType(modelPo)) { | |||||
return R.error("页面缺少分类ID"); | |||||
} | |||||
dbEngine.doTrans(() -> { | |||||
modelPo.setModelId(dbEngine.nextId()); | |||||
modelPo.setModelVersion(commit ? 1 : 0); | |||||
InsertSqlBuilder sqlBuilder = SqlBuilder.createInsert("sw_bpm.asp_model"); | |||||
sqlBuilder.add("model_id", modelPo.getModelId()) | |||||
.add("model_parent_id", modelPo.getModelParentId()) | |||||
.add("model_mc_id", modelPo.getModelMcId()) | |||||
.add("model_site_id", us.getSiteId()) | |||||
.add("model_key", modelPo.getModelKey()) | |||||
.add("model_name", modelPo.getModelName()) | |||||
.add("model_status", modelPo.getModelStatus()) | |||||
.add("model_content", modelContent) | |||||
// .add("model_content_sign", contentSign) | |||||
.add("model_type", modelPo.getModelType()) | |||||
.add("model_sub_type", modelPo.getModelSubType()) | |||||
.add("model_version", modelPo.getModelVersion()) | |||||
.add("model_create_time", modelPo.getModelLastTime()) | |||||
.add("model_last_time", modelPo.getModelLastTime()) | |||||
.add("model_create_uid", us.getUserId()) | |||||
.add("model_update_uid", us.getUserId()); | |||||
sqlBuilder.update(dbEngine); | |||||
if (commit) { | |||||
this.insertDeployLog(modelPo, us); | |||||
} | |||||
return true; | |||||
}); | |||||
updateCache(modelPo.getModelId(), modelPo.getModelType()); | |||||
return R.success(modelPo.getModelId()); | |||||
} else { | |||||
if (commit) { | |||||
// 比较签名 | |||||
AspModelPO old = dbEngine.queryEntity("select model_version, model_content_sign from sw_bpm.bpm_model where model_id=?", AspModelPO.class, modelPo.getModelId()); | |||||
if (old != null) { | |||||
if (old.getModelContentSign() != null && old.getModelContentSign().equals(modelPo.getModelContentSign())) { | |||||
return R.success(); | |||||
} | |||||
modelPo.setModelVersion(old.getModelVersion() + 1); | |||||
} else { | |||||
modelPo.setModelVersion(1); | |||||
} | |||||
} | |||||
// 更新数据 | |||||
boolean r = dbEngine.doTrans(() -> { | |||||
// Timestamp now = new Timestamp(System.currentTimeMillis()); | |||||
UpdateSqlBuilder sqlBuilder = SqlBuilder.createUpdate("sw_bpm.asp_model"); | |||||
// .add("model_parent_id", modelPo.getModelParentId()) | |||||
// .add("model_mc_id", modelPo.getModelMcId()) | |||||
sqlBuilder.add("model_key", modelPo.getModelKey()) | |||||
.add("model_name", modelPo.getModelName()) | |||||
.add("model_content", modelContent) | |||||
// .add("model_content_sign", contentSign) | |||||
.add("model_status", modelPo.getModelStatus()) | |||||
.add("model_update_uid", us.getUserId()) | |||||
.add("model_last_time", modelPo.getModelLastTime()) | |||||
.addWhere("model_id", modelPo.getModelId()) | |||||
.addWhere("model_site_id", us.getSiteId()); | |||||
if (commit) { | |||||
sqlBuilder.add("model_version", modelPo.getModelVersion()); | |||||
} | |||||
int ret = sqlBuilder.update(dbEngine); | |||||
if (ret > 0) { | |||||
if (commit) { | |||||
this.insertDeployLog(modelPo, us); | |||||
} | |||||
return true; | |||||
} | |||||
return false; | |||||
}); | |||||
if (r) { | |||||
updateCache(modelPo.getModelId(), modelPo.getModelType()); | |||||
return R.success(); | |||||
} | |||||
return R.error("保存失败,未找到记录"); | |||||
} | |||||
} | |||||
private IPageRouter loadTree(Long pageId) { | |||||
ITreeDataLevelHandler<AspModelTreeVO> handler = AspModelTreeVO.createTreeHandler(); | |||||
List<AspModelTreeVO> list = dbEngine.query("select model_id, model_parent_id, model_key, model_name from sw_bpm.asp_model where model_mc_id in" + | |||||
" (select model_mc_id from sw_bpm.asp_model where model_id=?)", | |||||
AspModelTreeVO.class, pageId); | |||||
AspModelTreeVO root = new AspModelTreeVO(); | |||||
TreeDataUtil.buildLevelTree(root, list, handler); | |||||
return new TreePageRouter(root, null); | |||||
} | |||||
private boolean isUiType(@SwBody AspModelPO modelPo) { | |||||
return modelPo.getModelType() == AspModelPO.TYPE_UI_PC || modelPo.getModelType() == AspModelPO.TYPE_UI_MOBILE; | |||||
} | |||||
private void insertDeployLog(AspModelPO modelPo, UserSession us) { | |||||
// 部署 | |||||
Long oldId = dbEngine.queryLong("select model_id from sw_bpm.bpm_model where model_id=?", modelPo.getModelId()); | |||||
if (oldId != null) { | |||||
UpdateSqlBuilder sqlBuilder = SqlBuilder.createUpdate("sw_bpm.bpm_model"); | |||||
sqlBuilder.add("model_full_name", modelPo.getModelFullName()) | |||||
.add("model_name", modelPo.getModelName()) | |||||
.add("model_status", 0) | |||||
.add("model_use_vue", modelPo.getModelUseVue()) | |||||
.add("model_use_yaml", modelPo.getModelUseYaml()) | |||||
.add("model_content", modelPo.getModelContent()) | |||||
.add("model_content_sign", modelPo.getModelContentSign()) | |||||
.add("model_version", modelPo.getModelVersion()) | |||||
.add("model_last_time", modelPo.getModelLastTime()) | |||||
.addWhere("model_id", modelPo.getModelId()); | |||||
sqlBuilder.update(dbEngine); | |||||
} else { | |||||
InsertSqlBuilder sqlBuilder = SqlBuilder.createInsert("sw_bpm.bpm_model"); | |||||
sqlBuilder.add("model_id", modelPo.getModelId()) | |||||
.add("model_full_name", modelPo.getModelFullName()) | |||||
.add("model_site_id", us.getSiteId()) | |||||
.add("model_name", modelPo.getModelName()) | |||||
.add("model_status", 0) | |||||
.add("model_content", modelPo.getModelContent()) | |||||
.add("model_content_sign", modelPo.getModelContentSign()) | |||||
.add("model_type", modelPo.getModelType()) | |||||
.add("model_version", modelPo.getModelVersion()) | |||||
.add("model_create_time", modelPo.getModelLastTime()) | |||||
.add("model_last_time", modelPo.getModelLastTime()); | |||||
sqlBuilder.update(dbEngine); | |||||
} | |||||
// 产生部署日志 | |||||
Long dmId = dbEngine.nextId(); | |||||
InsertSqlBuilder sqlBuilder = SqlBuilder.createInsert("sw_bpm.asp_model_deploy"); | |||||
sqlBuilder.add("md_id", dmId) | |||||
.add("md_model_id", modelPo.getModelId()) | |||||
.add("md_model_key", modelPo.getModelKey()) | |||||
.add("md_name", modelPo.getModelName()) | |||||
.add("md_status", modelPo.getModelStatus()) | |||||
.add("md_content", modelPo.getModelContent()) | |||||
.add("md_type", modelPo.getModelType()) | |||||
.add("md_version", modelPo.getModelVersion()) | |||||
.add("md_create_uid", us.getUserId()); | |||||
sqlBuilder.update(dbEngine); | |||||
} | |||||
private void updateCache(Long modelId, byte modelType) { | |||||
switch (modelType) { | |||||
case AspModelPO.TYPE_FLOW: | |||||
bpmFlowCache.remove(modelId); | |||||
break; | |||||
case AspModelPO.TYPE_UI_PC: | |||||
case AspModelPO.TYPE_UI_MOBILE: | |||||
bpmPageCache.remove(modelId); | |||||
break; | |||||
default: | |||||
} | |||||
} | |||||
// @ApiOperation(value = "删除数据模型") | |||||
public R delete(@SwBody AspModelPO modelPo, UserSession us) { | |||||
String sql = "delete from sw_bpm.asp_model where model_id=? and model_site_id=?"; | |||||
if (dbEngine.update(sql, modelPo.getModelId(), us.getSiteId()) > 0) { | |||||
updateCache(modelPo.getModelId(), modelPo.getModelType()); | |||||
return R.success(); | |||||
} | |||||
return R.error("删除失败"); | |||||
} | |||||
// 修改子类型 | |||||
public R saveSubType(@SwBody AspModelPO modelPo, UserSession us) { | |||||
dbEngine.update("update sw_bpm.asp_model set model_sub_type=? where model_id=? and model_site_id=?", modelPo.getModelSubType(), modelPo.getModelId(), us.getSiteId()); | |||||
return R.success(); | |||||
} | |||||
} |
@@ -1,54 +0,0 @@ | |||||
package cc.smtweb.system.bpm.web.design.model; | |||||
import cc.smtweb.framework.core.common.R; | |||||
import cc.smtweb.framework.core.common.SwMap; | |||||
import cc.smtweb.framework.core.annotation.SwParam; | |||||
import cc.smtweb.framework.core.annotation.SwService; | |||||
import cc.smtweb.framework.core.common.SwEnum; | |||||
import cc.smtweb.system.bpm.spring.BpmConfigBean; | |||||
import cc.smtweb.system.bpm.util.YamlUtil; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.apache.commons.lang3.StringUtils; | |||||
import java.io.File; | |||||
import java.util.HashMap; | |||||
import java.util.Map; | |||||
@Slf4j | |||||
@SwService | |||||
@Deprecated | |||||
public class AspModelConfigService { | |||||
@SwParam | |||||
private BpmConfigBean bpmConfigBean; | |||||
public R load() { | |||||
R result = R.success().put("dataType", SwEnum.DataType.instance.values()); | |||||
String configUiPath = bpmConfigBean.getConfigUiPath(); | |||||
if (StringUtils.isNotBlank(configUiPath)) { | |||||
File file = new File(configUiPath); | |||||
if (file.isDirectory()) { | |||||
File[] files = file.listFiles(); | |||||
if (files != null) { | |||||
Map<String, SwMap> config = new HashMap<>(); | |||||
for (File yamlFile: files) { | |||||
String fileName = yamlFile.getName(); | |||||
if (fileName.endsWith(".yaml") && fileName.startsWith("fx-")) { | |||||
SwMap meta = YamlUtil.readValue(yamlFile, SwMap.class); | |||||
config.put(fileName.substring(0, fileName.length() - 5), meta); | |||||
} | |||||
} | |||||
if (!config.isEmpty()) { | |||||
result.put("schema", config); | |||||
} | |||||
} | |||||
} else { | |||||
log.error("not find path:" + configUiPath); | |||||
} | |||||
} | |||||
return result; | |||||
} | |||||
} |
@@ -1,69 +0,0 @@ | |||||
package cc.smtweb.system.bpm.web.design.model; | |||||
import cc.smtweb.framework.core.annotation.SwParam; | |||||
import cc.smtweb.framework.core.annotation.SwService; | |||||
import cc.smtweb.framework.core.db.DbEngine; | |||||
import cc.smtweb.framework.core.db.jdbc.IdGenerator; | |||||
import cc.smtweb.system.bpm.spring.cache.BpmFlowCache; | |||||
import cc.smtweb.system.bpm.spring.cache.BpmPageCache; | |||||
@SwService | |||||
public class AspModelExportService { | |||||
@SwParam | |||||
private DbEngine dbEngine; | |||||
@SwParam | |||||
private BpmFlowCache bpmFlowCache; | |||||
@SwParam | |||||
private BpmPageCache bpmPageCache; | |||||
@SwParam | |||||
private IdGenerator idGenerator; | |||||
/*// @ApiOperation(value = "读取数据模型数据") | |||||
public R mysql(@SwBody SwMap body, UserSession us) { | |||||
String sql = "select model_id, model_parent_id, model_mc_id, model_site_id, model_key, model_name, model_status, model_content, model_type, model_version, model_create_uid, model_update_uid, model_create_time, model_last_time from sw_bpm.asp_model" + | |||||
" where model_id=? and model_site_id=?"; | |||||
AspModelPO po = dbEngine.queryEntity(sql, AspModelPO.class, body.readLong("modelId"), us.getSiteId()); | |||||
DbLoader loader = new DbLoader(designConfig.getDataType()); | |||||
ModelDatabase modelDatabase = loader.load(po.getModelContent()); | |||||
if (loader.getLastError() != null) { | |||||
return R.error(loader.getLastError()).put("modelErrors", loader.getErrors()); | |||||
} | |||||
// 创建数据库 | |||||
HikariDataSource datasource = new HikariDataSource(); | |||||
String host = body.readString("host", "127.0.0.1"); | |||||
Integer port = body.readInt("port", 3306); | |||||
String dbName = body.readString("database", modelDatabase.getName()); | |||||
modelDatabase.setName(dbName); | |||||
datasource.setJdbcUrl("jdbc:mysql://" + host + ":" + port + "/" + dbName + "?serverTimezone=UTC&allowMultiQueries=true&useSSL=false"); | |||||
datasource.setDriverClassName("com.mysql.cj.jdbc.Driver"); | |||||
datasource.setUsername(body.readString("username")); | |||||
datasource.setPassword(body.readString("password")); | |||||
try { | |||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(datasource); | |||||
DbEngine dynDbEngine = new DbEngine(jdbcTemplate, idGenerator); | |||||
// 导入数据库结构 | |||||
SqlImport sqlImport = new SqlImport(dynDbEngine); | |||||
ModelDatabase oldDb = sqlImport.importDb(dbName); | |||||
SqlExport sqlExport = new SqlExport(); | |||||
// 导出数据库结构 | |||||
sqlExport.export(modelDatabase, oldDb, dynDbEngine::update); | |||||
} finally { | |||||
datasource.close(); | |||||
} | |||||
return R.success(); | |||||
}*/ | |||||
} |
@@ -1,25 +0,0 @@ | |||||
package cc.smtweb.system.bpm.web.design.model; | |||||
import cc.smtweb.framework.core.common.R; | |||||
import cc.smtweb.framework.core.annotation.SwParam; | |||||
import cc.smtweb.framework.core.annotation.SwService; | |||||
import cc.smtweb.framework.core.db.DbEngine; | |||||
import cc.smtweb.framework.core.session.UserSession; | |||||
import cc.smtweb.system.bpm.engine.entity.AspModelPO; | |||||
import java.util.List; | |||||
// @Api(tags = "数据模型") | |||||
@SwService | |||||
public class AspModelListService { | |||||
@SwParam | |||||
private DbEngine dbEngine; | |||||
// @ApiOperation(value = "数据模型列表") | |||||
public R list(@SwParam("type") long type, UserSession us) { | |||||
String sql = "select model_id, model_mc_id, model_site_id, model_name, model_key, model_status, model_type, model_sub_type, model_version, model_create_uid, model_update_uid, model_create_time, model_last_time from sw_bpm.asp_model" + | |||||
" where model_site_id=? and model_type=?"; | |||||
List<AspModelPO> list = dbEngine.query(sql, AspModelPO.class,us.getSiteId(), type); | |||||
return R.success(list); | |||||
} | |||||
} |
@@ -1,103 +0,0 @@ | |||||
package cc.smtweb.system.bpm.web.design.model; | |||||
import cc.smtweb.framework.core.common.R; | |||||
import cc.smtweb.framework.core.annotation.SwBody; | |||||
import cc.smtweb.framework.core.annotation.SwParam; | |||||
import cc.smtweb.framework.core.annotation.SwService; | |||||
import cc.smtweb.framework.core.db.DbEngine; | |||||
import cc.smtweb.framework.core.session.UserSession; | |||||
import cc.smtweb.system.bpm.engine.entity.AspModelCatalogPO; | |||||
import cc.smtweb.system.bpm.engine.entity.AspModelPO; | |||||
import cc.smtweb.system.bpm.engine.entity.AspModelTreeVO; | |||||
import cc.smtweb.system.bpm.util.TreeDataUtil; | |||||
import cc.smtweb.system.bpm.web.design.model.entity.TreeMoveVO; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
@SwService | |||||
public class AspModelTreeService { | |||||
@SwParam | |||||
private DbEngine dbEngine; | |||||
public R treeAll(@SwParam("mcId") long mcId, @SwParam("modelType") long modelType, UserSession us) { | |||||
return R.success(loadTreeAll(mcId, modelType, us)); | |||||
} | |||||
private List<AspModelTreeVO> loadTreeAll(@SwParam("mcId") long mcId, @SwParam("modelType") long modelType, UserSession us) { | |||||
String sql = "select model_id, model_parent_id, model_key, model_name, model_status, model_type, model_sub_type, model_version, model_create_time, model_last_time from sw_bpm.asp_model" + | |||||
" where model_mc_id=? and model_type=? and model_site_id=? order by model_order, model_id"; | |||||
List<AspModelTreeVO> list = dbEngine.query(sql, AspModelTreeVO.class, mcId, modelType, us.getSiteId()); | |||||
AspModelTreeVO root = new AspModelTreeVO(); | |||||
root.setModelName("项目"); | |||||
return TreeDataUtil.buildTree(root, list, AspModelTreeVO.createTreeHandler()); | |||||
} | |||||
public R menu(@SwParam("mcId") long mcId, @SwParam("modelType") long modelType, UserSession us) { | |||||
List<AspModelTreeVO> tree = loadTreeAll(mcId, modelType, us); | |||||
// 强制只显示2级 | |||||
if (tree != null) { | |||||
for (AspModelTreeVO item : tree) { | |||||
List<AspModelTreeVO> children = item.getChildren(); | |||||
if (children != null) { | |||||
for (AspModelTreeVO child : item.getChildren()) { | |||||
child.setChildren(null); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
return R.success(tree); | |||||
} | |||||
/** 动态Tree数据 */ | |||||
public R tree(@SwParam("type") long type, @SwParam("catalog") long catalog, @SwParam("parentId") Long parentId, UserSession us) { | |||||
R result = null; | |||||
if (parentId == null) { | |||||
String sql = "select model_id, model_mc_id, model_key, model_name, model_status, model_version, model_create_uid, model_update_uid, model_create_time, model_last_time from sw_bpm.asp_model" + | |||||
" where model_mc_id=? and model_parent_id is null and model_site_id=? and model_type=? order by model_order, model_id"; | |||||
List<AspModelPO> list = dbEngine.query(sql, AspModelPO.class, catalog, us.getSiteId(), type); | |||||
result = R.success(list); | |||||
sql = "select mc_id, mc_parent_id, mc_code, mc_site_id, mc_name, mc_create_time, mc_last_time from sw_bpm.asp_model_catalog" + | |||||
" where mc_id=? and mc_site_id=?"; | |||||
AspModelCatalogPO po = dbEngine.queryEntity(sql, AspModelCatalogPO.class, catalog, us.getSiteId()); | |||||
result.put("catalog", po); | |||||
} else { | |||||
String sql = "select model_id, model_mc_id, model_key, model_name, model_status, model_version, model_create_uid, model_update_uid, model_create_time, model_last_time from sw_bpm.asp_model" + | |||||
" where model_mc_id=? and model_parent_id=? and model_site_id=? and model_type=? order by model_order, model_id"; | |||||
List<AspModelPO> list = dbEngine.query(sql, AspModelPO.class, catalog, parentId, us.getSiteId(), type); | |||||
result = R.success(list); | |||||
AspModelPO parent = dbEngine.queryEntity("select model_id, model_mc_id, model_parent_id, model_key, model_name, model_status, model_version, model_create_time, model_last_time from sw_bpm.asp_model" + | |||||
" where model_id=?",AspModelPO.class, parentId); | |||||
result.put("parent", parent); | |||||
} | |||||
return result; | |||||
} | |||||
public R move(@SwBody TreeMoveVO vo, UserSession us) { | |||||
if (vo.getId() != null && vo.getOrders() != null) { | |||||
List<Object[]> params = new ArrayList<>(); | |||||
int index = 0; | |||||
for (Long order: vo.getOrders()) { | |||||
params.add(new Object[]{vo.getParentId(), ++index, order}); | |||||
} | |||||
int[] ret = dbEngine.batchUpdate("update sw_bpm.asp_model set model_parent_id=?, model_order=? where model_id=?", params); | |||||
if (ret.length > 0) { | |||||
return R.success(); | |||||
} | |||||
} | |||||
return R.error(); | |||||
} | |||||
} |
@@ -1,10 +0,0 @@ | |||||
package cc.smtweb.system.bpm.web.design.model.entity; | |||||
import lombok.Data; | |||||
@Data | |||||
public class TreeMoveVO { | |||||
private Long id; | |||||
private Long parentId; | |||||
private Long[] orders; | |||||
} |