use of org.sagacity.sqltoy.exception.DataAccessException in project sagacity-sqltoy by chenrenfei.
the class ResultUtils method hiberarchySet.
/**
* @TODO 将集合数据反射到java对象并建立层次关系
* @param sqlToyContext
* @param entityMeta
* @param columnFieldMap
* @param queryResultRows
* @param labelNames
* @param resultType
* @param cascadeModel
* @param hiberarchyClasses
* @param fieldsMap
* @return
* @throws Exception
*/
private static List hiberarchySet(SqlToyContext sqlToyContext, EntityMeta entityMeta, HashMap<String, String> columnFieldMap, List queryResultRows, String[] labelNames, Class resultType, List<TableCascadeModel> cascadeModel, Class[] hiberarchyClasses, Map<Class, IgnoreKeyCaseMap<String, String>> fieldsMap) throws Exception {
// 获得所有层次关系的分组字段
String[] groupFields = cascadeModel.get(0).getFields();
int groupSize = groupFields.length;
int[] colIndexs = new int[groupSize];
IgnoreKeyCaseMap<String, Integer> labelIndexs = new IgnoreKeyCaseMap<String, Integer>();
int index = 0;
for (String label : labelNames) {
labelIndexs.put(label.replace("_", ""), index);
index++;
}
for (int i = 0; i < groupSize; i++) {
if (labelIndexs.containsKey(groupFields[i])) {
colIndexs[i] = labelIndexs.get(groupFields[i]);
} else {
throw new DataAccessException("查询结果中未包含属性:" + groupFields[i] + " 对应的值!");
}
}
// 判断是否存在oneToMany
boolean hasOneToMany = false;
for (TableCascadeModel cascade : cascadeModel) {
if (cascade.getCascadeType() == 1) {
hasOneToMany = true;
break;
}
}
// 分组的master数据
List masterData;
LinkedHashMap<String, List> groupListMap = null;
Iterator<List> groupListIter;
// 存在oneToMany 则将数据进行分组
if (hasOneToMany) {
groupListMap = hashGroupList(queryResultRows, colIndexs);
// 提取每组的第一条数据作为master数据
groupListIter = groupListMap.values().iterator();
masterData = new ArrayList();
while (groupListIter.hasNext()) {
masterData.add(groupListIter.next().get(0));
}
} else {
masterData = queryResultRows;
}
// 构造主对象集合
List result = BeanUtil.reflectListToBean(sqlToyContext.getTypeHandler(), masterData, convertRealProps(wrapMapFields(labelNames, fieldsMap, resultType), columnFieldMap), resultType);
List<List> oneToOnes = new ArrayList();
List<String> oneToOneProps = new ArrayList<String>();
TableCascadeModel oneToMany = null;
int oneToManySize = 0;
for (TableCascadeModel cascade : cascadeModel) {
// oneToOne模式
if (cascade.getCascadeType() == 2) {
boolean hasCascade = false;
if (hiberarchyClasses != null) {
for (Class hiberarchyClass : hiberarchyClasses) {
if (hiberarchyClass.equals(cascade.getMappedType())) {
hasCascade = true;
break;
}
}
} else {
hasCascade = true;
}
// 将多个oneToOne的数据批量构造
if (hasCascade) {
// 主对象字段属性转化为级联对象属性
if (cascade.getMappedFields() != null && cascade.getMappedFields().length > 0) {
for (int i = 0; i < groupSize; i++) {
labelNames[colIndexs[i]] = cascade.getMappedFields()[i];
}
}
columnFieldMap = null;
if (entityMeta != null && sqlToyContext.isEntity(cascade.getMappedType())) {
columnFieldMap = sqlToyContext.getEntityMeta(cascade.getMappedType()).getColumnFieldMap();
}
List oneToOneList = BeanUtil.reflectListToBean(sqlToyContext.getTypeHandler(), masterData, convertRealProps(wrapMapFields(labelNames, fieldsMap, cascade.getMappedType()), columnFieldMap), cascade.getMappedType());
wrapResultTranslate(sqlToyContext, oneToOneList, cascade.getMappedType());
oneToOnes.add(oneToOneList);
oneToOneProps.add(cascade.getProperty());
}
} else // 只支持一个oneToMany
{
// 指定了级联对象
if (hiberarchyClasses != null) {
for (Class hiberarchyClass : hiberarchyClasses) {
if (hiberarchyClass.equals(cascade.getMappedType())) {
oneToMany = cascade;
break;
}
}
} else {
// 不指定则以第一个为准
if (oneToMany == null) {
oneToMany = cascade;
}
oneToManySize++;
}
}
}
if (oneToManySize > 1 && hiberarchyClasses == null) {
throw new IllegalArgumentException("返回依照层次结构结果时,存在多个oneToMany映射关系,必须要指明hiberarchyClasses!");
}
Object masterBean;
// 循环将oneToOne 的一一通过反射赋值到主对象属性上
if (!oneToOneProps.isEmpty()) {
int oneToOneSize = oneToOneProps.size();
for (int i = 0, n = result.size(); i < n; i++) {
masterBean = result.get(i);
for (int j = 0; j < oneToOneSize; j++) {
BeanUtil.setProperty(masterBean, oneToOneProps.get(j), oneToOnes.get(j).get(i));
}
}
}
// 处理oneToMany
if (oneToMany != null) {
// 变化级联子对象的属性
if (oneToMany.getMappedFields() != null && oneToMany.getMappedFields().length > 0) {
for (int i = 0; i < groupSize; i++) {
labelNames[colIndexs[i]] = oneToMany.getMappedFields()[i];
}
}
Class oneToManyClass = oneToMany.getMappedType();
columnFieldMap = null;
if (entityMeta != null && sqlToyContext.isEntity(oneToManyClass)) {
columnFieldMap = sqlToyContext.getEntityMeta(oneToManyClass).getColumnFieldMap();
}
List item;
String property = oneToMany.getProperty();
// 循环分组Map
groupListIter = groupListMap.values().iterator();
index = 0;
while (groupListIter.hasNext()) {
masterBean = result.get(index);
item = BeanUtil.reflectListToBean(sqlToyContext.getTypeHandler(), groupListIter.next(), convertRealProps(wrapMapFields(labelNames, fieldsMap, oneToManyClass), columnFieldMap), oneToManyClass);
// 处理类上@Translate注解进行缓存翻译
wrapResultTranslate(sqlToyContext, item, oneToManyClass);
// 将子对象集合写到主对象属性上
BeanUtil.setProperty(masterBean, property, item);
index++;
}
}
return result;
}
use of org.sagacity.sqltoy.exception.DataAccessException in project sagacity-sqltoy by chenrenfei.
the class ResultUtils method getMoreLinkResultSet.
/**
* @TODO 实现多列link
* @param sqlToyConfig
* @param sqlToyContext
* @param decryptHandler
* @param conn
* @param rs
* @param rowCnt
* @param labelIndexMap
* @param labelNames
* @param startColIndex
* @return
* @throws Exception
*/
private static List getMoreLinkResultSet(SqlToyConfig sqlToyConfig, SqlToyContext sqlToyContext, DecryptHandler decryptHandler, Connection conn, ResultSet rs, int rowCnt, HashMap<String, Integer> labelIndexMap, String[] labelNames, int startColIndex) throws Exception {
// 字段连接(多行数据拼接成一个数据,以一行显示)
LinkModel linkModel = sqlToyConfig.getLinkModel();
List<List> items = new ArrayList();
// 判断是否有缓存翻译器定义
Boolean hasTranslate = (sqlToyConfig.getTranslateMap().isEmpty()) ? false : true;
HashMap<String, Translate> translateMap = sqlToyConfig.getTranslateMap();
HashMap<String, HashMap<String, Object[]>> translateCache = null;
if (hasTranslate) {
translateCache = sqlToyContext.getTranslateManager().getTranslates(translateMap);
if (translateCache == null || translateCache.isEmpty()) {
hasTranslate = false;
logger.debug("通过缓存配置未获取到缓存数据,请正确配置TranslateManager!");
}
}
// link 目前只支持单个字段运算
int columnSize = labelNames.length;
int index = 0;
// 警告阀值
int warnThresholds = SqlToyConstants.getWarnThresholds();
boolean warnLimit = false;
// 最大阀值
long maxThresholds = SqlToyConstants.getMaxThresholds();
boolean maxLimit = false;
// 是否判断全部为null的行记录
boolean ignoreAllEmpty = sqlToyConfig.isIgnoreEmpty();
// 最大值要大于等于警告阀值
if (maxThresholds > 1 && maxThresholds <= warnThresholds) {
maxThresholds = warnThresholds;
}
int linkCols = linkModel.getColumns().length;
String[] linkColumns = linkModel.getColumns();
int[] linkIndexs = new int[linkCols];
StringBuilder[] linkBuffers = new StringBuilder[linkCols];
Set<String>[] linkSets = linkModel.isDistinct() ? new HashSet[linkCols] : null;
boolean[] translateLinks = new boolean[linkCols];
TranslateExtend[] transExtends = new TranslateExtend[linkCols];
String linkColumnLow;
for (int i = 0; i < linkCols; i++) {
linkBuffers[i] = new StringBuilder();
linkColumnLow = linkColumns[i].toLowerCase();
if (!labelIndexMap.containsKey(linkColumnLow)) {
throw new DataAccessException("做link操作时,查询结果字段中没有字段:" + linkColumnLow + ",请检查sql或link 配置的正确性!");
}
linkIndexs[i] = labelIndexMap.get(linkColumnLow);
if (hasTranslate) {
translateLinks[i] = translateMap.containsKey(linkColumnLow);
if (translateLinks[i]) {
transExtends[i] = translateMap.get(linkColumnLow).getExtend();
}
}
if (linkModel.isDistinct()) {
linkSets[i] = new HashSet<String>();
}
}
// link是否有修饰器
boolean hasDecorate = (linkModel.getDecorateAppendChar() == null) ? false : true;
boolean isLeft = true;
if (hasDecorate) {
isLeft = linkModel.getDecorateAlign().equals("left") ? true : false;
}
Object preIdentity = null;
Object[] linkValues = new Object[linkCols];
String[] linkStrs = new String[linkCols];
TranslateExtend extend = null;
Object[] cacheValues;
List rowTemp;
Object identity = null;
// 判断link拼接是否重新开始
boolean isLastProcess = false;
boolean doLink = false;
while (rs.next()) {
isLastProcess = false;
// 对多个link字段取值并进行翻译转义
for (int i = 0; i < linkCols; i++) {
linkValues[i] = rs.getObject(linkColumns[i]);
if (linkValues[i] == null) {
linkStrs[i] = "";
} else {
if (translateLinks[i]) {
extend = transExtends[i];
cacheValues = translateCache.get(extend.column).get(linkValues[i].toString());
if (cacheValues == null) {
linkStrs[i] = "[" + linkValues[i] + "]未匹配";
logger.debug("translate cache:{},cacheType:{}, 对应的key:{} 没有设置相应的value!", extend.cache, extend.cacheType, linkValues[i]);
} else {
linkStrs[i] = (cacheValues[extend.index] == null) ? "" : cacheValues[extend.index].toString();
}
} else {
linkStrs[i] = linkValues[i].toString();
}
}
}
// 取分组列的值
identity = (linkModel.getIdColumns() == null) ? "default" : getLinkColumnsId(rs, linkModel.getIdColumns());
// 不相等
if (!identity.equals(preIdentity)) {
// 不相等时先对最后一条记录修改,写入拼接后的字符串
if (index != 0) {
rowTemp = items.get(items.size() - 1);
for (int i = 0; i < linkCols; i++) {
rowTemp.set(linkIndexs[i], linkBuffers[i].toString());
linkBuffers[i].delete(0, linkBuffers[i].length());
// 清除
if (linkModel.isDistinct()) {
linkSets[i].clear();
}
}
}
// 再写入新的拼接串
for (int i = 0; i < linkCols; i++) {
linkBuffers[i].append(linkStrs[i]);
if (linkModel.isDistinct()) {
linkSets[i].add(linkStrs[i]);
}
}
// 提取result中的数据(identity相等时不需要提取)
if (hasTranslate) {
rowTemp = processResultRowWithTranslate(translateMap, translateCache, labelNames, rs, columnSize, decryptHandler, ignoreAllEmpty);
} else {
rowTemp = processResultRow(rs, labelNames, columnSize, decryptHandler, ignoreAllEmpty);
}
if (rowTemp != null) {
items.add(rowTemp);
}
preIdentity = identity;
} else {
isLastProcess = true;
// identity相同,表示还在同一组内,直接拼接link字符
for (int i = 0; i < linkCols; i++) {
doLink = true;
// 判断是否已经重复
if (linkModel.isDistinct()) {
if (linkSets[i].contains(linkStrs[i])) {
doLink = false;
}
linkSets[i].add(linkStrs[i]);
}
if (doLink) {
if (linkBuffers[i].length() > 0) {
linkBuffers[i].append(linkModel.getSign());
}
linkBuffers[i].append(hasDecorate ? StringUtil.appendStr(linkStrs[i], linkModel.getDecorateAppendChar(), linkModel.getDecorateSize(), isLeft) : linkStrs[i]);
}
}
}
index++;
// 存在超出25000条数据的查询
if (index == warnThresholds) {
warnLimit = true;
}
// 提取数据超过上限(-1表示不限制)
if (index == maxThresholds) {
maxLimit = true;
break;
}
}
// 数据集合不为空,对最后一条记录写入循环值
if (isLastProcess) {
rowTemp = items.get(items.size() - 1);
for (int i = 0; i < linkCols; i++) {
rowTemp.set(linkIndexs[i], linkBuffers[i].toString());
}
}
// 超出警告阀值
if (warnLimit) {
warnLog(sqlToyConfig, index);
}
// 超过最大提取数据阀值
if (maxLimit) {
logger.error("MaxLargeResult:执行sql提取数据超出最大阀值限制{},sqlId={},具体语句={}", index, sqlToyConfig.getId(), sqlToyConfig.getSql(null));
}
return items;
}
use of org.sagacity.sqltoy.exception.DataAccessException in project sagacity-sqltoy by chenrenfei.
the class Mongo method findTop.
/**
* @todo 查询前多少条记录
* @param topSize
* @return
*/
public List<?> findTop(final Float topSize) {
QueryExecutor queryExecutor = build();
SqlToyConfig sqlToyConfig = sqlToyContext.getSqlToyConfig(sql, SqlType.search, "");
NoSqlConfigModel noSqlModel = sqlToyConfig.getNoSqlConfigModel();
if (noSqlModel == null || noSqlModel.getCollection() == null || noSqlModel.getFields() == null) {
throw new IllegalArgumentException(ERROR_MESSAGE);
}
try {
QueryExecutorExtend extend = queryExecutor.getInnerModel();
// 最后的执行语句
String realMql = MongoElasticUtils.wrapMql(sqlToyConfig, extend.getParamsName(sqlToyConfig), extend.getParamsValue(sqlToyContext, sqlToyConfig));
return findTop(getMongoTemplate(), sqlToyConfig, topSize, realMql, (Class) extend.resultType, extend.humpMapLabel);
} catch (Exception e) {
e.printStackTrace();
throw new DataAccessException(e);
}
}
use of org.sagacity.sqltoy.exception.DataAccessException in project sagacity-sqltoy by chenrenfei.
the class Mongo method findPage.
/**
* @todo 分页查询
* @param page
* @return
*/
public Page findPage(Page page) {
QueryExecutor queryExecutor = build();
SqlToyConfig sqlToyConfig = sqlToyContext.getSqlToyConfig(sql, SqlType.search, "");
NoSqlConfigModel noSqlModel = sqlToyConfig.getNoSqlConfigModel();
if (noSqlModel == null || noSqlModel.getCollection() == null || noSqlModel.getFields() == null) {
throw new IllegalArgumentException(ERROR_MESSAGE);
}
try {
QueryExecutorExtend extend = queryExecutor.getInnerModel();
// 最后的执行语句
String realMql = MongoElasticUtils.wrapMql(sqlToyConfig, extend.getParamsName(sqlToyConfig), extend.getParamsValue(sqlToyContext, sqlToyConfig));
return findPage(getMongoTemplate(), sqlToyConfig, page, realMql, (Class) extend.resultType, extend.humpMapLabel);
} catch (Exception e) {
e.printStackTrace();
throw new DataAccessException(e);
}
}
use of org.sagacity.sqltoy.exception.DataAccessException in project sagacity-sqltoy by chenrenfei.
the class SqlScriptLoader method getSqlConfig.
/**
* @todo 提供根据sql或sqlId获取sql配置模型
* @param sqlKey
* @param sqlType
* @param dialect
* @return
*/
public SqlToyConfig getSqlConfig(String sqlKey, SqlType sqlType, String dialect) {
if (StringUtil.isBlank(sqlKey)) {
throw new IllegalArgumentException("sql or sqlId is null!");
}
SqlToyConfig result = null;
String realDialect = (dialect == null) ? "" : dialect.toLowerCase();
// sqlId形式
if (SqlConfigParseUtils.isNamedQuery(sqlKey)) {
if (!realDialect.equals("")) {
// sqlId_dialect
result = sqlCache.get(sqlKey.concat("_").concat(realDialect));
// dialect_sqlId
if (result == null) {
result = sqlCache.get(realDialect.concat("_").concat(sqlKey));
}
// 兼容一下sqlserver的命名
if (result == null && realDialect.equals(Dialect.SQLSERVER)) {
result = sqlCache.get(sqlKey.concat("_mssql"));
if (result == null) {
result = sqlCache.get("mssql_".concat(sqlKey));
}
}
// 兼容一下postgres的命名
if (result == null && realDialect.equals(Dialect.POSTGRESQL)) {
result = sqlCache.get(sqlKey.concat("_postgres"));
if (result == null) {
result = sqlCache.get("postgres_".concat(sqlKey));
}
}
}
if (result == null) {
result = sqlCache.get(sqlKey);
if (result == null) {
throw new DataAccessException("\n发生错误:sqlId=[" + sqlKey + "]无对应的sql配置,请检查对应的sql.xml文件是否被正确加载!\n" + "/*----------------------错误可能的原因如下---------------------*/\n" + "/* 1、检查: spring.sqltoy.sqlResourcesDir=[" + sqlResourcesDir + "]配置(如:字母拼写),会导致sql文件没有被加载;\n" + "/* 2、sql.xml文件没有被编译到classes目录下面;请检查maven的编译配置 \n" + "/* 3、sqlId对应的文件内部错误!版本合并或书写错误会导致单个文件解析错误 \n" + "/* ------------------------------------------------------------*/");
}
}
} else {
result = codeSqlCache.get(sqlKey);
if (result == null) {
result = SqlConfigParseUtils.parseSqlToyConfig(sqlKey, realDialect, sqlType);
// 设置默认空白查询条件过滤filter,便于直接传递sql语句情况下查询条件的处理
result.addFilter(new ParamFilterModel("blank", new String[] { "*" }));
// 限制数量的原因是存在部分代码中的sql会拼接条件参数值,导致不同的sql无限增加
if (codeSqlCache.size() < SqlToyConstants.getMaxCodeSqlCount()) {
codeSqlCache.put(sqlKey, result);
}
}
}
return result;
}
Aggregations