Search in sources :

Example 1 with ReflectPropsHandler

use of org.sagacity.sqltoy.callback.ReflectPropsHandler in project sagacity-sqltoy by chenrenfei.

the class DialectUtils method saveOrUpdateAll.

/**
 * @todo 执行批量保存或修改操作
 * @param sqlToyContext
 * @param entities
 * @param batchSize
 * @param entityMeta
 * @param forceUpdateFields
 * @param generateSqlHandler
 * @param reflectPropsHandler
 * @param conn
 * @param dbType
 * @param autoCommit
 * @return
 * @throws Exception
 */
public static Long saveOrUpdateAll(SqlToyContext sqlToyContext, List<?> entities, final int batchSize, EntityMeta entityMeta, String[] forceUpdateFields, GenerateSqlHandler generateSqlHandler, ReflectPropsHandler reflectPropsHandler, Connection conn, final Integer dbType, Boolean autoCommit) throws Exception {
    // 重新构造修改或保存的属性赋值反调
    ReflectPropsHandler handler = getSaveOrUpdateReflectHandler(entityMeta.getIdArray(), reflectPropsHandler, forceUpdateFields, sqlToyContext.getUnifyFieldsHandler());
    handler = getSecureReflectHandler(handler, sqlToyContext.getFieldsSecureProvider(), sqlToyContext.getDesensitizeProvider(), entityMeta.getSecureFields());
    List<Object[]> paramValues = BeanUtil.reflectBeansToInnerAry(entities, entityMeta.getFieldsArray(), null, handler);
    int pkIndex = entityMeta.getIdIndex();
    // 是否存在业务ID
    boolean hasBizId = (entityMeta.getBusinessIdGenerator() == null) ? false : true;
    int bizIdColIndex = hasBizId ? entityMeta.getFieldIndex(entityMeta.getBusinessIdField()) : 0;
    // 标识符
    String signature = entityMeta.getBizIdSignature();
    Integer[] relatedColumn = entityMeta.getBizIdRelatedColIndex();
    int relatedColumnSize = (relatedColumn == null) ? 0 : relatedColumn.length;
    // 无主键以及多主键以及assign或通过generator方式产生主键策略
    if (null != entityMeta.getIdStrategy() && null != entityMeta.getIdGenerator()) {
        int bizIdLength = entityMeta.getBizIdLength();
        int idLength = entityMeta.getIdLength();
        Object[] rowData;
        Object[] relatedColValue = null;
        String idJdbcType = entityMeta.getIdType();
        String businessIdType = hasBizId ? entityMeta.getColumnJavaType(entityMeta.getBusinessIdField()) : "";
        for (int i = 0; i < paramValues.size(); i++) {
            rowData = (Object[]) paramValues.get(i);
            // 获取主键策略关联字段的值
            if (relatedColumn != null) {
                relatedColValue = new Object[relatedColumnSize];
                for (int meter = 0; meter < relatedColumnSize; meter++) {
                    relatedColValue[meter] = rowData[relatedColumn[meter]];
                }
            }
            if (StringUtil.isBlank(rowData[pkIndex])) {
                rowData[pkIndex] = entityMeta.getIdGenerator().getId(entityMeta.getTableName(), signature, entityMeta.getBizIdRelatedColumns(), relatedColValue, null, idJdbcType, idLength, entityMeta.getBizIdSequenceSize());
                // 回写主键值
                BeanUtil.setProperty(entities.get(i), entityMeta.getIdArray()[0], rowData[pkIndex]);
            }
            if (hasBizId && StringUtil.isBlank(rowData[bizIdColIndex])) {
                rowData[bizIdColIndex] = entityMeta.getBusinessIdGenerator().getId(entityMeta.getTableName(), signature, entityMeta.getBizIdRelatedColumns(), relatedColValue, null, businessIdType, bizIdLength, entityMeta.getBizIdSequenceSize());
                // 回写主键值
                BeanUtil.setProperty(entities.get(i), entityMeta.getBusinessIdField(), rowData[bizIdColIndex]);
            }
        }
    }
    String saveOrUpdateSql = generateSqlHandler.generateSql(entityMeta, forceUpdateFields);
    SqlExecuteStat.showSql("执行saveOrUpdate语句", saveOrUpdateSql, null);
    return SqlUtil.batchUpdateByJdbc(sqlToyContext.getTypeHandler(), saveOrUpdateSql, paramValues, batchSize, null, entityMeta.getFieldsTypeArray(), autoCommit, conn, dbType);
}
Also used : ReflectPropsHandler(org.sagacity.sqltoy.callback.ReflectPropsHandler)

Example 2 with ReflectPropsHandler

use of org.sagacity.sqltoy.callback.ReflectPropsHandler in project sagacity-sqltoy by chenrenfei.

the class DialectUtils method saveAllIgnoreExist.

/**
 * @todo 执行批量保存或修改操作
 * @param sqlToyContext
 * @param entities
 * @param batchSize
 * @param entityMeta
 * @param generateSqlHandler
 * @param reflectPropsHandler
 * @param conn
 * @param dbType
 * @param autoCommit
 * @return
 * @throws Exception
 */
public static Long saveAllIgnoreExist(SqlToyContext sqlToyContext, List<?> entities, final int batchSize, EntityMeta entityMeta, GenerateSqlHandler generateSqlHandler, ReflectPropsHandler reflectPropsHandler, Connection conn, final Integer dbType, Boolean autoCommit) throws Exception {
    // 构造全新的新增记录参数赋值反射(覆盖之前的)
    ReflectPropsHandler handler = getAddReflectHandler(reflectPropsHandler, sqlToyContext.getUnifyFieldsHandler());
    handler = getSecureReflectHandler(handler, sqlToyContext.getFieldsSecureProvider(), sqlToyContext.getDesensitizeProvider(), entityMeta.getSecureFields());
    List<Object[]> paramValues = BeanUtil.reflectBeansToInnerAry(entities, entityMeta.getFieldsArray(), null, handler);
    int pkIndex = entityMeta.getIdIndex();
    // 是否存在业务ID
    boolean hasBizId = (entityMeta.getBusinessIdGenerator() == null) ? false : true;
    int bizIdColIndex = hasBizId ? entityMeta.getFieldIndex(entityMeta.getBusinessIdField()) : 0;
    // 标识符
    String signature = entityMeta.getBizIdSignature();
    Integer[] relatedColumn = entityMeta.getBizIdRelatedColIndex();
    String[] relatedColumnNames = entityMeta.getBizIdRelatedColumns();
    int relatedColumnSize = (relatedColumn == null) ? 0 : relatedColumn.length;
    // 无主键以及多主键以及assign或通过generator方式产生主键策略
    if (null != entityMeta.getIdStrategy() && null != entityMeta.getIdGenerator()) {
        int bizIdLength = entityMeta.getBizIdLength();
        int idLength = entityMeta.getIdLength();
        Object[] rowData;
        Object[] relatedColValue = null;
        String idJdbcType = entityMeta.getIdType();
        String businessIdType = hasBizId ? entityMeta.getColumnJavaType(entityMeta.getBusinessIdField()) : "";
        for (int i = 0; i < paramValues.size(); i++) {
            rowData = (Object[]) paramValues.get(i);
            // 关联字段赋值
            if (relatedColumn != null) {
                relatedColValue = new Object[relatedColumnSize];
                for (int meter = 0; meter < relatedColumnSize; meter++) {
                    relatedColValue[meter] = rowData[relatedColumn[meter]];
                    if (relatedColValue[meter] == null) {
                        throw new IllegalArgumentException("对象:" + entityMeta.getEntityClass().getName() + " 生成业务主键依赖的关联字段:" + relatedColumnNames[meter] + " 值为null!");
                    }
                }
            }
            if (StringUtil.isBlank(rowData[pkIndex])) {
                rowData[pkIndex] = entityMeta.getIdGenerator().getId(entityMeta.getTableName(), signature, entityMeta.getBizIdRelatedColumns(), relatedColValue, null, idJdbcType, idLength, entityMeta.getBizIdSequenceSize());
                // 回写主键值
                BeanUtil.setProperty(entities.get(i), entityMeta.getIdArray()[0], rowData[pkIndex]);
            }
            if (hasBizId && StringUtil.isBlank(rowData[bizIdColIndex])) {
                rowData[bizIdColIndex] = entityMeta.getBusinessIdGenerator().getId(entityMeta.getTableName(), signature, entityMeta.getBizIdRelatedColumns(), relatedColValue, null, businessIdType, bizIdLength, entityMeta.getBizIdSequenceSize());
                // 回写业务主键值
                BeanUtil.setProperty(entities.get(i), entityMeta.getBusinessIdField(), rowData[bizIdColIndex]);
            }
        }
    }
    String saveAllNotExistSql = generateSqlHandler.generateSql(entityMeta, null);
    SqlExecuteStat.showSql("批量插入且忽视已存在记录", saveAllNotExistSql, null);
    return SqlUtil.batchUpdateByJdbc(sqlToyContext.getTypeHandler(), saveAllNotExistSql, paramValues, batchSize, null, entityMeta.getFieldsTypeArray(), autoCommit, conn, dbType);
}
Also used : ReflectPropsHandler(org.sagacity.sqltoy.callback.ReflectPropsHandler)

Example 3 with ReflectPropsHandler

use of org.sagacity.sqltoy.callback.ReflectPropsHandler in project sagacity-sqltoy by chenrenfei.

the class DialectUtils method updateAll.

/**
 * @todo 批量对象修改
 * @param sqlToyContext
 * @param entities
 * @param batchSize
 * @param forceUpdateFields
 * @param reflectPropsHandler
 * @param nullFunction
 * @param conn
 * @param dbType
 * @param autoCommit
 * @param tableName
 * @param skipNull
 * @return
 * @throws Exception
 */
public static Long updateAll(SqlToyContext sqlToyContext, List<?> entities, final int batchSize, final String[] forceUpdateFields, ReflectPropsHandler reflectPropsHandler, String nullFunction, Connection conn, final Integer dbType, final Boolean autoCommit, String tableName, boolean skipNull) throws Exception {
    if (entities == null || entities.isEmpty()) {
        return 0L;
    }
    EntityMeta entityMeta = sqlToyContext.getEntityMeta(entities.get(0).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;
    }
    // 构造全新的修改记录参数赋值反射(覆盖之前的)
    ReflectPropsHandler handler = getUpdateReflectHandler(reflectPropsHandler, forceUpdateFields, sqlToyContext.getUnifyFieldsHandler());
    handler = getSecureReflectHandler(handler, sqlToyContext.getFieldsSecureProvider(), sqlToyContext.getDesensitizeProvider(), entityMeta.getSecureFields());
    List<Object[]> paramsValues = BeanUtil.reflectBeansToInnerAry(entities, entityMeta.getFieldsArray(), null, handler);
    // 判断主键是否为空
    int pkIndex = entityMeta.getIdIndex();
    int end = pkIndex + entityMeta.getIdArray().length;
    int index = 0;
    // 累计多少行为空
    int skipCount = 0;
    Iterator<Object[]> iter = paramsValues.iterator();
    Object[] rowValues;
    while (iter.hasNext()) {
        rowValues = iter.next();
        for (int i = pkIndex; i < end; i++) {
            // 判断主键值是否为空
            if (StringUtil.isBlank(rowValues[i])) {
                // 跳过主键值为空的
                if (skipNull) {
                    skipCount++;
                    iter.remove();
                    break;
                } else {
                    throw new IllegalArgumentException("通过对象对表" + realTable + " 进行updateAll操作,主键字段必须要赋值!第:" + index + " 条记录主键为null!");
                }
            }
        }
        index++;
    }
    if (skipCount > 0) {
        if (logger.isDebugEnabled()) {
            logger.debug("共有{}行记录因为主键值为空跳过修改操作!", skipCount);
        } else {
            System.out.println("共有:" + skipCount + " 行记录因为主键值为空跳过修改操作!");
        }
    }
    // 构建update语句
    String updateSql = generateUpdateSql(dbType, entityMeta, nullFunction, forceUpdateFields, realTable);
    if (updateSql == null) {
        throw new IllegalArgumentException("updateAll sql is null,引起问题的原因是没有设置需要修改的字段!");
    }
    SqlExecuteStat.showSql("批量修改[" + paramsValues.size() + "]条记录", updateSql, null);
    if (dbType == DBType.SQLSERVER) {
        return SqlUtilsExt.batchUpdateBySqlServer(sqlToyContext.getTypeHandler(), updateSql, paramsValues, entityMeta.getFieldsTypeArray(), null, null, batchSize, autoCommit, conn, dbType);
    }
    return SqlUtilsExt.batchUpdateByJdbc(sqlToyContext.getTypeHandler(), updateSql, paramsValues, entityMeta.getFieldsTypeArray(), null, null, batchSize, autoCommit, conn, dbType);
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta) ReflectPropsHandler(org.sagacity.sqltoy.callback.ReflectPropsHandler)

Example 4 with ReflectPropsHandler

use of org.sagacity.sqltoy.callback.ReflectPropsHandler in project sagacity-sqltoy by chenrenfei.

the class DialectUtils method getSecureReflectHandler.

/**
 * @TODO 对字段值进行加密
 * @param preHandler
 * @param fieldsSecureProvider
 * @param desensitizeProvider
 * @param secureFields
 * @return
 */
public static ReflectPropsHandler getSecureReflectHandler(final ReflectPropsHandler preHandler, final FieldsSecureProvider fieldsSecureProvider, final DesensitizeProvider desensitizeProvider, List<FieldSecureConfig> secureFields) {
    if (fieldsSecureProvider == null || secureFields == null || secureFields.isEmpty()) {
        return preHandler;
    }
    ReflectPropsHandler handler = new ReflectPropsHandler() {

        @Override
        public void process() {
            if (preHandler != null) {
                preHandler.setPropertyIndexMap(this.getPropertyIndexMap());
                preHandler.setRowIndex(this.getRowIndex());
                preHandler.setRowData(this.getRowData());
                preHandler.process();
            }
            Object value;
            String contents;
            String field;
            String sourceField;
            // 加密操作
            for (FieldSecureConfig config : secureFields) {
                field = config.getField();
                sourceField = config.getSourceField();
                // 安全脱敏便于检索的字段,优先依据其来源加密字段
                if (StringUtil.isNotBlank(sourceField)) {
                    value = this.getValue(sourceField);
                } else {
                    value = this.getValue(field);
                }
                if (value != null) {
                    contents = value.toString();
                    if (!contents.equals("")) {
                        // 加密
                        if (config.getSecureType().equals(SecureType.ENCRYPT)) {
                            this.setValue(field, fieldsSecureProvider.encrypt(contents));
                        } else // 脱敏
                        {
                            this.setValue(field, desensitizeProvider.desensitize(contents, config.getMask()));
                        }
                    }
                }
            }
        }
    };
    return handler;
}
Also used : FieldSecureConfig(org.sagacity.sqltoy.config.model.FieldSecureConfig) ReflectPropsHandler(org.sagacity.sqltoy.callback.ReflectPropsHandler)

Example 5 with ReflectPropsHandler

use of org.sagacity.sqltoy.callback.ReflectPropsHandler 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;
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) TableCascadeModel(org.sagacity.sqltoy.config.model.TableCascadeModel) ReflectPropsHandler(org.sagacity.sqltoy.callback.ReflectPropsHandler) SqlToyResult(org.sagacity.sqltoy.config.model.SqlToyResult) ReturnPkType(org.sagacity.sqltoy.dialect.model.ReturnPkType) Type(java.lang.reflect.Type) SecureType(org.sagacity.sqltoy.model.SecureType) DBType(org.sagacity.sqltoy.utils.DataSourceUtils.DBType) List(java.util.List) ArrayList(java.util.ArrayList)

Aggregations

ReflectPropsHandler (org.sagacity.sqltoy.callback.ReflectPropsHandler)19 ArrayList (java.util.ArrayList)9 List (java.util.List)8 EntityMeta (org.sagacity.sqltoy.config.model.EntityMeta)6 HashMap (java.util.HashMap)5 TableCascadeModel (org.sagacity.sqltoy.config.model.TableCascadeModel)4 IOException (java.io.IOException)3 PreparedStatement (java.sql.PreparedStatement)3 ResultSet (java.sql.ResultSet)3 SQLException (java.sql.SQLException)3 Map (java.util.Map)3 PreparedStatementResultHandler (org.sagacity.sqltoy.callback.PreparedStatementResultHandler)3 IgnoreCaseSet (org.sagacity.sqltoy.model.IgnoreCaseSet)3 IgnoreKeyCaseMap (org.sagacity.sqltoy.model.IgnoreKeyCaseMap)3 Type (java.lang.reflect.Type)2 HashSet (java.util.HashSet)2 PKStrategy (org.sagacity.sqltoy.config.model.PKStrategy)2 SqlToyResult (org.sagacity.sqltoy.config.model.SqlToyResult)2 ReturnPkType (org.sagacity.sqltoy.dialect.model.ReturnPkType)2 DBType (org.sagacity.sqltoy.utils.DataSourceUtils.DBType)2