Search in sources :

Example 11 with FieldMeta

use of org.sagacity.sqltoy.config.model.FieldMeta in project sagacity-sqltoy by chenrenfei.

the class SqlToyDaoSupport method updateByQuery.

/**
 * @TODO 针对单表对象查询进行更新操作(update和delete 操作filters过滤是无效的,必须是精准的条件参数)
 * @param entityClass
 * @param entityUpdate
 * @update 2021-12-23 支持update table set field=field+1等计算模式
 * @return
 */
protected Long updateByQuery(Class entityClass, EntityUpdate entityUpdate) {
    if (null == entityClass || null == entityUpdate || StringUtil.isBlank(entityUpdate.getInnerModel().where) || StringUtil.isBlank(entityUpdate.getInnerModel().values) || entityUpdate.getInnerModel().updateValues.isEmpty()) {
        throw new IllegalArgumentException("updateByQuery: entityClass、where条件、条件值value、变更值setValues不能为空!");
    }
    EntityUpdateExtend innerModel = entityUpdate.getInnerModel();
    boolean isName = SqlConfigParseUtils.hasNamedParam(innerModel.where);
    Object[] values = innerModel.values;
    String[] paramNames = null;
    String where = innerModel.where;
    int valueSize = (values == null) ? 0 : values.length;
    // 重新通过对象反射获取参数条件的值
    if (isName) {
        if (values.length > 1) {
            throw new IllegalArgumentException("updateByQuery: where条件采用:paramName形式传参,values只能传递单个VO或Map对象!");
        }
        paramNames = SqlConfigParseUtils.getSqlParamsName(where, false);
        values = BeanUtil.reflectBeanToAry(values[0], paramNames);
        // 重新设置值数组的长度
        valueSize = values.length;
    } else {
        if (DialectUtils.getParamsCount(where) != valueSize) {
            throw new IllegalArgumentException("updateByQuery: where语句中的?数量跟对应values 数组长度不一致,请检查!");
        }
    }
    EntityMeta entityMeta = getEntityMeta(entityClass);
    // 处理where 中写的java 字段名称为数据库表字段名称
    where = SqlUtil.convertFieldsToColumns(entityMeta, where);
    StringBuilder sql = new StringBuilder();
    sql.append("update ").append(entityMeta.getSchemaTable(null, null)).append(" set ");
    Entry<String, Object> entry;
    // 对统一更新字段做处理
    IUnifyFieldsHandler unifyHandler = getSqlToyContext().getUnifyFieldsHandler();
    if (unifyHandler != null) {
        Map<String, Object> updateFields = unifyHandler.updateUnifyFields();
        if (updateFields != null && !updateFields.isEmpty()) {
            Iterator<Entry<String, Object>> updateIter = updateFields.entrySet().iterator();
            while (updateIter.hasNext()) {
                entry = updateIter.next();
                // 是数据库表的字段
                if (entityMeta.getColumnName(entry.getKey()) != null) {
                    // 是否已经主动update
                    if (innerModel.updateValues.containsKey(entry.getKey())) {
                        // 判断是否存在强制更新
                        if (unifyHandler.forceUpdateFields() != null && unifyHandler.forceUpdateFields().contains(entry.getKey())) {
                            innerModel.updateValues.put(entry.getKey(), entry.getValue());
                        }
                    } else {
                        innerModel.updateValues.put(entry.getKey(), entry.getValue());
                    }
                }
            }
        }
    }
    Object[] realValues = new Object[innerModel.updateValues.size() + valueSize];
    if (valueSize > 0) {
        System.arraycopy(values, 0, realValues, innerModel.updateValues.size(), valueSize);
    }
    Integer[] paramsTypes = new Integer[realValues.length];
    for (int i = 0; i < paramsTypes.length; i++) {
        paramsTypes[i] = java.sql.Types.OTHER;
    }
    String[] realNames = null;
    if (isName) {
        realNames = new String[realValues.length];
        System.arraycopy(paramNames, 0, realNames, innerModel.updateValues.size(), valueSize);
    }
    int index = 0;
    String columnName;
    FieldMeta fieldMeta;
    Iterator<Entry<String, Object>> iter = innerModel.updateValues.entrySet().iterator();
    String[] fields;
    String fieldSetValue;
    // 设置一个扩展标志,避免set field=field+? 场景构造成field=field+:fieldExtParam跟where
    // field=:field名称冲突
    final String extSign = "ExtParam";
    while (iter.hasNext()) {
        entry = iter.next();
        // 考虑 field=filed+? 模式,分割成2部分
        fields = entry.getKey().split("=");
        fieldMeta = entityMeta.getFieldMeta(fields[0].trim());
        // entry.getKey() 直接是数据库字段名称
        if (fieldMeta == null) {
            // 先通过数据字段名称获得类的属性名称再获取fieldMeta
            fieldMeta = entityMeta.getFieldMeta(entityMeta.getColumnFieldMap().get(fields[0].trim().toLowerCase()));
        }
        columnName = fieldMeta.getColumnName();
        // 设置字段类型
        if (fields.length == 1) {
            paramsTypes[index] = fieldMeta.getType();
        }
        // 保留字处理
        columnName = ReservedWordsUtil.convertWord(columnName, null);
        if (isName) {
            if (fields.length > 1) {
                if (fields[1].contains("?")) {
                    // 拼接扩展字符,避免where后面有同样的参数名称
                    realNames[index] = fieldMeta.getFieldName().concat(extSign);
                } else {
                    realNames[index] = SqlConfigParseUtils.getSqlParamsName(fields[1], true)[0];
                }
            } else {
                realNames[index] = fieldMeta.getFieldName();
            }
        }
        realValues[index] = entry.getValue();
        if (index > 0) {
            sql.append(",");
        }
        if (fields.length == 1) {
            sql.append(columnName).append("=").append(isName ? (":" + fieldMeta.getFieldName()) : "?");
        } else {
            // field=filed+? 类似模式
            fieldSetValue = fields[1];
            sql.append(columnName).append("=");
            if (isName && fieldSetValue.contains("?")) {
                fieldSetValue = fieldSetValue.replace("?", ":" + fieldMeta.getFieldName().concat(extSign));
            }
            fieldSetValue = SqlUtil.convertFieldsToColumns(entityMeta, fieldSetValue);
            sql.append(fieldSetValue);
        }
        index++;
    }
    sql.append(" where ").append(where);
    String sqlStr = sql.toString();
    SqlToyConfig sqlToyConfig = sqlToyContext.getSqlToyConfig(sqlStr, SqlType.update, getDialect(innerModel.dataSource));
    QueryExecutor queryExecutor = new QueryExecutor(sqlStr).names(realNames).values(realValues);
    setEntitySharding(queryExecutor, entityMeta);
    return dialectFactory.executeSql(sqlToyContext, sqlToyConfig, queryExecutor, paramsTypes, null, getDataSource(innerModel.dataSource, sqlToyConfig));
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta) SqlToyConfig(org.sagacity.sqltoy.config.model.SqlToyConfig) FieldMeta(org.sagacity.sqltoy.config.model.FieldMeta) EntityUpdateExtend(org.sagacity.sqltoy.model.inner.EntityUpdateExtend) IUnifyFieldsHandler(org.sagacity.sqltoy.plugins.IUnifyFieldsHandler) Entry(java.util.Map.Entry) ParallQueryExecutor(org.sagacity.sqltoy.dialect.executor.ParallQueryExecutor) QueryExecutor(org.sagacity.sqltoy.model.QueryExecutor)

Example 12 with FieldMeta

use of org.sagacity.sqltoy.config.model.FieldMeta 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();
    }
}
Also used : EntityMeta(org.sagacity.sqltoy.config.model.EntityMeta) HashMap(java.util.HashMap) FieldMeta(org.sagacity.sqltoy.config.model.FieldMeta) Connection(java.sql.Connection) DataSourceCallbackHandler(org.sagacity.sqltoy.callback.DataSourceCallbackHandler) DataAccessException(org.sagacity.sqltoy.exception.DataAccessException) Type(java.lang.reflect.Type) DBType(org.sagacity.sqltoy.utils.DataSourceUtils.DBType) DataAccessException(org.sagacity.sqltoy.exception.DataAccessException)

Example 13 with FieldMeta

use of org.sagacity.sqltoy.config.model.FieldMeta in project sagacity-sqltoy by chenrenfei.

the class EntityManager method parseSecureConfig.

/**
 * @todo 解析加解密配置
 * @param entityMeta
 * @param entityClass
 */
private void parseSecureConfig(EntityMeta entityMeta, Class entityClass) {
    Class classType = entityClass;
    SecureConfig secureConfig = null;
    // 增加递归对父类检测
    while (classType != null && !classType.equals(Object.class)) {
        secureConfig = (SecureConfig) classType.getAnnotation(SecureConfig.class);
        if (secureConfig != null) {
            break;
        }
        classType = classType.getSuperclass();
    }
    // 不存在加解密配置
    if (secureConfig == null) {
        return;
    }
    Secure[] secures = secureConfig.secures();
    if (secures != null && secures.length > 0) {
        IgnoreCaseSet secureColumns = new IgnoreCaseSet();
        String field;
        FieldMeta fieldMeta;
        for (Secure secure : secures) {
            field = secure.field();
            fieldMeta = entityMeta.getFieldMeta(field);
            if (fieldMeta != null) {
                // 加密
                if (secure.secureType().equals(SecureType.ENCRYPT)) {
                    secureColumns.add(fieldMeta.getColumnName());
                    entityMeta.addSecureField(new FieldSecureConfig(field, SecureType.ENCRYPT, null, null, 0, 0, 0));
                } else {
                    // 依据加密字段进行脱敏保存
                    entityMeta.addSecureField(new FieldSecureConfig(field, secure.secureType(), secure.sourceField(), secure.maskCode(), secure.headSize(), secure.tailSize(), secure.maskRate()));
                }
            }
        }
        // 加密字段
        if (!secureColumns.isEmpty()) {
            entityMeta.setSecureColumns(secureColumns);
        }
    }
}
Also used : FieldSecureConfig(org.sagacity.sqltoy.config.model.FieldSecureConfig) Secure(org.sagacity.sqltoy.config.annotation.Secure) FieldMeta(org.sagacity.sqltoy.config.model.FieldMeta) SecureConfig(org.sagacity.sqltoy.config.annotation.SecureConfig) FieldSecureConfig(org.sagacity.sqltoy.config.model.FieldSecureConfig) IgnoreCaseSet(org.sagacity.sqltoy.model.IgnoreCaseSet)

Example 14 with FieldMeta

use of org.sagacity.sqltoy.config.model.FieldMeta in project sagacity-sqltoy by chenrenfei.

the class EntityManager method parseFieldMeta.

/**
 * @todo 解析对象属性跟数据库表字段的信息
 * @param sqlToyContext
 * @param entityMeta
 * @param field
 * @param rejectIdFieldList
 * @param allFieldAry
 * @param loadNamedWhereSql
 * @param loadArgWhereSql
 * @throws Exception
 */
private void parseFieldMeta(SqlToyContext sqlToyContext, EntityMeta entityMeta, Field field, List<String> rejectIdFieldList, List<String> allFieldAry, StringBuilder loadNamedWhereSql, StringBuilder loadArgWhereSql) throws Exception {
    Column column = field.getAnnotation(Column.class);
    if (column == null) {
        return;
    }
    // 字段的详细配置信息,字段名称,字段对应数据库表字段,字段默认值,字段类型
    FieldMeta fieldMeta = new FieldMeta(field.getName(), column.name(), (SqlToyConstants.DEFAULT_NULL.equals(column.defaultValue())) ? null : column.defaultValue(), column.type(), column.nullable(), column.keyword(), Long.valueOf(column.length()).intValue(), column.precision(), column.scale());
    // 增加字段
    allFieldAry.add(column.name());
    // 字段是否自增
    fieldMeta.setAutoIncrement(column.autoIncrement());
    // 设置type类型,并转小写便于后续对比的统一
    fieldMeta.setFieldType(field.getType().getTypeName().toLowerCase());
    // 设置是否分区字段
    if (field.getAnnotation(PartitionKey.class) != null) {
        fieldMeta.setPartitionKey(true);
    }
    // 内部包含了构造表字段名称跟vo属性名称的对照
    entityMeta.addFieldMeta(fieldMeta);
    // 判断字段是否为主键
    Id id = field.getAnnotation(Id.class);
    String idColName;
    if (id != null) {
        fieldMeta.setPK(true);
        // 主键生成策略
        entityMeta.setIdStrategy(PKStrategy.getPKStrategy(id.strategy().toLowerCase()));
        entityMeta.setSequence(id.sequence());
        String idGenerator = id.generator();
        if (StringUtil.isNotBlank(idGenerator)) {
            processIdGenerator(sqlToyContext, entityMeta, idGenerator);
            entityMeta.setIdGenerator(idGenerators.get(idGenerator));
        }
        if (loadNamedWhereSql.length() > 1) {
            loadNamedWhereSql.append(" and ");
            loadArgWhereSql.append(" and ");
        } else {
            loadNamedWhereSql.append(" where ");
            loadArgWhereSql.append(" where ");
        }
        idColName = ReservedWordsUtil.convertWord(column.name(), null);
        loadNamedWhereSql.append(idColName).append("=:").append(field.getName());
        loadArgWhereSql.append(idColName).append("=?");
    } else {
        rejectIdFieldList.add(field.getName());
    }
    // 业务主键策略配置解析
    BusinessId bizId = field.getAnnotation(BusinessId.class);
    if (bizId != null && StringUtil.isNotBlank(bizId.generator())) {
        String bizGenerator = bizId.generator();
        entityMeta.setBizIdLength(bizId.length());
        entityMeta.setBizIdSignature(bizId.signature());
        entityMeta.setHasBizIdConfig(true);
        entityMeta.setBizIdSequenceSize(bizId.sequenceSize());
        entityMeta.setBusinessIdField(field.getName());
        // 生成业务主键关联的字段(主键值生成需要其他字段的值进行组合,入交易业务ID组合交易类别码等)
        if (bizId.relatedColumns() != null && bizId.relatedColumns().length > 0) {
            entityMeta.setBizIdRelatedColumns(bizId.relatedColumns());
        }
        processIdGenerator(sqlToyContext, entityMeta, bizGenerator);
        // 如果是业务主键跟ID重叠,则ID以业务主键策略生成
        if (id != null) {
            entityMeta.setIdGenerator(idGenerators.get(bizGenerator));
            fieldMeta.setLength(bizId.length());
            entityMeta.setBizIdEqPK(true);
        } else {
            entityMeta.setBusinessIdGenerator(idGenerators.get(bizGenerator));
        }
    }
}
Also used : Column(org.sagacity.sqltoy.config.annotation.Column) FieldMeta(org.sagacity.sqltoy.config.model.FieldMeta) PartitionKey(org.sagacity.sqltoy.config.annotation.PartitionKey) Id(org.sagacity.sqltoy.config.annotation.Id) BusinessId(org.sagacity.sqltoy.config.annotation.BusinessId) BusinessId(org.sagacity.sqltoy.config.annotation.BusinessId)

Example 15 with FieldMeta

use of org.sagacity.sqltoy.config.model.FieldMeta in project sagacity-sqltoy by chenrenfei.

the class EntityManager method parseFieldTypeAndDefault.

/**
 * @todo 设置字段类型和默认值
 * @param entityMeta
 */
private void parseFieldTypeAndDefault(EntityMeta entityMeta) {
    // 组织对象对应表字段的类型和默认值以及是否可以为null
    int fieldSize = entityMeta.getFieldsArray().length;
    Integer[] fieldsTypeArray = new Integer[fieldSize];
    String[] fieldsDefaultValue = new String[fieldSize];
    Boolean[] fieldsNullable = new Boolean[fieldSize];
    FieldMeta fieldMeta;
    for (int i = 0; i < fieldSize; i++) {
        fieldMeta = entityMeta.getFieldMeta(entityMeta.getFieldsArray()[i]);
        fieldsTypeArray[i] = fieldMeta.getType();
        fieldsDefaultValue[i] = fieldMeta.getDefaultValue();
        fieldsNullable[i] = fieldMeta.isNullable();
    }
    entityMeta.setFieldsTypeArray(fieldsTypeArray);
    entityMeta.setFieldsDefaultValue(fieldsDefaultValue);
    entityMeta.setFieldsNullable(fieldsNullable);
}
Also used : FieldMeta(org.sagacity.sqltoy.config.model.FieldMeta)

Aggregations

FieldMeta (org.sagacity.sqltoy.config.model.FieldMeta)29 HashSet (java.util.HashSet)8 HashMap (java.util.HashMap)7 EntityMeta (org.sagacity.sqltoy.config.model.EntityMeta)6 Test (org.junit.jupiter.api.Test)3 BusinessId (org.sagacity.sqltoy.config.annotation.BusinessId)2 Column (org.sagacity.sqltoy.config.annotation.Column)2 Id (org.sagacity.sqltoy.config.annotation.Id)2 DataAccessException (org.sagacity.sqltoy.exception.DataAccessException)2 Serializable (java.io.Serializable)1 Type (java.lang.reflect.Type)1 Connection (java.sql.Connection)1 PreparedStatement (java.sql.PreparedStatement)1 ResultSet (java.sql.ResultSet)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 Entry (java.util.Map.Entry)1 DataSourceCallbackHandler (org.sagacity.sqltoy.callback.DataSourceCallbackHandler)1 PreparedStatementResultHandler (org.sagacity.sqltoy.callback.PreparedStatementResultHandler)1 PartitionKey (org.sagacity.sqltoy.config.annotation.PartitionKey)1