package cn.org.rapid_framework.generator.provider.db.sql.model; import java.util.Iterator; import java.util.LinkedHashSet; import cn.org.rapid_framework.generator.provider.db.sql.SqlFactory; import cn.org.rapid_framework.generator.provider.db.table.model.Column; import cn.org.rapid_framework.generator.provider.db.table.model.Table; import cn.org.rapid_framework.generator.util.StringHelper; import cn.org.rapid_framework.generator.util.sqlparse.SqlParseHelper; /** * 用于生成代码的Sql对象.对应数据库的sql语句 * 使用SqlFactory.parseSql()生成 <br /> * * SQL参数同时支持以下几种语法 * <pre> * hibernate: :username, * ibatis2: #username#,$usename$, * mybatis(or ibatis3): #{username},${username} * </pre> * SQL对象创建示例: * <pre> * Sql sql = new SqlFactory().parseSql("select * from user_info where username=#username# and password=#password#"); * </pre> * * @see SqlFactory * @author badqiu * */ public class Sql { public static String MULTIPLICITY_ONE = "one"; public static String MULTIPLICITY_MANY = "many"; public static String MULTIPLICITY_PAGING = "paging"; String tableSqlName = null; //是否需要 String operation = null; String resultClass; String parameterClass; String remarks; String multiplicity = "many"; // many or one or paging boolean paging = false; // 是否分页查询 String sqlmap; //for ibatis and ibatis3 LinkedHashSet<Column> columns = new LinkedHashSet<Column>(); LinkedHashSet<SqlParameter> params = new LinkedHashSet<SqlParameter>(); String sourceSql; // source sql String executeSql; public Sql() { } public Sql(Sql sql) { this.tableSqlName = sql.tableSqlName; this.operation = sql.operation; this.parameterClass = sql.parameterClass; this.resultClass = sql.resultClass; this.multiplicity = sql.multiplicity; this.columns = sql.columns; this.params = sql.params; this.sourceSql = sql.sourceSql; this.executeSql = sql.executeSql; this.remarks = sql.remarks; } public boolean isColumnsInSameTable() { //FIXME 还要增加表的列数与columns是否相等,才可以为select 生成 include语句 if(columns == null || columns.isEmpty()) return false; if(columns.size() == 1 && columns.iterator().next().getTable() != null) return true; String preTableName = columns.iterator().next().getSqlName(); for(Column c :columns) { Table table = c.getTable(); if(table == null) { return false; } if(preTableName.equalsIgnoreCase(table.getSqlName())) { continue; } } return true; } /** * 得到select查询返回的resultClass,可以通过setResultClass()自定义,如果没有自定义则为你自动生成<br /> * resultClass可以为com.company.User的完全路径 * 示例: * <pre> * select count(*) from user, 返回值为: Long * select * from user 返回值为: User * select count(*) cnt, sum(age) sum_age 返回值为: getOperation()+"Result"; * </pre> * @return */ public String getResultClass() { if(StringHelper.isNotBlank(resultClass)) return resultClass; if(columns.size() == 1) { return columns.iterator().next().getSimpleJavaType(); } if(isColumnsInSameTable()) { return columns.iterator().next().getTable().getClassName(); }else { if(operation == null) return null; return StringHelper.makeAllWordFirstLetterUpperCase(StringHelper.toUnderscoreName(operation))+"Result"; } } public void setResultClass(String queryResultClass) { this.resultClass = queryResultClass; } /** * 返回getResultClass()的类名称 <br /> * 示例: <br /> * 如getResultClass()=com.company.User,将返回User */ public String getResultClassName() { int lastIndexOf = getResultClass().lastIndexOf("."); return lastIndexOf >= 0 ? getResultClass().substring(lastIndexOf+1) : getResultClass(); } /** * SQL参数过多时用于封装为一个ParameterObject的class<br /> * <pre> * 可以通过setParameterClass()自定义 * 没有自定义则: * 如果是select查询,返回 operation+"Query" * 其它则返回operation+"Parameter" * <pre> */ public String getParameterClass() { if(StringHelper.isNotBlank(parameterClass)) return parameterClass; if(StringHelper.isBlank(operation)) return null; if(isSelectSql()) { return StringHelper.makeAllWordFirstLetterUpperCase(StringHelper.toUnderscoreName(operation))+"Query"; }else { return StringHelper.makeAllWordFirstLetterUpperCase(StringHelper.toUnderscoreName(operation))+"Parameter"; } } public void setParameterClass(String parameterClass) { this.parameterClass = parameterClass; } /** * 返回getParameterClass()的类名称 <br /> * 示例: <br /> * 如getParameterClass()=com.company.UserQuery,将返回UserQuery */ public String getParameterClassName() { int lastIndexOf = getParameterClass().lastIndexOf("."); return lastIndexOf >= 0 ? getParameterClass().substring(lastIndexOf+1) : getParameterClass(); } //TODO columnsSize大于二并且不是在同一张表中,将创建一个QueryResultClassName类,同一张表中也要考虑创建类 public int getColumnsCount() { return columns.size(); } public void addColumn(Column c) { columns.add(c); } /** * 得到该sql方法相对应的操作名称,模板中的使用方式为: public List ${operation}(),示例值: findByUsername * @return */ public String getOperation() { return operation; } public void setOperation(String operation) { this.operation = operation; } public String getOperationFirstUpper() { return StringHelper.capitalize(getOperation()); } /** * 用于控制查询结果,固定值为:one,many * @return */ public String getMultiplicity() { return multiplicity; } public void setMultiplicity(String multiplicity) { //TODO 是否要增加验证数据为 one,many this.multiplicity = multiplicity; } /** * 得到sqlect 查询的列对象(column),如果是insert,delete,update语句,则返回empty Set.<br /> * 示例: * <pre> * SQL : select count(*) cnt, sum(age) sum_age from user_info * columns: cnt,sum_age * </pre> * @return */ public LinkedHashSet<Column> getColumns() { return columns; } public void setColumns(LinkedHashSet<Column> columns) { this.columns = columns; } /** * 得到SQL的参数对象<br /> * 示例: * <pre> * SQL : select * from user_info where username=:user and password=:pwd limit :offset,:limit * params: user,pwd,offset,limit * </pre> * @return */ public LinkedHashSet<SqlParameter> getParams() { return params; } public void setParams(LinkedHashSet<SqlParameter> params) { this.params = params; } public SqlParameter getParam(String paramName) { for(SqlParameter p : getParams()) { if(p.getParamName().equals(paramName)) { return p; } } return null; } /** * 得到SQL原始语句 * @return */ public String getSourceSql() { return sourceSql; } public void setSourceSql(String sourceSql) { this.sourceSql = sourceSql; } public String getSqlmap() { return sqlmap; } public void setSqlmap(String sqlmap) { this.sqlmap = sqlmap; } // public String replaceParamsWith(String prefix,String suffix) { // String sql = sourceSql; // List<SqlParameter> sortedParams = new ArrayList(params); // Collections.sort(sortedParams,new Comparator<SqlParameter>() { // public int compare(SqlParameter o1, SqlParameter o2) { // return o2.paramName.length() - o1.paramName.length(); // } // }); // for(SqlParameter s : sortedParams){ //FIXME 现在只实现了:username参数替换 // sql = StringHelper.replace(sql,":"+s.getParamName(),prefix+s.getParamName()+suffix); // } // return sql; // } /** * sourceSql转换为在数据库实际执行的SQL, * 示例: * <pre> * sourceSql: select * from user where username=:username and password=:password * executeSql: select * from user where username=? and password=? * </pre> * @return */ public String getExecuteSql() { return executeSql; } public void setExecuteSql(String executeSql) { this.executeSql = executeSql; } public String getCountHql() { if(isSelectSql()) { return countQueryPrefix + SqlParseHelper.removeSelect(getHql()); }else { return getHql(); } } private String countQueryPrefix = "select count(*) "; public String getCountSql() { if(isSelectSql()) { return countQueryPrefix + SqlParseHelper.removeSelect(getSql()); }else { return getSql(); } } public String getIbatisCountSql() { if(isSelectSql()) { return countQueryPrefix + SqlParseHelper.removeSelect(getIbatisSql()); }else { return getIbatisSql(); } } public String getIbatis3CountSql() { if(isSelectSql()) { return countQueryPrefix + SqlParseHelper.removeSelect(getIbatis3Sql()); }else { return getIbatis3Sql(); } } public String getSql() { return replaceWildcardWithColumnsSqlName(sourceSql); } public String getSpringJdbcSql() { return SqlParseHelper.convert2NamedParametersSql(getSql(),":",""); } public String getHql() { return SqlParseHelper.convert2NamedParametersSql(getSql(),":",""); } public String getIbatisSql() { return StringHelper.isBlank(ibatisSql) ? SqlParseHelper.convert2NamedParametersSql(getSql(),"#","#") : ibatisSql; } public String getIbatis3Sql() { return StringHelper.isBlank(ibatis3Sql) ? SqlParseHelper.convert2NamedParametersSql(getSql(),"#{","}") : ibatis3Sql; } public void setIbatisSql(String ibatisSql) { this.ibatisSql = ibatisSql; } public void setIbatis3Sql(String ibatis3Sql) { this.ibatis3Sql = ibatis3Sql; } private String joinColumnsSqlName() { // TODO 未解决 a.*,b.*问题 StringBuffer sb = new StringBuffer(); for(Iterator<Column> it = columns.iterator();it.hasNext();) { Column c = it.next(); sb.append(c.getSqlName()); if(it.hasNext()) sb.append(","); } return sb.toString(); } public String replaceWildcardWithColumnsSqlName(String sql) { if(isSelectSql() && SqlParseHelper.getSelect(sql).indexOf("*") >= 0 && SqlParseHelper.getSelect(sql).indexOf("count(") < 0) { return SqlParseHelper.getPrettySql("select " + joinColumnsSqlName() + " " + SqlParseHelper.removeSelect(sql)); }else { return sql; } } /** * 当前的sourceSql是否是select语句 * @return */ public boolean isSelectSql() { return sourceSql.trim().toLowerCase().matches("(?is)\\s*select\\s.*from\\s+.*"); } /** * 当前的sourceSql是否是update语句 * @return */ public boolean isUpdateSql() { return sourceSql.trim().toLowerCase().matches("(?is)\\s*update\\s+.*"); } /** * 当前的sourceSql是否是delete语句 * @return */ public boolean isDeleteSql() { return sourceSql.trim().toLowerCase().matches("(?is)\\s*delete\\s+from\\s.*"); } /** * 当前的sourceSql是否是insert语句 * @return */ public boolean isInsertSql() { return sourceSql.trim().toLowerCase().matches("(?is)\\s*insert\\s+into\\s+.*"); } /** * 得到表相对应的sqlName,主要用途为生成文件时的分组. * @return */ public String getTableSqlName() { return tableSqlName; } public void setTableSqlName(String tableName) { this.tableSqlName = tableName; } /** * 得到备注 * @return */ public String getRemarks() { return remarks; } public void setRemarks(String comments) { this.remarks = comments; } public boolean isPaging() { if(MULTIPLICITY_PAGING.equalsIgnoreCase(multiplicity)) { return true; } return paging; } public void setPaging(boolean paging) { this.paging = paging; } /** * 根据tableSqlName和成相对应的tableClassName,主要用途路径变量引用.如${tableClassName}Dao.java * @return */ public String getTableClassName() { if(StringHelper.isBlank(tableSqlName)) return null; String removedPrefixSqlName = Table.removeTableSqlNamePrefix(tableSqlName); return StringHelper.makeAllWordFirstLetterUpperCase(StringHelper.toUnderscoreName(removedPrefixSqlName)); } public Column getColumnBySqlName(String sqlName) { for(Column c : getColumns()) { if(c.getSqlName().equalsIgnoreCase(sqlName)) { return c; } } return null; } public Column getColumnByName(String name) { Column c = getColumnBySqlName(name); if(c == null) { c = getColumnBySqlName(StringHelper.toUnderscoreName(name)); } return c; } public String toString() { return "sourceSql:\n"+sourceSql+"\nsql:"+getSql(); } private String ibatisSql; private String ibatis3Sql; }