use of org.sagacity.sqltoy.utils.DataSourceUtils.DBType in project sagacity-sqltoy by chenrenfei.
the class DialectUtils method update.
/**
* @todo 单个对象修改,包含接连修改
* @param sqlToyContext
* @param entity
* @param nullFunction
* @param forceUpdateFields
* @param cascade
* @param generateSqlHandler
* @param forceCascadeClasses
* @param subTableForceUpdateProps
* @param conn
* @param tableName
* @throws Exception
*/
public static Long update(SqlToyContext sqlToyContext, Serializable entity, String nullFunction, String[] forceUpdateFields, final boolean cascade, final GenerateSqlHandler generateSqlHandler, final Class[] forceCascadeClasses, final HashMap<Class, String[]> subTableForceUpdateProps, Connection conn, final Integer dbType, String tableName) throws Exception {
EntityMeta entityMeta = sqlToyContext.getEntityMeta(entity.getClass());
String realTable = entityMeta.getSchemaTable(tableName, dbType);
// 无主键
if (entityMeta.getIdArray() == null) {
throw new IllegalArgumentException("表:" + realTable + " 无主键,不符合update/updateAll规则,请检查表设计是否合理!");
}
// 全部是主键则无需update
if (entityMeta.getRejectIdFieldArray() == null) {
logger.warn("表:" + realTable + " 字段全部是主键不存在更新字段,无需执行更新操作!");
return 0L;
}
Long updateCnt = update(sqlToyContext, entity, entityMeta, nullFunction, forceUpdateFields, conn, dbType, tableName);
// 不存在级联操作
if (!cascade || entityMeta.getCascadeModels().isEmpty()) {
return updateCnt;
}
// 级联保存
HashMap<Type, String> typeMap = new HashMap<Type, String>();
// 即使子对象数据是null,也强制进行级联修改(null表示删除子表数据)
if (forceCascadeClasses != null) {
for (Type type : forceCascadeClasses) {
typeMap.put(type, "");
}
}
// 级联子表数据
List subTableData = null;
String[] forceUpdateProps = null;
EntityMeta subTableEntityMeta;
// 对子表进行级联处理
for (TableCascadeModel cascadeModel : entityMeta.getCascadeModels()) {
final Object[] mainFieldValues = BeanUtil.reflectBeanToAry(entity, cascadeModel.getFields());
subTableEntityMeta = sqlToyContext.getEntityMeta(cascadeModel.getMappedType());
forceUpdateProps = (subTableForceUpdateProps == null) ? null : subTableForceUpdateProps.get(cascadeModel.getMappedType());
// oneToMany
if (cascadeModel.getCascadeType() == 1) {
subTableData = (List) BeanUtil.getProperty(entity, cascadeModel.getProperty());
} else {
subTableData = new ArrayList();
Object item = BeanUtil.getProperty(entity, cascadeModel.getProperty());
if (item != null) {
subTableData.add(item);
}
}
final String[] mappedFields = cascadeModel.getMappedFields();
// 针对子表存量数据,调用级联修改的语句,分delete 和update两种操作 1、删除存量数据;2、设置存量数据状态为停用
if (cascadeModel.getCascadeUpdateSql() != null && ((subTableData != null && !subTableData.isEmpty()) || typeMap.containsKey(cascadeModel.getMappedType()))) {
SqlExecuteStat.debug("执行子表级联更新前的存量数据更新", null);
// 根据quickvo配置文件针对cascade中update-cascade配置组织具体操作sql
SqlToyResult sqlToyResult = SqlConfigParseUtils.processSql(cascadeModel.getCascadeUpdateSql(), mappedFields, mainFieldValues, null);
SqlUtil.executeSql(sqlToyContext.getTypeHandler(), sqlToyResult.getSql(), sqlToyResult.getParamsValue(), null, conn, dbType, null, true);
}
// 子表数据不为空,采取saveOrUpdateAll操作
if (subTableData != null && !subTableData.isEmpty()) {
logger.info("执行update主表:{} 对应级联子表: {} 更新操作!", realTable, subTableEntityMeta.getTableName());
SqlExecuteStat.debug("执行子表级联更新操作", null);
// 将外键值通过反调赋到相关属性上
ReflectPropsHandler reflectPropsHandler = new ReflectPropsHandler() {
public void process() {
for (int i = 0; i < mappedFields.length; i++) {
this.setValue(mappedFields[i], mainFieldValues[i]);
}
}
};
// 这里需要进行修改,mysql\postgresql\sqlite 等存在缺陷(字段值不为null时会报错)
if (dbType == DBType.MYSQL || dbType == DBType.MYSQL57 || dbType == DBType.TIDB) {
mysqlSaveOrUpdateAll(sqlToyContext, subTableEntityMeta, subTableData, reflectPropsHandler, forceUpdateProps, conn, dbType);
} else if (dbType == DBType.POSTGRESQL || dbType == DBType.GAUSSDB) {
postgreSaveOrUpdateAll(sqlToyContext, subTableEntityMeta, subTableData, reflectPropsHandler, forceUpdateProps, conn, dbType);
} else if (dbType == DBType.OCEANBASE) {
oceanBaseSaveOrUpdateAll(sqlToyContext, subTableEntityMeta, subTableData, reflectPropsHandler, forceUpdateProps, conn, dbType);
} else if (dbType == DBType.SQLITE) {
sqliteSaveOrUpdateAll(sqlToyContext, subTableEntityMeta, subTableData, reflectPropsHandler, forceUpdateProps, conn, dbType);
} else // 达梦数据库
if (dbType == DBType.DM) {
dmSaveOrUpdateAll(sqlToyContext, subTableEntityMeta, subTableData, reflectPropsHandler, forceUpdateProps, conn, dbType);
} else // kingbase
if (dbType == DBType.KINGBASE) {
kingbaseSaveOrUpdateAll(sqlToyContext, subTableEntityMeta, subTableData, reflectPropsHandler, forceUpdateProps, conn, dbType);
} else // db2/oracle/mssql 通过merge 方式
{
saveOrUpdateAll(sqlToyContext, subTableData, sqlToyContext.getBatchSize(), subTableEntityMeta, forceUpdateProps, generateSqlHandler, // 设置关联外键字段的属性值(来自主表的主键)
reflectPropsHandler, conn, dbType, null);
}
} else {
logger.info("未执行update主表:{} 对应级联子表: {} 更新操作,子表数据为空!", realTable, subTableEntityMeta.getTableName());
}
}
return updateCnt;
}
use of org.sagacity.sqltoy.utils.DataSourceUtils.DBType in project sagacity-sqltoy by chenrenfei.
the class SqlServerDialectUtils method update.
/**
* @todo 单个对象修改,包含级联修改
* @param sqlToyContext
* @param entity
* @param forceUpdateFields
* @param cascade
* @param emptyCascadeClasses
* @param subTableForceUpdateProps
* @param conn
* @param dbType
* @param tableName
* @return
* @throws Exception
*/
public static Long update(SqlToyContext sqlToyContext, Serializable entity, String[] forceUpdateFields, final boolean cascade, final Class[] emptyCascadeClasses, final HashMap<Class, String[]> subTableForceUpdateProps, Connection conn, final Integer dbType, final String tableName) throws Exception {
EntityMeta entityMeta = sqlToyContext.getEntityMeta(entity.getClass());
String realTable = entityMeta.getSchemaTable(tableName, dbType);
Long updateCount = DialectUtils.update(sqlToyContext, entity, entityMeta, "isnull", forceUpdateFields, conn, dbType, realTable);
// 级联修改
if (cascade && !entityMeta.getCascadeModels().isEmpty()) {
HashMap<Type, String> typeMap = new HashMap<Type, String>();
if (emptyCascadeClasses != null) {
for (Type type : emptyCascadeClasses) {
typeMap.put(type, "");
}
}
// 级联子表数据
List subTableData = null;
String[] forceUpdateProps = null;
EntityMeta subTableEntityMeta;
for (TableCascadeModel cascadeModel : entityMeta.getCascadeModels()) {
final Object[] mainFieldValues = BeanUtil.reflectBeanToAry(entity, cascadeModel.getFields());
subTableEntityMeta = sqlToyContext.getEntityMeta(cascadeModel.getMappedType());
forceUpdateProps = (subTableForceUpdateProps == null) ? null : subTableForceUpdateProps.get(cascadeModel.getMappedType());
if (cascadeModel.getCascadeType() == 1) {
subTableData = (List) BeanUtil.getProperty(entity, cascadeModel.getProperty());
} else {
subTableData = new ArrayList();
Object item = BeanUtil.getProperty(entity, cascadeModel.getProperty());
if (item != null) {
subTableData.add(item);
}
}
final String[] mappedFields = cascadeModel.getMappedFields();
// 针对存量子表数据,调用级联修改的语句,分delete 和update两种操作 1、删除存量数据;2、设置存量数据状态为停用
if (cascadeModel.getCascadeUpdateSql() != null && ((subTableData != null && !subTableData.isEmpty()) || typeMap.containsKey(cascadeModel.getMappedType()))) {
SqlExecuteStat.debug("执行子表级联更新前的存量数据更新", null);
SqlToyResult sqlToyResult = SqlConfigParseUtils.processSql(cascadeModel.getCascadeUpdateSql(), mappedFields, mainFieldValues, null);
SqlUtil.executeSql(sqlToyContext.getTypeHandler(), sqlToyResult.getSql(), sqlToyResult.getParamsValue(), null, conn, dbType, null, true);
}
// 子表数据不为空,采取saveOrUpdateAll操作
if (subTableData != null && !subTableData.isEmpty()) {
logger.info("执行update主表:{} 对应级联子表: {} 更新操作!", tableName, subTableEntityMeta.getTableName());
SqlExecuteStat.debug("执行子表级联更新操作", null);
saveOrUpdateAll(sqlToyContext, subTableData, sqlToyContext.getBatchSize(), // 设置关联外键字段的属性值(来自主表的主键)
new ReflectPropsHandler() {
public void process() {
for (int i = 0; i < mappedFields.length; i++) {
this.setValue(mappedFields[i], mainFieldValues[i]);
}
}
}, forceUpdateProps, conn, dbType, null, null);
} else {
logger.info("未执行update主表:{} 对应级联子表: {} 更新操作,子表数据为空!", tableName, subTableEntityMeta.getTableName());
}
}
}
return updateCount;
}
use of org.sagacity.sqltoy.utils.DataSourceUtils.DBType in project sagacity-sqltoy by chenrenfei.
the class DialectFactory method wrapTreeTableRoute.
/**
* @todo 构造树形表的节点路径、节点层级、节点类别(是否叶子节点)
* @param sqlToyContext
* @param treeModel
* @param dataSource
* @return
*/
public boolean wrapTreeTableRoute(final SqlToyContext sqlToyContext, final TreeTableModel treeModel, final DataSource dataSource) {
if (treeModel == null || StringUtil.isBlank(treeModel.getPidField())) {
throw new IllegalArgumentException("请检查pidField赋值是否正确!");
}
if (StringUtil.isBlank(treeModel.getLeafField()) || StringUtil.isBlank(treeModel.getNodeRouteField()) || StringUtil.isBlank(treeModel.getNodeLevelField())) {
throw new IllegalArgumentException("请检查isLeafField\nodeRouteField\nodeLevelField 赋值是否正确!");
}
try {
if (null != treeModel.getEntity()) {
EntityMeta entityMeta = null;
if (treeModel.getEntity() instanceof Type) {
entityMeta = sqlToyContext.getEntityMeta((Class) treeModel.getEntity());
} else {
entityMeta = sqlToyContext.getEntityMeta(treeModel.getEntity().getClass());
}
// 兼容填写fieldName,统一转化为columnName
// pid
String columnName = entityMeta.getColumnName(treeModel.getPidField());
if (columnName != null) {
treeModel.pidField(columnName);
}
// leafField
columnName = entityMeta.getColumnName(treeModel.getLeafField());
if (columnName != null) {
treeModel.isLeafField(columnName);
}
// nodeLevel
columnName = entityMeta.getColumnName(treeModel.getNodeLevelField());
if (columnName != null) {
treeModel.nodeLevelField(columnName);
}
// nodeRoute
columnName = entityMeta.getColumnName(treeModel.getNodeRouteField());
if (columnName != null) {
treeModel.nodeRouteField(columnName);
}
HashMap<String, String> columnMap = new HashMap<String, String>();
for (FieldMeta column : entityMeta.getFieldsMeta().values()) {
columnMap.put(column.getColumnName().toUpperCase(), "");
}
if (!columnMap.containsKey(treeModel.getNodeRouteField().toUpperCase())) {
throw new IllegalArgumentException("树形表:节点路径字段名称:" + treeModel.getNodeRouteField() + "不正确,请检查!");
}
if (!columnMap.containsKey(treeModel.getLeafField().toUpperCase())) {
throw new IllegalArgumentException("树形表:是否叶子节点字段名称:" + treeModel.getLeafField() + "不正确,请检查!");
}
if (!columnMap.containsKey(treeModel.getNodeLevelField().toUpperCase())) {
throw new IllegalArgumentException("树形表:节点等级字段名称:" + treeModel.getNodeLevelField() + "不正确,请检查!");
}
FieldMeta idMeta = (FieldMeta) entityMeta.getFieldMeta(entityMeta.getIdArray()[0]);
// 如未定义则使用主键(update 2020-10-16)
if (StringUtil.isBlank(treeModel.getIdField())) {
treeModel.idField(idMeta.getColumnName());
} else {
// 别名转换
columnName = entityMeta.getColumnName(treeModel.getIdField());
if (columnName != null) {
treeModel.idField(columnName);
}
}
if (StringUtil.isBlank(treeModel.getTableName())) {
treeModel.table(entityMeta.getSchemaTable(null, null));
}
// 通过实体对象取值给rootId和idValue赋值
if (!(treeModel.getEntity() instanceof Type)) {
// update 2020-10-19 从手工设定的字段中取值(原本从主键中取值)
if (null == treeModel.getRootId()) {
Object pidValue = BeanUtil.getProperty(treeModel.getEntity(), StringUtil.toHumpStr(treeModel.getPidField(), false));
treeModel.rootId(pidValue);
}
if (null == treeModel.getIdValue()) {
Object idValue = BeanUtil.getProperty(treeModel.getEntity(), StringUtil.toHumpStr(treeModel.getIdField(), false));
treeModel.setIdValue(idValue);
}
}
// 类型,默认值为false
if (idMeta.getType() == java.sql.Types.INTEGER || idMeta.getType() == java.sql.Types.DECIMAL || idMeta.getType() == java.sql.Types.DOUBLE || idMeta.getType() == java.sql.Types.FLOAT || idMeta.getType() == java.sql.Types.NUMERIC) {
treeModel.idTypeIsChar(false);
// update 2016-12-05 节点路径默认采取主键值直接拼接,更加直观科学
// treeModel.setAppendZero(true);
} else if (idMeta.getType() == java.sql.Types.VARCHAR || idMeta.getType() == java.sql.Types.CHAR) {
treeModel.idTypeIsChar(true);
}
}
SqlExecuteStat.start(treeModel.getTableName(), "wrapTreeTableRoute", true);
return (Boolean) DataSourceUtils.processDataSource(sqlToyContext, dataSource, new DataSourceCallbackHandler() {
@Override
public void doConnection(Connection conn, Integer dbType, String dialect) throws Exception {
this.setResult(SqlUtil.wrapTreeTableRoute(sqlToyContext.getTypeHandler(), treeModel, conn, dbType));
}
});
} catch (Exception e) {
logger.error("封装树形表节点路径操作:wrapTreeTableRoute发生错误,{}", e.getMessage());
e.printStackTrace();
throw new DataAccessException(e);
} finally {
SqlExecuteStat.destroy();
}
}
use of org.sagacity.sqltoy.utils.DataSourceUtils.DBType in project sagacity-sqltoy by chenrenfei.
the class DialectFactory method loadAll.
/**
* @todo 批量加载集合(自4.13.1 版本已经自动将超大规模集合拆分执行),规避了jpa等框架的缺陷
* @param sqlToyContext
* @param entities
* @param cascadeTypes
* @param lockMode
* @param dataSource
* @return
*/
public <T extends Serializable> List<T> loadAll(final SqlToyContext sqlToyContext, final List<T> entities, final Class[] cascadeTypes, final LockMode lockMode, final DataSource dataSource) {
if (entities == null || entities.isEmpty()) {
logger.warn("loadAll entities is null or empty,please check!");
return entities;
}
try {
SqlExecuteStat.start(BeanUtil.getEntityClass(entities.get(0).getClass()).getName(), "loadAll:[" + entities.size() + "]条记录!", null);
// 一般in的最大数量是1000
int batchSize = SqlToyConstants.getLoadAllBatchSize();
// 对可能存在的配置参数定义错误进行校正,最大控制在1000内
if (batchSize > 1000 || batchSize < 1) {
batchSize = 1000;
}
int totalSize = entities.size();
int batch = (totalSize + batchSize - 1) / batchSize;
List result = new ArrayList();
List batchEntities;
for (int i = 0; i < batch; i++) {
// 切取单个批次的记录
batchEntities = entities.subList(i * batchSize, (i == batch - 1) ? totalSize : (i + 1) * batchSize);
// 分库分表并行执行,并返回结果
result.addAll(ParallelUtils.execute(sqlToyContext, batchEntities, false, dataSource, (context, batchModel) -> {
ShardingModel shardingModel = batchModel.getShardingModel();
return (List) DataSourceUtils.processDataSource(context, shardingModel.getDataSource(), new DataSourceCallbackHandler() {
@Override
public void doConnection(Connection conn, Integer dbType, String dialect) throws Exception {
this.setResult(getDialectSqlWrapper(dbType).loadAll(context, batchModel.getEntities(), (cascadeTypes == null) ? null : CollectionUtil.arrayToList(cascadeTypes), lockMode, conn, dbType, dialect, shardingModel.getTableName(), getFetchSize(-1), -1));
}
});
}));
}
SqlExecuteStat.debug("执行结果", "查询结果记录:{} 条!", result.size());
return result;
} catch (Exception e) {
SqlExecuteStat.error(e);
throw new DataAccessException(e);
} finally {
SqlExecuteStat.destroy();
}
}
Aggregations