package com.taover.repository; import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.math.BigDecimal; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.persistence.Column; import javax.persistence.Id; import javax.persistence.Table; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import com.taover.repository.exception.MultiRowException; import com.taover.repository.exception.NoContainTenantException; import com.taover.repository.exception.NotFoundException; import com.taover.repository.exception.ObjectReflectException; /** * * @author root * * @param * @param */ public class CustomJdbcTemplateWrapperTenant implements JdbcRepositoryWrapperTenant{ @Resource private JdbcTemplate jdbcTemplateWrite; private Map beanToTableField; private Map tableToBeanField; private String tableFieldNameListGapWithComma; private String idTableFieldName; private String idBeanFieldName; private String dbName; private String tableName; private Class tClassInfo; private CustomJdbcTemplateRowMapper customJdbcTemplateRowMapper; public CustomJdbcTemplateRowMapper getCustomJdbcTemplateRowMapper(){ return this.customJdbcTemplateRowMapper; } public CustomJdbcTemplateWrapperTenant() throws Exception{ //获取泛型类Class this.tClassInfo = (Class)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]; //检查实体声明 Table annoTable = (Table) tClassInfo.getAnnotation(Table.class); if(annoTable == null){ throw new Exception("DAO层初始化失败,失败原因:"+tClassInfo.getName()+"实体类,没有@Table注解指定表名"); } this.tableName = annoTable.name(); String schema = annoTable.schema(); String catalog = annoTable.catalog(); if(schema != null && !"".equals(schema)){ this.dbName = schema; }else if(catalog != null && !"".equals(catalog)){ this.dbName = catalog; } //初始化数据 beanToTableField = new HashMap(); tableToBeanField = new HashMap(); tableFieldNameListGapWithComma = ""; Field[] declaredFields = tClassInfo.getDeclaredFields(); for(int i=0; i * 例如:HelloWorld->HELLO_WORLD * @param name 转换前的驼峰式命名的字符串 * @return 转换后下划线大写方式命名的字符串 */ private String camelToUnderline(String name) { StringBuilder result = new StringBuilder(); if (name != null && name.length() > 0) { // 将第一个字符处理成大写 result.append(name.substring(0, 1).toUpperCase()); // 循环处理其余字符 for (int i = 1; i < name.length(); i++) { String s = name.substring(i, i + 1); // 在大写字母前添加下划线 if (Character.isUpperCase(s.charAt(0)) && Character.isLetter(s.charAt(0))) { result.append("_"); } // 其他字符直接转成大写 result.append(s.toUpperCase()); } } return result.toString(); } /** * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。
* 例如:HELLO_WORLD->HelloWorld * @param name 转换前的下划线大写方式命名的字符串 * @return 转换后的驼峰式命名的字符串 */ private String underlineToCamel(String name) { StringBuilder result = new StringBuilder(); // 快速检查 if (name == null || name.isEmpty()) { // 没必要转换 return ""; } else if (!name.contains("_")) { // 不含下划线,仅将首字母小写 return name.substring(0, 1).toLowerCase() + name.substring(1); } // 用下划线将原始字符串分割 String camels[] = name.split("_"); for (String camel : camels) { // 跳过原始字符串中开头、结尾的下换线或双重下划线 if (camel.isEmpty()) { continue; } // 处理真正的驼峰片段 if (result.length() == 0) { // 第一个驼峰片段,全部字母都小写 result.append(camel.toLowerCase()); } else { // 其他的驼峰片段,首字母大写 result.append(camel.substring(0, 1).toUpperCase()); result.append(camel.substring(1).toLowerCase()); } } return result.toString(); } private void appendWhereCondition(StringBuffer sql, StringBuffer pql, List list, List condition) { if (condition == null || condition.size() == 0) return; Object[] con = condition.get(0); int iLen = condition.size(); sql.append(" WHERE "); pql.append(" WHERE "); sql.append(con[0]); pql.append(con[0]); if (null != con[1] && con[1] != "" && con[1] != "useArg[0]") { sql.append(" " + con[1] + " ?"); pql.append(" " + con[1] + " " + con[2]); list.add(con[2]); } for (int i = 1; i < iLen; i++) { con = condition.get(i); sql.append(" AND "); pql.append(" AND "); sql.append(con[0]); pql.append(con[0]); if (null == con[1] || "" == con[1] || con[1] == "useArg[0]") continue; sql.append(" " + con[1] + " ?"); pql.append(" " + con[1] + " " + con[2]); list.add(con[2]); } } private void appendWhereConditionForCount(StringBuffer sql, List condition) { if (condition == null || condition.size() == 0) return; Object[] con = condition.get(0); int iLen = condition.size(); sql.append(" WHERE "); sql.append(con[0]); if (null != con[1] && con[1] != "" && con[1] != "useArg[0]") { sql.append(" " + con[1] + " ?"); } for (int i = 1; i < iLen; i++) { con = condition.get(i); sql.append(" AND "); sql.append(con[0]); if (null == con[1] || "" == con[1] || con[1] == "useArg[0]") continue; sql.append(" " + con[1] + " ?"); } } private void appendSetSql(StringBuffer sql, StringBuffer pql, List list, List obj) { for (Object[] arg : obj) { if (arg.length > 2) { sql.append(" " + arg[0] + " = " + arg[0] + arg[2] + " ?,"); pql.append(" " + arg[0] + " = " + arg[0] + arg[2] + arg[1] +","); list.add(arg[1]); }else if(arg.length == 2) { sql.append(" " + arg[0] + " = ?,"); pql.append(" " + arg[0] + " = " + arg[1] + ","); list.add(arg[1]); }else if(arg.length == 1) { sql.append(" " + arg[0] + ","); pql.append(" " + arg[0] + ","); } } } private String getTableSql(){ return (this.dbName == null || "".equals(this.dbName.trim()))? ("`"+this.tableName+"`"): ("`"+this.dbName+"`.`"+this.tableName+"`"); } private String constructUpdateSql(T entity, List beanFieldList) { StringBuffer sqlInsertPart = new StringBuffer("INSERT INTO "+this.getTableSql()+"("); Iterator beanFieldIter = this.beanToTableField.keySet().iterator(); while(beanFieldIter.hasNext()){ String beanFieldName = beanFieldIter.next(); String tableFieldName = this.beanToTableField.get(beanFieldName); Field beanField = null; try { beanField = this.tClassInfo.getDeclaredField(beanFieldName); beanField.setAccessible(true); if(beanField.get(entity) == null) { continue; } } catch (Exception e) { continue; } if(tableFieldName == null || beanFieldName == null){ continue; } beanFieldList.add(beanField); sqlInsertPart.append("`"+tableFieldName+"`,"); } return sqlInsertPart.substring(0, sqlInsertPart.length()-1)+")"; } private Object getDefaultValueByFieldType(Field itemField) { String simpleName = itemField.getType().getSimpleName(); if("String".equals(simpleName)) { return ""; }else if("Date".equals(simpleName) || "Timestamp".equals(simpleName)) { return "2000-01-01 00:00:00"; }else if("BigDecimal".equals(simpleName)){ return BigDecimal.ZERO; }else { return 0; } } @Override public T findEntityByID(ID id, Long tenantId) throws NotFoundException { return findEntityByID(id, tenantId, false); } @Override public T findEntityByID(ID id, Long tenantId, boolean isLock) throws NotFoundException { StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql()); sql.append(" WHERE "+idTableFieldName+" = ? and tenant_id="+tenantId); if (isLock) { sql.append(" FOR UPDATE"); } try { return (T) jdbcTemplateWrite.queryForObject(sql.toString(), this.customJdbcTemplateRowMapper, id); }catch (DataAccessException e) { throw new NotFoundException(); } } @Override public T findEntityByCondition(List condition) throws NotFoundException, MultiRowException, NoContainTenantException { this.checkTenantInfoFromCondition(condition); List tempList = findListByCondition(condition); if(tempList == null || tempList.size() == 0){ throw new NotFoundException(); } if(tempList != null && tempList.size() == 1){ return tempList.get(0); }else{ throw new MultiRowException(); } } private void checkTenantInfoFromCondition(List condition) throws NoContainTenantException{ for(Object[] item: condition) { if(item == null || item.length == 0) { continue; } if(item[0].toString().contains("tenant_id")) { return; } } throw new NoContainTenantException(); } @Override public T findEntityBySql(String sqlCondition) throws NotFoundException, MultiRowException, NoContainTenantException { this.checkTenantInfoFromSql(sqlCondition); List tempList = findListBySql(sqlCondition); if(tempList == null || tempList.size() == 0){ throw new NotFoundException(); } if(tempList != null && tempList.size() == 1){ return tempList.get(0); }else{ throw new MultiRowException(); } } private void checkTenantInfoFromSql(String sqlCondition) throws NoContainTenantException{ if(sqlCondition.contains("tenant_id")) { return; }else { throw new NoContainTenantException(); } } @Override public List findListByCondition(List condition) throws NoContainTenantException { return findListByCondition(condition, null); } @Override public List findListByCondition(List condition, String sortCondition) throws NoContainTenantException { this.checkTenantInfoFromCondition(condition); StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql()); StringBuffer pql = new StringBuffer(sql.toString()); List list = new ArrayList(); this.appendWhereCondition(sql, pql, list, condition); if(sortCondition != null && !sortCondition.equals("")){ sql.append(" " + sortCondition + " "); pql.append(" " + sortCondition + " "); } return (List)jdbcTemplateWrite.query(sql.toString(), this.customJdbcTemplateRowMapper, list.toArray()); } @Override public List findListBySql(String sqlCondition) throws NoContainTenantException { this.checkTenantInfoFromSql(sqlCondition); StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql()+" WHERE " + sqlCondition); return (List)jdbcTemplateWrite.query(sql.toString(), this.customJdbcTemplateRowMapper); } @Override public Map findPageByCondition(List condition, int page, int pageSize) throws NoContainTenantException { return findPageByCondition(condition, null , page, pageSize); } @Override public Map findPageByCondition(List condition, String sortCondition, int page, int pageSize) throws NoContainTenantException { this.checkTenantInfoFromCondition(condition); StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql()); StringBuffer pql = new StringBuffer(sql.toString()); StringBuffer sqlCount = new StringBuffer("SELECT COUNT(1) rowCount FROM "+this.getTableSql()); List count_list = new ArrayList(); List page_list = new ArrayList(); this.appendWhereConditionForCount(sqlCount, condition); this.appendWhereCondition(sql, pql, count_list, condition); for (int i = 0; i < count_list.size(); i++) page_list.add(count_list.get(i)); page_list.add((page - 1) * pageSize); page_list.add(pageSize); if(sortCondition != null && !sortCondition.equals("")){ sql.append(" " + sortCondition + " "); pql.append(" " + sortCondition + " "); } String pageSql = sql.toString() + " limit ?, ?"; Map totalRowsMap = jdbcTemplateWrite.queryForMap(sqlCount.toString(), count_list.toArray()) ; List resultList = jdbcTemplateWrite.query(pageSql.toString(), this.customJdbcTemplateRowMapper, page_list.toArray()); return UtilsSql.createPage(page, pageSize, Integer.valueOf(totalRowsMap.get("rowCount").toString()), resultList); } @Override public Map findPageBySql(String sqlCondition, int page, int pageSize) throws NoContainTenantException { this.checkTenantInfoFromSql(sqlCondition); StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql()+" WHERE " + sqlCondition ); StringBuffer sqlCount = new StringBuffer("SELECT count(1) rowCount FROM "+this.getTableSql()+" WHERE " + sqlCondition); sql.append(" limit ?, ?"); List page_list = new ArrayList(); page_list.add((page - 1) * pageSize); page_list.add(page * pageSize); Map totalRowsMap = jdbcTemplateWrite.queryForMap(sqlCount.toString()); List resultList = jdbcTemplateWrite.query(sql.toString(), this.customJdbcTemplateRowMapper, page_list.toArray()); return UtilsSql.createPage(page, pageSize, Integer.valueOf(totalRowsMap.get("rowCount").toString()), resultList); } @Override public void addEntity(T entity) { StringBuffer sqlInsertPart = new StringBuffer("INSERT INTO "+this.getTableSql()+"("); StringBuffer sqlColumnPart = new StringBuffer(") VALUES ("); List paramList = new ArrayList(); Iterator beanFieldIter = this.beanToTableField.keySet().iterator(); while(beanFieldIter.hasNext()){ String beanFieldName = beanFieldIter.next(); String tableFieldName = this.beanToTableField.get(beanFieldName); Field beanField; Object beanFieldValue = null; try { beanField = this.tClassInfo.getDeclaredField(beanFieldName); beanField.setAccessible(true); beanFieldValue = beanField.get(entity); } catch (Exception e) { e.printStackTrace(); } if(tableFieldName == null || beanFieldName == null || beanFieldValue == null){ continue; } sqlInsertPart.append("`"+tableFieldName+"`,"); sqlColumnPart.append(" ?,"); paramList.add(beanFieldValue); } //执行SQL String exeSql = sqlInsertPart.substring(0, sqlInsertPart.length()-1)+sqlColumnPart.substring(0, sqlColumnPart.length()-1)+")"; jdbcTemplateWrite.update(exeSql, paramList.toArray()); } @Override public void addEntityList(List entityList) { if(entityList == null || entityList.isEmpty()) { return; } //构造SQL语句及Entity Field列表 List beanFieldList = new ArrayList(this.beanToTableField.size()); StringBuffer exeSql = new StringBuffer(this.constructUpdateSql(entityList.get(0), beanFieldList)); //构造参数信息 List args = new ArrayList(); exeSql.append(" VALUES"); for(int itemIndex=0; itemIndex list = new ArrayList(); StringBuffer sql = new StringBuffer("DELETE FROM "+this.getTableSql()+""); StringBuffer pql = new StringBuffer(sql.toString()); this.appendWhereCondition(sql, pql, list, condition); return jdbcTemplateWrite.update( sql.toString(), list.toArray()); } @Override public int deleteEntityBySql(String sqlCondition) throws NoContainTenantException { if("".equals(sqlCondition.trim())) { throw new RuntimeException("params[sqlCondition] is empty"); } this.checkTenantInfoFromSql(sqlCondition); return jdbcTemplateWrite.update( "DELETE FROM "+this.getTableSql()+" WHERE " + sqlCondition); } @Override public int deleteEntityList(List idList, Long tenantId) throws NoContainTenantException { StringBuffer idSb = new StringBuffer(); for(ID id: idList) { idSb.append(id); } return this.deleteEntityBySql(this.idTableFieldName + " in ("+idSb.toString().substring(0, idSb.length()-1)+") and tenant_id="+tenantId); } @Override public int updateEntityById(List changeList, ID id, Long tenantId) { if(null == id){ throw new RuntimeException("params[id] is null"); } if (null == changeList || changeList.size() == 0) { throw new RuntimeException("params[changeList] is empty"); } StringBuffer sql = new StringBuffer("UPDATE "+this.getTableSql()+" SET"); StringBuffer pql = new StringBuffer(sql.toString()); List list = new ArrayList(); this.appendSetSql(sql, pql, list, changeList); String where = " WHERE "+this.idTableFieldName+"=? and tenant_id="+tenantId; String updateSql = sql.substring(0, sql.length()-1)+where; list.add(id); return jdbcTemplateWrite.update(updateSql, list.toArray()); } @Override public int updateEntityByCondition(List updateObj, List condition) throws NoContainTenantException { if (null == updateObj || updateObj.size() == 0) { throw new RuntimeException("params[updateObj] is empty"); } if (null == condition || condition.size() == 0) { throw new RuntimeException("params[condition] is empty"); } this.checkTenantInfoFromCondition(condition); StringBuffer sql = new StringBuffer("UPDATE "+this.getTableSql()+" SET"); StringBuffer pql = new StringBuffer(sql.toString()); List list = new ArrayList(); this.appendSetSql(sql, pql, list, updateObj); StringBuffer where = new StringBuffer(""); StringBuffer pwhere = new StringBuffer(""); this.appendWhereCondition(where, pwhere, list, condition); String updateSql = sql.substring(0, sql.length()-1)+where.toString(); return jdbcTemplateWrite.update(updateSql, list.toArray()); } @Override public int updateEntityBySql(List updateObj, String sqlCondition) throws NoContainTenantException { if (null == updateObj || updateObj.size() == 0) { throw new RuntimeException("params[updateObj] is empty"); } if ("".equals(sqlCondition)) { throw new RuntimeException("params[sqlCondition] is empty"); } this.checkTenantInfoFromSql(sqlCondition); StringBuffer sql = new StringBuffer("UPDATE "+this.getTableSql()+" SET"); StringBuffer pql = new StringBuffer(sql.toString()); List list = new ArrayList(); this.appendSetSql(sql, pql, list, updateObj); String updateSql = sql.toString().substring(0, sql.length()-1) + " WHERE "+sqlCondition; return jdbcTemplateWrite.update(updateSql, list.toArray()); } @Override public Map getPageData(String coreSql, String orderByPartSql, Integer page, Integer pageSize) throws NoContainTenantException { this.checkTenantInfoFromSql(coreSql); try { String[] splitedSql = UtilsSql.splitCoreSql(coreSql); return this.getPageData(splitedSql[0], splitedSql[1], orderByPartSql, page, pageSize); }catch (Exception e) { return UtilsSql.createPage(page, pageSize, 0, new ArrayList()); } } @Override public Map getPageData(String selectSql, String fromAndWhereSql, String orderByPartSql, Integer page, Integer pageSize) throws NoContainTenantException { this.checkTenantInfoFromSql(fromAndWhereSql); //构造查询语句 String querySql = selectSql+" "+fromAndWhereSql+" "+orderByPartSql+" "+UtilsSql.getLimitCondition(page, pageSize); //构造统计计数语句 String countSql = "select count(*) rowsCount from ( select 1 "+fromAndWhereSql+" ) t "; //执行查询 List> queryData = new ArrayList>(); Map countData = new HashMap(); queryData = this.jdbcTemplateWrite.queryForList(querySql); countData = this.jdbcTemplateWrite.queryForMap(countSql); return UtilsSql.createPage(page, pageSize, Integer.valueOf(countData.get("rowsCount").toString()), queryData); } }