use of org.sagacity.sqltoy.model.inner.TranslateExtend 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.model.inner.TranslateExtend in project sagacity-sqltoy by chenrenfei.
the class ResultUtils method wrapResultTranslate.
/**
* @TODO 对返回POJO(或DTO)含@Translate 配置的结果进行缓存翻译处理,通过key属性的值翻译成名称反射到当前名称属性上
* @param sqlToyContext
* @param result
* @param resultType
*/
public static void wrapResultTranslate(SqlToyContext sqlToyContext, Object result, Class resultType) {
HashMap<String, Translate> translateConfig = TranslateConfigParse.getClassTranslates(resultType);
if (result == null || translateConfig == null || translateConfig.isEmpty()) {
return;
}
// 获取缓存数据
HashMap<String, HashMap<String, Object[]>> cacheDatas = sqlToyContext.getTranslateManager().getTranslates(translateConfig);
List voList;
if (result instanceof List) {
voList = (List) result;
} else {
voList = new ArrayList();
voList.add(result);
}
if (voList.isEmpty()) {
return;
}
Object item;
String field = null;
TranslateExtend trans;
Object srcFieldValue;
Object fieldValue;
HashMap<String, Object[]> cacheData;
try {
for (int i = 0; i < voList.size(); i++) {
item = voList.get(i);
for (Map.Entry<String, Translate> entry : translateConfig.entrySet()) {
field = entry.getKey();
trans = entry.getValue().getExtend();
// column是field小写后的值
cacheData = cacheDatas.get(trans.column);
srcFieldValue = BeanUtil.getProperty(item, trans.keyColumn);
fieldValue = BeanUtil.getProperty(item, field);
if (srcFieldValue != null && !srcFieldValue.toString().equals("") && fieldValue == null) {
BeanUtil.setProperty(item, field, translateKey(trans, cacheData, srcFieldValue));
}
}
}
} catch (Exception e) {
e.printStackTrace();
logger.error("针对类:{} 的属性:{} 进行缓存翻译发生异常!{}", resultType.getName(), field, e.getMessage());
}
}
use of org.sagacity.sqltoy.model.inner.TranslateExtend in project sagacity-sqltoy by chenrenfei.
the class EntityQuery method translates.
/**
* @TODO 对sql语句指定缓存翻译
* @param translates
* @return
*/
public EntityQuery translates(Translate... translates) {
if (translates != null && translates.length > 0) {
TranslateExtend extend;
for (Translate trans : translates) {
extend = trans.getExtend();
if (StringUtil.isBlank(extend.cache) || StringUtil.isBlank(extend.keyColumn) || StringUtil.isBlank(extend.column)) {
throw new IllegalArgumentException("针对EntityQuery设置缓存翻译必须要明确:cacheName=[" + extend.cache + "]、keyColumn=[" + extend.keyColumn + "](作为key的字段列)、 column=[" + extend.column + "](翻译结果映射的列)!");
}
innerModel.translates.put(extend.column, trans);
}
}
return this;
}
use of org.sagacity.sqltoy.model.inner.TranslateExtend in project sagacity-sqltoy by chenrenfei.
the class TranslateManager method getTranslates.
/**
* @todo 根据sqltoy sql.xml中的翻译设置获取对应的缓存(多个translate对应的多个缓存结果)
* @param translates
* @return
*/
public HashMap<String, HashMap<String, Object[]>> getTranslates(HashMap<String, Translate> translates) {
// 获得当前线程中的sql执行日志,后续缓存获取会覆盖掉日志
SqlExecuteTrace sqlTrace = SqlExecuteStat.get();
HashMap<String, HashMap<String, Object[]>> result = new HashMap<String, HashMap<String, Object[]>>();
HashMap<String, Object[]> cache;
TranslateConfigModel cacheModel;
TranslateExtend extend;
int cacheEltLength;
for (Map.Entry<String, Translate> entry : translates.entrySet()) {
extend = entry.getValue().getExtend();
if (translateMap.containsKey(extend.cache)) {
cacheModel = translateMap.get(extend.cache);
cache = getCacheData(cacheModel, extend.cacheType);
if (cache != null) {
// update 2022-1-4 增加缓存使用时cache-index 合法性校验
if (cache.size() > 0) {
cacheEltLength = cache.values().iterator().next().length;
if (extend.index >= cacheEltLength) {
throw new IllegalArgumentException("缓存取值数组越界:cacheName:" + extend.cache + ", column:" + extend.column + ",cache-indexs:(" + extend.index + ">=" + cacheEltLength + ")[缓存内容数组长度],请检查cache-indexs值确保跟缓存数据具体列保持一致!");
}
}
result.put(extend.column, cache);
} else {
result.put(extend.column, new HashMap<String, Object[]>());
if (logger.isWarnEnabled()) {
logger.warn("sqltoy translate:cacheName={},cache-type={},column={}配置不正确,未获取对应cache数据!", cacheModel.getCache(), extend.cacheType, extend.column);
} else {
System.err.println("sqltoy translate:cacheName=" + cacheModel.getCache() + ",cache-type=" + extend.cacheType + ",column=" + extend.column + " 配置不正确,未获取对应cache数据!");
}
}
} else {
logger.error("cacheName:{} 没有配置,请检查sqltoy-translate.xml文件!", extend.cache);
}
}
// 将调用获取缓存之前的日志放回线程中
if (sqlTrace != null) {
SqlExecuteStat.set(sqlTrace);
}
return result;
}
Aggregations