package com.nfwork.dbfound.model.bean; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.dom4j.Element; import com.nfwork.dbfound.core.Context; import com.nfwork.dbfound.db.dialect.SqlDialect; import com.nfwork.dbfound.exception.DBFoundPackageException; import com.nfwork.dbfound.model.ModelEngine; import com.nfwork.dbfound.model.reflector.ReflectorUtil; import com.nfwork.dbfound.util.DBUtil; import com.nfwork.dbfound.util.LogUtil; import com.nfwork.dbfound.util.ParseUtil; public class Query extends SqlEntity { private static final long serialVersionUID = 83009892861541099L; private String name = "_default"; // query对象的名字 private int pagerSize; private long startWith; private long length; // 总共条数 private Map<String, Param> params; // query对象对应参数 private Map<String, Filter> filters; private String currentPath; private String rootPath; private String modelName; private Integer queryTimeout; private static final String WHERE_CLAUSE = "#WHERE_CLAUSE#"; private static final String AND_CLAUSE = "#AND_CLAUSE#"; @Override public void init(Element element) { params = new HashMap<String, Param>(); filters = new HashMap<String, Filter>(); super.init(element); } @Override public void run() { if (getParent() instanceof Model) { Model model = (Model) getParent(); if (name == null || "".equals(name)) { model.putQuery("_default", this); } else { model.putQuery(name, this); } } else { super.run(); } } public Query cloneEntity() { Query query; try { query = (Query) this.clone(); } catch (CloneNotSupportedException e) { throw new DBFoundPackageException("query克隆异常:" + e.getMessage(), e); } HashMap<String, Param> params = new HashMap<String, Param>(); HashMap<String, Filter> filters = new HashMap<String, Filter>(); for (Iterator iterator = this.params.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = (Map.Entry) iterator.next(); Param param = (Param) entry.getValue(); params.put(entry.getKey().toString(), (Param) param.cloneEntity()); } for (Iterator iterator = this.filters.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = (Map.Entry) iterator.next(); Filter filter = (Filter) entry.getValue(); if (entry.getKey() != null) { filters.put(entry.getKey().toString(), (Filter) filter.cloneEntity()); } } query.setParams(params); query.setFilters(filters); return query; } /** * 查询结构集 以list的map对象返回 * * @param context * @param provideName * @param object * @return */ public <T> List<T> query(Context context, String provideName, Class<T> object) { Connection conn = context.getConn(provideName); SqlDialect dialect = context.getConnDialect(provideName); // 2012年8月14日22:01:04 添加静态参数设置 sql = ParseUtil.parse(sql, params); // end 添加 // 再次解析filter里面的静态参数 2013年5月20日11:12:27 sql = initFilter(sql); sql = ParseUtil.parse(sql, params); // end 修改 // fileter初始化,数据库方言初始化 sql = dialect.parseSql(sql); List<Map> data = new ArrayList<Map>(); String eSql = getExecuteSql(this.sql); if (pagerSize > 0) { eSql = dialect.getPagerSql(eSql, pagerSize, startWith); } PreparedStatement statement = null; ResultSet dataset = null; try { statement = conn.prepareStatement(eSql); if (queryTimeout != null) { statement.setQueryTimeout(queryTimeout); } // 参数设定 initParam(statement, this.sql, params); dataset = statement.executeQuery(); ResultSetMetaData metaset = dataset.getMetaData(); // 如果对象不为null,利用反射构建object对象 if (object != null) { List<T> list = (List<T>) ReflectorUtil.parseResultList(object, dataset, context); return list; } int size = metaset.getColumnCount(); String colNames[] = new String[size + 1]; for (int i = 1; i < colNames.length; i++) { colNames[i] = metaset.getColumnLabel(i).toLowerCase(); } int totalCounts = 0; while (dataset.next()) { if (context.queryLimit && ++totalCounts > context.queryLimitSize) { break; } Map<String, Object> mapdata = new HashMap<String, Object>(); for (int i = 1; i <= size; i++) { String value = dataset.getString(i); String columnName = colNames[i]; if ("d_p_rm".equals(columnName)) {// 分页参数 不放入map continue; } int columnType = metaset.getColumnType(i); if (value == null) { mapdata.put(columnName, null); continue; } switch (columnType) { case Types.VARCHAR: mapdata.put(columnName, value); break; case Types.INTEGER: mapdata.put(columnName, dataset.getInt(i)); break; case Types.DOUBLE: if (value.endsWith(".0")) { mapdata.put(columnName, dataset.getLong(i)); } else { mapdata.put(columnName, dataset.getDouble(i)); } break; case Types.FLOAT: if (value.endsWith(".0")) { mapdata.put(columnName, dataset.getInt(i)); } else { mapdata.put(columnName, dataset.getFloat(i)); } break; case Types.DECIMAL: if (value.endsWith(".0") || value.indexOf(".") == -1) { mapdata.put(columnName, dataset.getLong(i)); } else { mapdata.put(columnName, dataset.getDouble(i)); } break; case Types.NUMERIC: if (value.endsWith(".0") || value.indexOf(".") == -1) { mapdata.put(columnName, dataset.getLong(i)); } else { mapdata.put(columnName, dataset.getDouble(i)); } break; case Types.VARBINARY: if (value.matches("[0123456789]*\\.[0123456789]+")) { mapdata.put(columnName, dataset.getDouble(i)); } else if (value.matches("[0123456789]*")) { mapdata.put(columnName, dataset.getLong(i)); } else { mapdata.put(columnName, value); } break; case Types.BIGINT: mapdata.put(columnName, dataset.getLong(i)); break; case Types.REAL: if (value.endsWith(".0") || value.indexOf(".") == -1) { mapdata.put(columnName, dataset.getInt(i)); } else { mapdata.put(columnName, dataset.getFloat(i)); } break; case Types.DATE: if (value.length() > 19) { mapdata.put(columnName, value.subSequence(0, 19)); } else { mapdata.put(columnName, value); } break; case Types.TIME: if (value.length() > 19) { mapdata.put(columnName, value.subSequence(0, 19)); } else { mapdata.put(columnName, value); } break; case Types.TIMESTAMP: if (value.length() > 19) { mapdata.put(columnName, value.subSequence(0, 19)); } else { mapdata.put(columnName, value); } break; case Types.BLOB: break; // case Types.CLOB: break; // case Types.NCLOB: break; case Types.LONGVARBINARY: break; default: mapdata.put(columnName, value); } } data.add(mapdata); } } catch (SQLException e) { throw new DBFoundPackageException("Query执行异常:" + e.getMessage(), e); } finally { DBUtil.closeResultSet(dataset); DBUtil.closeStatement(statement); LogUtil.log(eSql, params); } return (List<T>) data; } /** * 初始化过滤条件 * * @param ssql * @return */ public String initFilter(String ssql) { StringBuffer bfsql = new StringBuffer(); Collection<Filter> params = filters.values(); for (Filter nfFilter : params) { if (nfFilter.isActive()) { bfsql.append(nfFilter.getExpress()).append(" and "); } } String fsql = bfsql.length() > 4 ? bfsql.substring(0, bfsql.length() - 4) : null; if (fsql != null) { fsql = Matcher.quoteReplacement(fsql); } Pattern p = Pattern.compile("\\#[A-Z_]+\\#"); Matcher m = p.matcher(ssql); StringBuffer buf = new StringBuffer(); while (m.find()) { String text = m.group(); if (text.equals(WHERE_CLAUSE)) { if (fsql == null) { m.appendReplacement(buf, " "); } else { m.appendReplacement(buf, " where " + fsql); } } else if (text.equals(AND_CLAUSE)) { if (fsql == null) { m.appendReplacement(buf, " "); } else { m.appendReplacement(buf, " and " + fsql); } } } m.appendTail(buf); return buf.toString(); } /** * 得到最后执行的sql语句 * * @return */ public String getExecuteSql(String executeSqlString) { executeSqlString = executeSqlString.replaceAll(replaceString, "?"); return executeSqlString; } /** * 统计sql查询总共的条数 * * @return */ public long countItems(Connection conn) { char[] sqlChars = sql.toLowerCase().toCharArray(); int dyh = 0; int kh = 0; int from_hold = 0; int order_hold = 0; int group_hold = 0; // 寻找from的位置 for (int i = 6; i < sqlChars.length - 4; i++) { if (sqlChars[i] == '(') { kh++; } else if (sqlChars[i] == ')') { kh--; } else if (sqlChars[i] == '\'') { dyh++; } else if (sqlChars[i] == 'f') { if (sqlChars[i + 1] == 'r') { if (sqlChars[i + 2] == 'o') { if (sqlChars[i + 3] == 'm') { if (sqlChars[i + 4] == ' ' || sqlChars[i + 4] == '\n' || sqlChars[i + 4] == '\t') { if (kh == 0 && (dyh % 2 == 0) && (sqlChars[i - 1] == ' ' || sqlChars[i - 1] == ')' || sqlChars[i - 1] == '\n' || sqlChars[i - 1] == '\t')) { from_hold = i; break; } else { i = i + 4; } } else { i = i + 3; } } else { i = i + 2; } } else { i = i + 1; } } } } if (from_hold == 0) { return 1; // 没有找到from return 1 } // 寻找order by的位置,group by 位置 for (int i = from_hold + 4; i < sqlChars.length - 8; i++) { if (sqlChars[i] == '(') { kh++; } else if (sqlChars[i] == ')') { kh--; } else if (sqlChars[i] == '\'') { dyh++; } else if (sqlChars[i] == 'o') { if (sqlChars[i + 1] == 'r') { if (sqlChars[i + 2] == 'd') { if (sqlChars[i + 3] == 'e') { if (sqlChars[i + 4] == 'r') { if (sqlChars[i + 5] == ' ' || sqlChars[i + 5] == '\n' || sqlChars[i + 5] == '\t') { if (kh == 0 && (dyh % 2 == 0) && (sqlChars[i - 1] == ' ' || sqlChars[i - 1] == ')' || sqlChars[i - 1] == '\n' || sqlChars[i - 1] == '\t')) { order_hold = i; break; } else { i = i + 5; } } else { i = i + 4; } } else { i = i + 3; } } else { i = i + 2; } } else { i = i + 1; } } } else if (sqlChars[i] == 'g') { if (sqlChars[i + 1] == 'r') { if (sqlChars[i + 2] == 'o') { if (sqlChars[i + 3] == 'u') { if (sqlChars[i + 4] == 'p') { if (sqlChars[i + 5] == ' ' || sqlChars[i + 5] == '\n' || sqlChars[i + 5] == '\t') { if (kh == 0 && (dyh % 2 == 0) && (sqlChars[i - 1] == ' ' || sqlChars[i - 1] == ')' || sqlChars[i - 1] == '\n' || sqlChars[i - 1] == '\t')) { group_hold = i; break; } else { i = i + 5; } } else { i = i + 4; } } else { i = i + 3; } } else { i = i + 2; } } else { i = i + 1; } } } } String cSql = ""; if (order_hold == 0) { if (group_hold > 0) { cSql = "select count(1) from (select 1 " + sql.substring(from_hold) + " ) v"; } else { cSql = "select count(1) " + sql.substring(from_hold); } } else { cSql = "select count(1) " + sql.substring(from_hold, order_hold); } String ceSql = getExecuteSql(cSql); PreparedStatement statement = null; ResultSet dataset = null; long count = 0; try { statement = conn.prepareStatement(ceSql); // 参数设定 initParam(statement, cSql, params); dataset = statement.executeQuery(); dataset.next(); count = dataset.getLong(1); length = count; } catch (SQLException e) { throw new DBFoundPackageException("Query执行count查询异常:" + e.getMessage(), e); } finally { DBUtil.closeResultSet(dataset); DBUtil.closeStatement(statement); LogUtil.info("execute count sql:" + ceSql); } return count; } /** * 设定参数 * * @param name * @param value */ public void setParam(String name, String value) { params.get(name).setValue(value); } /** * 得到参数值 * * @param name * @return */ public String getParam(String name) { return params.get(name).getStringValue(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public Map<String, Param> getParams() { return params; } public void setParams(Map<String, Param> params) { this.params = params; } public int getPagerSize() { return pagerSize; } public void setPagerSize(int pagerSize) { this.pagerSize = pagerSize; } public long getStartWith() { return startWith; } public void setStartWith(long startWith) { this.startWith = startWith; } public long getLength() { return length; } public void setLength(long dataLength) { this.length = dataLength; } public Map<String, Filter> getFilters() { return filters; } public void setFilters(Map<String, Filter> filters) { this.filters = filters; } public String getCurrentPath() { return currentPath; } public void setCurrentPath(String currentPath) { this.currentPath = currentPath; } public String getSql() { return sql; } public void setSql(String sql) { this.sql = sql; } public String getRootPath() { return rootPath; } public void setRootPath(String rootPath) { this.rootPath = rootPath; } public String getModelName() { return modelName; } public void setModelName(String modelName) { this.modelName = modelName; } public Integer getQueryTimeout() { return queryTimeout; } public void setQueryTimeout(Integer queryTimeout) { this.queryTimeout = queryTimeout; } @Override public void execute(Context context, Map<String, Param> params, String provideName) { String currentPath = context.getCurrentPath(); if (modelName == null) { modelName = context.getCurrentModel(); } List<Map> datas = ModelEngine.query(context, modelName, name, currentPath, false).getDatas(); context.setData(rootPath, datas); } }