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));
}
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();
}
}
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);
}
}
}
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));
}
}
}
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);
}
Aggregations