From 7de08bb02302ea0169762d508ac55e51eec3356f Mon Sep 17 00:00:00 2001 From: 王彬 Date: Mon, 29 Mar 2021 16:09:55 +0800 Subject: [PATCH] 增加支持广播SQL --- build.gradle | 2 +- src/main/java/com/taover/repository/CustomJdbcTemplateBroadcast.java | 546 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/repository/CustomJdbcTemplateBroadcastInterface.java | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/repository/autoconfigure/TaoverRepositoryAutoConfiguration.java | 15 +++++++++++++-- src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateBroadcast.java | 976 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateBroadcastImpl.java | 667 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateWrapperTenant.java | 12 +++++++++++- src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateWrapperTenantImpl.java | 17 ++++++++++------- src/main/java/com/taover/repository/shardingsphere/ShardingSphereService.java | 34 +++++++++++++++++++++++++++++----- src/test/java/com/taover/repository/test/TestAutoconfigure.java | 15 ++++++++++----- src/test/resources/application.properties | 17 ++++++++++++----- 11 files changed, 2428 insertions(+), 26 deletions(-) create mode 100644 src/main/java/com/taover/repository/CustomJdbcTemplateBroadcast.java create mode 100644 src/main/java/com/taover/repository/CustomJdbcTemplateBroadcastInterface.java create mode 100644 src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateBroadcast.java create mode 100644 src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateBroadcastImpl.java diff --git a/build.gradle b/build.gradle index 8304a48..09a60a5 100644 --- a/build.gradle +++ b/build.gradle @@ -57,7 +57,7 @@ uploadArchives { authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD) } pom.project { - version '2.1.48' + version '2.1.52' artifactId ARTIFACT_Id groupId GROUP_ID packaging TYPE diff --git a/src/main/java/com/taover/repository/CustomJdbcTemplateBroadcast.java b/src/main/java/com/taover/repository/CustomJdbcTemplateBroadcast.java new file mode 100644 index 0000000..efc5188 --- /dev/null +++ b/src/main/java/com/taover/repository/CustomJdbcTemplateBroadcast.java @@ -0,0 +1,546 @@ +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 com.taover.repository.exception.MultiRowException; +import com.taover.repository.exception.NoContainTenantException; +import com.taover.repository.exception.NotFoundException; +import com.taover.repository.exception.ObjectReflectException; +import com.taover.repository.jdbctemplate.JdbcTemplateBroadcast; +import com.taover.repository.mapper.CustomJdbcTemplateRowMapper; +import com.taover.repository.util.UtilsSql; + +/** + * + * @author root + * + * @param + * @param + */ +public class CustomJdbcTemplateBroadcast implements CustomJdbcTemplateBroadcastInterface{ + @Resource + private JdbcTemplateBroadcast _jdbcTemplateBroadcast; + + private Map _beanToTableField; + private Map _tableToBeanField; + private String _tableFieldNameListGapWithComma; + private String _idTableFieldName; + private String _dbName; + private String _tableName; + private Class _tClassInfo; + private CustomJdbcTemplateRowMapper _customJdbcTemplateRowMapper; + + public CustomJdbcTemplateRowMapper getCustomJdbcTemplateRowMapper(){ + return this._customJdbcTemplateRowMapper; + } + + @SuppressWarnings("unchecked") + public CustomJdbcTemplateBroadcast() 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(this._tClassInfo, this._tableToBeanField); + } + + /** + * 将驼峰式命名的字符串转换为下划线大写方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。
+ * 例如: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(); + } + + 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) throws NotFoundException { + return findEntityByID(id, false); + } + + @Override + public T findEntityByID(ID id, boolean isLock) throws NotFoundException { + StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql()); + sql.append(" WHERE "+_idTableFieldName+" = ? "); + if (isLock) { + sql.append(" FOR UPDATE"); + } + try { + return (T) _jdbcTemplateBroadcast.queryForObject(sql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName}, id); + }catch (DataAccessException e) { + throw new NotFoundException(e); + } + } + + @Override + public T findEntityByCondition(List condition) throws NotFoundException, MultiRowException, NoContainTenantException { + 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(); + } + } + + @Override + public T findEntityBySql(String sqlCondition) throws NotFoundException, MultiRowException { + 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(); + } + } + + @Override + public List findListByCondition(List condition){ + return findListByCondition(condition, null); + } + + @Override + public List findListByCondition(List condition, String sortCondition){ + StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql()); + List list = new ArrayList(); + this.appendWhereCondition(sql, new StringBuffer(), list, condition); + if(sortCondition != null && !sortCondition.equals("")){ + sql.append(" " + sortCondition + " "); + } + return (List)_jdbcTemplateBroadcast.query(sql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName}, list.toArray()); + } + + @Override + public List findListBySql(String sqlCondition){ + StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql()+" WHERE " + sqlCondition); + return (List)_jdbcTemplateBroadcast.query(sql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName}); + } + + @Override + public Map findPageByCondition(List condition, int page, int pageSize){ + return findPageByCondition(condition, null , page, pageSize); + } + + @Override + public Map findPageByCondition(List condition, String sortCondition, int page, int pageSize){ + 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 = _jdbcTemplateBroadcast.queryForMap(sqlCount.toString(), new String[] {this._tableName}, count_list.toArray()) ; + List resultList = _jdbcTemplateBroadcast.query(pageSql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName}, 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){ + 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 = _jdbcTemplateBroadcast.queryForMap(sqlCount.toString(), new String[] {this._tableName}); + List resultList = _jdbcTemplateBroadcast.query(sql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName}, 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)+")"; + _jdbcTemplateBroadcast.update(exeSql, new String[] {this._tableName}, 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 condition){ + if (null == condition || condition.size() == 0) { + throw new RuntimeException("params[condition] is empty"); + } + + List list = new ArrayList(); + StringBuffer sql = new StringBuffer("DELETE FROM "+this.getTableSql()+""); + StringBuffer pql = new StringBuffer(sql.toString()); + this.appendWhereCondition(sql, pql, list, condition); + return _jdbcTemplateBroadcast.update( sql.toString(), new String[] {this._tableName}, list.toArray()); + } + + @Override + public int deleteEntityBySql(String sqlCondition){ + if("".equals(sqlCondition.trim())) { + throw new RuntimeException("params[sqlCondition] is empty"); + } + return _jdbcTemplateBroadcast.update( "DELETE FROM "+this.getTableSql()+" WHERE " + sqlCondition, new String[] {this._tableName}); + } + + @Override + public int deleteEntityList(List idList){ + StringBuffer idSb = new StringBuffer(); + for(ID id: idList) { + idSb.append(id); + } + return this.deleteEntityBySql(this._idTableFieldName + " in ("+idSb.toString().substring(0, idSb.length()-1)+") "); + } + + @Override + public int updateEntityById(List changeList, ID id) { + 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+"=? "; + String updateSql = sql.substring(0, sql.length()-1)+where; + list.add(id); + return _jdbcTemplateBroadcast.update(updateSql, new String[] {this._tableName}, list.toArray()); + } + + @Override + public int updateEntityByCondition(List updateObj, List condition){ + 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"); + } + + 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 _jdbcTemplateBroadcast.update(updateSql, new String[] {this._tableName}, list.toArray()); + } + + @Override + public int updateEntityBySql(List updateObj, String sqlCondition){ + if (null == updateObj || updateObj.size() == 0) { + throw new RuntimeException("params[updateObj] is empty"); + } + if ("".equals(sqlCondition)) { + throw new RuntimeException("params[sqlCondition] 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, updateObj); + + String updateSql = sql.toString().substring(0, sql.length()-1) + " WHERE "+sqlCondition; + return _jdbcTemplateBroadcast.update(updateSql, new String[] {this._tableName}, list.toArray()); + } + + @Override + public Map getPageData(String coreSql, String orderByPartSql, Integer page, Integer pageSize){ + String[] splitedSql = UtilsSql.splitCoreSql(coreSql); + return this.getPageData(splitedSql[0], splitedSql[1], orderByPartSql, page, pageSize); + } + + @Override + public Map getPageData(String selectSql, String fromAndWhereSql, String orderByPartSql, Integer page, Integer pageSize){ + //构造查询语句 + 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._jdbcTemplateBroadcast.queryForList(querySql, new String[] {this._tableName}); + countData = this._jdbcTemplateBroadcast.queryForMap(countSql, new String[] {this._tableName}); + return UtilsSql.createPage(page, pageSize, Integer.valueOf(countData.get("rowsCount").toString()), queryData); + } +} diff --git a/src/main/java/com/taover/repository/CustomJdbcTemplateBroadcastInterface.java b/src/main/java/com/taover/repository/CustomJdbcTemplateBroadcastInterface.java new file mode 100644 index 0000000..82b4a2a --- /dev/null +++ b/src/main/java/com/taover/repository/CustomJdbcTemplateBroadcastInterface.java @@ -0,0 +1,153 @@ +package com.taover.repository; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +import com.taover.repository.exception.MultiRowException; +import com.taover.repository.exception.NoContainTenantException; +import com.taover.repository.exception.NotFoundException; + +public interface CustomJdbcTemplateBroadcastInterface { + + /** + * 按主键查询 + */ + public T findEntityByID(ID id) throws NotFoundException; + + /** + * 按主键查询 + * isLock 是否锁定, 默认不锁 + * fromWriteDB 是否从写库读写,默认从读库查询 + */ + public T findEntityByID(ID id, boolean isLock) throws NotFoundException; + + /** + * 根据条件List查询 + * Object[]数组长度是3 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。 + */ + public T findEntityByCondition(List condition) throws NotFoundException,MultiRowException,NoContainTenantException; + + /** + * 根据条件sql查询 + * sqlCondition 为where 后面的条件。 + */ + public T findEntityBySql(String sqlCondition) throws NotFoundException,MultiRowException,NoContainTenantException; + + /** + * 根据条件List查询 + * Object[]数组长度是3 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。 + */ + public List findListByCondition(List condition); + + /** + * 根据条件List查询 + * Object[]数组长度是3 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。 + */ + public List findListByCondition(List condition, String sortCondition); + + /** + * 根据条件sql查询 + * sqlCondition 为where 后面的条件。 + */ + public List findListBySql(String sqlCondition); + + /** + * 按条件分页查询 + * Object[]数组长度是3 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。 + */ + public Map findPageByCondition(List condition, int page, int pageSize); + + /** + * 按条件分页查询 + * Object[]数组长度是3 + * Object[]第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。 + * boolean isUseCache, 是否用缓存,默认用。 + * boolean isAddCache, 是否添加缓存,默认添加。 + */ + public Map findPageByCondition(List condition, String sortCondition, int page, int pageSize); + + /** + * 按sql分页查询, sqlCondition为where 后条件sql + */ + public Map findPageBySql(String sqlCondition, int page, int pageSize); + + /** + * 添加 + */ + public void addEntity(T entity); + + /** + * 批量添加 + * @throws Exception + */ + public void addEntityList(List entityList); + + /** + * 按ID删除 + */ + public int deleteEntityByID(ID id); + + /** + * 删除按List条件 + * Object[]数组长度是3 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。 + */ + public int deleteEntityByCondition(List condition); + + /** + * 删除按condition条件 + * 建议使用deleteTByCondition(List condition), 如果removeTByCondition(List condition)满足不了where条件可以使用此方法。 + * condition为where后面的条件,condition不能为空。 + */ + public int deleteEntityBySql(String sqlCondition); + + /** + * 根据list对象逐个删除。 + * @throws NoContainTenantException + */ + public int deleteEntityList(List idList); + + /** + * 根据ID修改指定的值 + */ + public int updateEntityById(List changeList, ID id); + + /** + * List updateObj 要修改成的值,数组长度为2,第一个值为列名,第二个值是要改成的值。 + * List condition 修改的条件, 数组长度是3, 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。 + */ + public int updateEntityByCondition(List updateObj, List condition); + + /** + * List updateObj 要修改成的值,数组长度为2,第一个值为列名,第二个值是要改成的值。 + * String sqlCondition 修改的条件。 + */ + public int updateEntityBySql(List updateObj, String sqlCondition); + + /** + * 获取分页数据 + * @param coreSql + * @param orderByPartSql + * @param page + * @param pageSize + * @return + */ + public Map getPageData(String coreSql, String orderByPartSql, Integer page, Integer pageSize); + + /** + * 获取分页数据 + * @param selectSql + * @param fromAndWhereSql + * @param orderByPartSql + * @param page + * @param pageSize + * @return + */ + public Map getPageData(String selectSql, String fromAndWhereSql, String orderByPartSql, Integer page, Integer pageSize); + +} diff --git a/src/main/java/com/taover/repository/autoconfigure/TaoverRepositoryAutoConfiguration.java b/src/main/java/com/taover/repository/autoconfigure/TaoverRepositoryAutoConfiguration.java index a85825a..e4384e7 100644 --- a/src/main/java/com/taover/repository/autoconfigure/TaoverRepositoryAutoConfiguration.java +++ b/src/main/java/com/taover/repository/autoconfigure/TaoverRepositoryAutoConfiguration.java @@ -10,7 +10,10 @@ import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import com.taover.repository.jdbctemplate.JdbcTemplateBroadcast; +import com.taover.repository.jdbctemplate.JdbcTemplateBroadcastImpl; import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenant; import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenantImpl; import com.taover.repository.shardingsphere.ShardingInfoRepository; @@ -23,9 +26,12 @@ import com.taover.repository.shardingsphere.ShardingSphereService; @ConditionalOnClass({ShardingSphereService.class}) @ConditionalOnMissingBean(ShardingSphereService.class) public class TaoverRepositoryAutoConfiguration { - + @Resource + private JdbcTemplate jdbcTemplate; @Resource private ShardingSphereKeyGeneratorConfiguration config; + @Resource + private ShardingSphereService shardingSphereService; @Bean public ShardingSphereService shardingSphereService() { @@ -39,6 +45,11 @@ public class TaoverRepositoryAutoConfiguration { @Bean public JdbcTemplateWrapperTenant jdbcTemplateWrapperTenant() { - return new JdbcTemplateWrapperTenantImpl(); + return new JdbcTemplateWrapperTenantImpl(this.jdbcTemplate, this.shardingSphereService); + } + + @Bean + public JdbcTemplateBroadcast jdbcTemplateWrapperBroadcast() { + return new JdbcTemplateBroadcastImpl(this.jdbcTemplate, this.shardingSphereService); } } diff --git a/src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateBroadcast.java b/src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateBroadcast.java new file mode 100644 index 0000000..3817372 --- /dev/null +++ b/src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateBroadcast.java @@ -0,0 +1,976 @@ +package com.taover.repository.jdbctemplate; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.springframework.dao.DataAccessException; +import org.springframework.dao.IncorrectResultSizeDataAccessException; +import org.springframework.jdbc.core.BatchPreparedStatementSetter; +import org.springframework.jdbc.core.CallableStatementCallback; +import org.springframework.jdbc.core.CallableStatementCreator; +import org.springframework.jdbc.core.ColumnMapRowMapper; +import org.springframework.jdbc.core.ConnectionCallback; +import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter; +import org.springframework.jdbc.core.PreparedStatementCallback; +import org.springframework.jdbc.core.PreparedStatementCreator; +import org.springframework.jdbc.core.PreparedStatementCreatorFactory; +import org.springframework.jdbc.core.PreparedStatementSetter; +import org.springframework.jdbc.core.ResultSetExtractor; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.SingleColumnRowMapper; +import org.springframework.jdbc.core.SqlParameter; +import org.springframework.jdbc.core.SqlParameterValue; +import org.springframework.jdbc.core.SqlRowSetResultSetExtractor; +import org.springframework.jdbc.core.StatementCallback; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.jdbc.support.rowset.SqlRowSet; +import org.springframework.lang.Nullable; + +public interface JdbcTemplateBroadcast { + /** + * 加载分片信息 + * @param tenantId + */ + public void loadShardingInfo(String[] broadcastTableNames); + + /** + * 清空分片信息 + */ + public void clearShardingInfo(); + + //------------------------------------------------------------------------- + // Methods dealing with a plain java.sql.Connection + //------------------------------------------------------------------------- + + /** + * Execute a JDBC data access operation, implemented as callback action + * working on a JDBC Connection. This allows for implementing arbitrary + * data access operations, within Spring's managed JDBC environment: + * that is, participating in Spring-managed transactions and converting + * JDBC SQLExceptions into Spring's DataAccessException hierarchy. + *

The callback action can return a result object, for example a domain + * object or a collection of domain objects. + * @param action a callback object that specifies the action + * @return a result object returned by the action, or {@code null} if none + * @throws DataAccessException if there is any problem + */ + @Nullable + T execute(ConnectionCallback action, String[] broadcastTableNames) throws DataAccessException; + + + //------------------------------------------------------------------------- + // Methods dealing with static SQL (java.sql.Statement) + //------------------------------------------------------------------------- + + /** + * Execute a JDBC data access operation, implemented as callback action + * working on a JDBC Statement. This allows for implementing arbitrary data + * access operations on a single Statement, within Spring's managed JDBC + * environment: that is, participating in Spring-managed transactions and + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy. + *

The callback action can return a result object, for example a domain + * object or a collection of domain objects. + * @param action a callback that specifies the action + * @return a result object returned by the action, or {@code null} if none + * @throws DataAccessException if there is any problem + */ + @Nullable + T execute(StatementCallback action, String[] broadcastTableNames) throws DataAccessException; + + /** + * Issue a single SQL execute, typically a DDL statement. + * @param sql static SQL to execute + * @throws DataAccessException if there is any problem + */ + void execute(String sql, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute a query given static SQL, reading the ResultSet with a + * ResultSetExtractor. + *

Uses a JDBC Statement, not a PreparedStatement. If you want to + * execute a static query with a PreparedStatement, use the overloaded + * {@code query} method with {@code null} as argument array. + * @param sql the SQL query to execute + * @param rse a callback that will extract all rows of results + * @return an arbitrary result object, as returned by the ResultSetExtractor + * @throws DataAccessException if there is any problem executing the query + * @see #query(String, Object[], ResultSetExtractor) + */ + @Nullable + T query(String sql, ResultSetExtractor rse, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute a query given static SQL, reading the ResultSet on a per-row + * basis with a RowCallbackHandler. + *

Uses a JDBC Statement, not a PreparedStatement. If you want to + * execute a static query with a PreparedStatement, use the overloaded + * {@code query} method with {@code null} as argument array. + * @param sql the SQL query to execute + * @param rch a callback that will extract results, one row at a time + * @throws DataAccessException if there is any problem executing the query + * @see #query(String, Object[], RowCallbackHandler) + */ + void query(String sql, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute a query given static SQL, mapping each row to a result object + * via a RowMapper. + *

Uses a JDBC Statement, not a PreparedStatement. If you want to + * execute a static query with a PreparedStatement, use the overloaded + * {@code query} method with {@code null} as argument array. + * @param sql the SQL query to execute + * @param rowMapper a callback that will map one object per row + * @return the result List, containing mapped objects + * @throws DataAccessException if there is any problem executing the query + * @see #query(String, Object[], RowMapper) + */ + List query(String sql, RowMapper rowMapper, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute a query given static SQL, mapping a single result row to a + * result object via a RowMapper. + *

Uses a JDBC Statement, not a PreparedStatement. If you want to + * execute a static query with a PreparedStatement, use the overloaded + * {@link #queryForObject(String, RowMapper, Object...)} method with + * {@code null} as argument array. + * @param sql the SQL query to execute + * @param rowMapper a callback that will map one object per row + * @return the single mapped object (may be {@code null} if the given + * {@link RowMapper} returned {@code} null) + * @throws IncorrectResultSizeDataAccessException if the query does not + * return exactly one row + * @throws DataAccessException if there is any problem executing the query + * @see #queryForObject(String, Object[], RowMapper) + */ + @Nullable + T queryForObject(String sql, RowMapper rowMapper, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute a query for a result object, given static SQL. + *

Uses a JDBC Statement, not a PreparedStatement. If you want to + * execute a static query with a PreparedStatement, use the overloaded + * {@link #queryForObject(String, Class, Object...)} method with + * {@code null} as argument array. + *

This method is useful for running static SQL with a known outcome. + * The query is expected to be a single row/single column query; the returned + * result will be directly mapped to the corresponding object type. + * @param sql the SQL query to execute + * @param requiredType the type that the result object is expected to match + * @return the result object of the required type, or {@code null} in case of SQL NULL + * @throws IncorrectResultSizeDataAccessException if the query does not return + * exactly one row, or does not return exactly one column in that row + * @throws DataAccessException if there is any problem executing the query + * @see #queryForObject(String, Object[], Class) + */ + @Nullable + T queryForObject(String sql, Class requiredType, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute a query for a result map, given static SQL. + *

Uses a JDBC Statement, not a PreparedStatement. If you want to + * execute a static query with a PreparedStatement, use the overloaded + * {@link #queryForMap(String, Object...)} method with {@code null} + * as argument array. + *

The query is expected to be a single row query; the result row will be + * mapped to a Map (one entry for each column, using the column name as the key). + * @param sql the SQL query to execute + * @return the result Map (one entry per column, with column name as key) + * @throws IncorrectResultSizeDataAccessException if the query does not + * return exactly one row + * @throws DataAccessException if there is any problem executing the query + * @see #queryForMap(String, Object[]) + * @see ColumnMapRowMapper + */ + Map queryForMap(String sql, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute a query for a result list, given static SQL. + *

Uses a JDBC Statement, not a PreparedStatement. If you want to + * execute a static query with a PreparedStatement, use the overloaded + * {@code queryForList} method with {@code null} as argument array. + *

The results will be mapped to a List (one entry for each row) of + * result objects, each of them matching the specified element type. + * @param sql the SQL query to execute + * @param elementType the required type of element in the result list + * (for example, {@code Integer.class}) + * @return a List of objects that match the specified element type + * @throws DataAccessException if there is any problem executing the query + * @see #queryForList(String, Object[], Class) + * @see SingleColumnRowMapper + */ + List queryForList(String sql, Class elementType, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute a query for a result list, given static SQL. + *

Uses a JDBC Statement, not a PreparedStatement. If you want to + * execute a static query with a PreparedStatement, use the overloaded + * {@code queryForList} method with {@code null} as argument array. + *

The results will be mapped to a List (one entry for each row) of + * Maps (one entry for each column using the column name as the key). + * Each element in the list will be of the form returned by this interface's + * {@code queryForMap} methods. + * @param sql the SQL query to execute + * @return an List that contains a Map per row + * @throws DataAccessException if there is any problem executing the query + * @see #queryForList(String, Object[]) + */ + List> queryForList(String sql, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute a query for a SqlRowSet, given static SQL. + *

Uses a JDBC Statement, not a PreparedStatement. If you want to + * execute a static query with a PreparedStatement, use the overloaded + * {@code queryForRowSet} method with {@code null} as argument array. + *

The results will be mapped to an SqlRowSet which holds the data in a + * disconnected fashion. This wrapper will translate any SQLExceptions thrown. + *

Note that, for the default implementation, JDBC RowSet support needs to + * be available at runtime: by default, Sun's {@code com.sun.rowset.CachedRowSetImpl} + * class is used, which is part of JDK 1.5+ and also available separately as part of + * Sun's JDBC RowSet Implementations download (rowset.jar). + * @param sql the SQL query to execute + * @return a SqlRowSet representation (possibly a wrapper around a + * {@code javax.sql.rowset.CachedRowSet}) + * @throws DataAccessException if there is any problem executing the query + * @see #queryForRowSet(String, Object[]) + * @see SqlRowSetResultSetExtractor + * @see javax.sql.rowset.CachedRowSet + */ + SqlRowSet queryForRowSet(String sql, String[] broadcastTableNames) throws DataAccessException; + + /** + * Issue a single SQL update operation (such as an insert, update or delete statement). + * @param sql static SQL to execute + * @return the number of rows affected + * @throws DataAccessException if there is any problem. + */ + int update(String sql, String[] broadcastTableNames) throws DataAccessException; + + /** + * Issue multiple SQL updates on a single JDBC Statement using batching. + *

Will fall back to separate updates on a single Statement if the JDBC + * driver does not support batch updates. + * @param sql defining an array of SQL statements that will be executed. + * @return an array of the number of rows affected by each statement + * @throws DataAccessException if there is any problem executing the batch + */ + int[] batchUpdate(String[] broadcastTableNames, String... sql) throws DataAccessException; + + + //------------------------------------------------------------------------- + // Methods dealing with prepared statements + //------------------------------------------------------------------------- + + /** + * Execute a JDBC data access operation, implemented as callback action + * working on a JDBC PreparedStatement. This allows for implementing arbitrary + * data access operations on a single Statement, within Spring's managed JDBC + * environment: that is, participating in Spring-managed transactions and + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy. + *

The callback action can return a result object, for example a domain + * object or a collection of domain objects. + * @param psc a callback that creates a PreparedStatement given a Connection + * @param action a callback that specifies the action + * @return a result object returned by the action, or {@code null} if none + * @throws DataAccessException if there is any problem + */ + @Nullable + T execute(PreparedStatementCreator psc, PreparedStatementCallback action, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute a JDBC data access operation, implemented as callback action + * working on a JDBC PreparedStatement. This allows for implementing arbitrary + * data access operations on a single Statement, within Spring's managed JDBC + * environment: that is, participating in Spring-managed transactions and + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy. + *

The callback action can return a result object, for example a domain + * object or a collection of domain objects. + * @param sql the SQL to execute + * @param action a callback that specifies the action + * @return a result object returned by the action, or {@code null} if none + * @throws DataAccessException if there is any problem + */ + @Nullable + T execute(String sql, PreparedStatementCallback action, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query using a prepared statement, reading the ResultSet with a ResultSetExtractor. + *

A PreparedStatementCreator can either be implemented directly or + * configured through a PreparedStatementCreatorFactory. + * @param psc a callback that creates a PreparedStatement given a Connection + * @param rse a callback that will extract results + * @return an arbitrary result object, as returned by the ResultSetExtractor + * @throws DataAccessException if there is any problem + * @see PreparedStatementCreatorFactory + */ + @Nullable + T query(PreparedStatementCreator psc, ResultSetExtractor rse, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query using a prepared statement, reading the ResultSet with a ResultSetExtractor. + * @param sql the SQL query to execute + * @param pss a callback that knows how to set values on the prepared statement. + * If this is {@code null}, the SQL will be assumed to contain no bind parameters. + * Even if there are no bind parameters, this callback may be used to set the + * fetch size and other performance options. + * @param rse a callback that will extract results + * @return an arbitrary result object, as returned by the ResultSetExtractor + * @throws DataAccessException if there is any problem + */ + @Nullable + T query(String sql, @Nullable PreparedStatementSetter pss, ResultSetExtractor rse, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of arguments + * to bind to the query, reading the ResultSet with a ResultSetExtractor. + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * @param argTypes the SQL types of the arguments + * (constants from {@code java.sql.Types}) + * @param rse a callback that will extract results + * @return an arbitrary result object, as returned by the ResultSetExtractor + * @throws DataAccessException if the query fails + * @see java.sql.Types + */ + @Nullable + T query(String sql, Object[] args, int[] argTypes, ResultSetExtractor rse, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of arguments + * to bind to the query, reading the ResultSet with a ResultSetExtractor. + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @param rse a callback that will extract results + * @return an arbitrary result object, as returned by the ResultSetExtractor + * @throws DataAccessException if the query fails + */ + @Nullable + T query(String sql, Object[] args, ResultSetExtractor rse, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of arguments + * to bind to the query, reading the ResultSet with a ResultSetExtractor. + * @param sql the SQL query to execute + * @param rse a callback that will extract results + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @return an arbitrary result object, as returned by the ResultSetExtractor + * @throws DataAccessException if the query fails + * @since 3.0.1 + */ + @Nullable + T query(String sql, ResultSetExtractor rse, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException; + + /** + * Query using a prepared statement, reading the ResultSet on a per-row basis + * with a RowCallbackHandler. + *

A PreparedStatementCreator can either be implemented directly or + * configured through a PreparedStatementCreatorFactory. + * @param psc a callback that creates a PreparedStatement given a Connection + * @param rch a callback that will extract results, one row at a time + * @throws DataAccessException if there is any problem + * @see PreparedStatementCreatorFactory + */ + void query(PreparedStatementCreator psc, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a + * PreparedStatementSetter implementation that knows how to bind values to the + * query, reading the ResultSet on a per-row basis with a RowCallbackHandler. + * @param sql the SQL query to execute + * @param pss a callback that knows how to set values on the prepared statement. + * If this is {@code null}, the SQL will be assumed to contain no bind parameters. + * Even if there are no bind parameters, this callback may be used to set the + * fetch size and other performance options. + * @param rch a callback that will extract results, one row at a time + * @throws DataAccessException if the query fails + */ + void query(String sql, @Nullable PreparedStatementSetter pss, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, reading the ResultSet on a per-row basis + * with a RowCallbackHandler. + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * @param argTypes the SQL types of the arguments + * (constants from {@code java.sql.Types}) + * @param rch a callback that will extract results, one row at a time + * @throws DataAccessException if the query fails + * @see java.sql.Types + */ + void query(String sql, Object[] args, int[] argTypes, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, reading the ResultSet on a per-row basis + * with a RowCallbackHandler. + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @param rch a callback that will extract results, one row at a time + * @throws DataAccessException if the query fails + */ + void query(String sql, Object[] args, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, reading the ResultSet on a per-row basis + * with a RowCallbackHandler. + * @param sql the SQL query to execute + * @param rch a callback that will extract results, one row at a time + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @throws DataAccessException if the query fails + * @since 3.0.1 + */ + void query(String sql, RowCallbackHandler rch, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException; + + /** + * Query using a prepared statement, mapping each row to a result object + * via a RowMapper. + *

A PreparedStatementCreator can either be implemented directly or + * configured through a PreparedStatementCreatorFactory. + * @param psc a callback that creates a PreparedStatement given a Connection + * @param rowMapper a callback that will map one object per row + * @return the result List, containing mapped objects + * @throws DataAccessException if there is any problem + * @see PreparedStatementCreatorFactory + */ + List query(PreparedStatementCreator psc, RowMapper rowMapper, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a + * PreparedStatementSetter implementation that knows how to bind values + * to the query, mapping each row to a result object via a RowMapper. + * @param sql the SQL query to execute + * @param pss a callback that knows how to set values on the prepared statement. + * If this is {@code null}, the SQL will be assumed to contain no bind parameters. + * Even if there are no bind parameters, this callback may be used to set the + * fetch size and other performance options. + * @param rowMapper a callback that will map one object per row + * @return the result List, containing mapped objects + * @throws DataAccessException if the query fails + */ + List query(String sql, @Nullable PreparedStatementSetter pss, RowMapper rowMapper, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, mapping each row to a result object + * via a RowMapper. + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * @param argTypes the SQL types of the arguments + * (constants from {@code java.sql.Types}) + * @param rowMapper a callback that will map one object per row + * @return the result List, containing mapped objects + * @throws DataAccessException if the query fails + * @see java.sql.Types + */ + List query(String sql, Object[] args, int[] argTypes, RowMapper rowMapper, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, mapping each row to a result object + * via a RowMapper. + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @param rowMapper a callback that will map one object per row + * @return the result List, containing mapped objects + * @throws DataAccessException if the query fails + */ + List query(String sql, Object[] args, RowMapper rowMapper, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, mapping each row to a result object + * via a RowMapper. + * @param sql the SQL query to execute + * @param rowMapper a callback that will map one object per row + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @return the result List, containing mapped objects + * @throws DataAccessException if the query fails + * @since 3.0.1 + */ + List query(String sql, RowMapper rowMapper, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list + * of arguments to bind to the query, mapping a single result row to a + * result object via a RowMapper. + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type) + * @param argTypes the SQL types of the arguments + * (constants from {@code java.sql.Types}) + * @param rowMapper a callback that will map one object per row + * @return the single mapped object (may be {@code null} if the given + * {@link RowMapper} returned {@code} null) + * @throws IncorrectResultSizeDataAccessException if the query does not + * return exactly one row + * @throws DataAccessException if the query fails + */ + @Nullable + T queryForObject(String sql, Object[] args, int[] argTypes, RowMapper rowMapper, String[] broadcastTableNames) + throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list + * of arguments to bind to the query, mapping a single result row to a + * result object via a RowMapper. + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @param rowMapper a callback that will map one object per row + * @return the single mapped object (may be {@code null} if the given + * {@link RowMapper} returned {@code} null) + * @throws IncorrectResultSizeDataAccessException if the query does not + * return exactly one row + * @throws DataAccessException if the query fails + */ + @Nullable + T queryForObject(String sql, Object[] args, RowMapper rowMapper, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list + * of arguments to bind to the query, mapping a single result row to a + * result object via a RowMapper. + * @param sql the SQL query to execute + * @param rowMapper a callback that will map one object per row + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @return the single mapped object (may be {@code null} if the given + * {@link RowMapper} returned {@code} null) + * @throws IncorrectResultSizeDataAccessException if the query does not + * return exactly one row + * @throws DataAccessException if the query fails + * @since 3.0.1 + */ + @Nullable + T queryForObject(String sql, RowMapper rowMapper, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, expecting a result object. + *

The query is expected to be a single row/single column query; the returned + * result will be directly mapped to the corresponding object type. + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * @param argTypes the SQL types of the arguments + * (constants from {@code java.sql.Types}) + * @param requiredType the type that the result object is expected to match + * @return the result object of the required type, or {@code null} in case of SQL NULL + * @throws IncorrectResultSizeDataAccessException if the query does not return + * exactly one row, or does not return exactly one column in that row + * @throws DataAccessException if the query fails + * @see #queryForObject(String, Class) + * @see java.sql.Types + */ + @Nullable + T queryForObject(String sql, Object[] args, int[] argTypes, Class requiredType, String[] broadcastTableNames) + throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, expecting a result object. + *

The query is expected to be a single row/single column query; the returned + * result will be directly mapped to the corresponding object type. + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @param requiredType the type that the result object is expected to match + * @return the result object of the required type, or {@code null} in case of SQL NULL + * @throws IncorrectResultSizeDataAccessException if the query does not return + * exactly one row, or does not return exactly one column in that row + * @throws DataAccessException if the query fails + * @see #queryForObject(String, Class) + */ + @Nullable + T queryForObject(String sql, Object[] args, Class requiredType, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, expecting a result object. + *

The query is expected to be a single row/single column query; the returned + * result will be directly mapped to the corresponding object type. + * @param sql the SQL query to execute + * @param requiredType the type that the result object is expected to match + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @return the result object of the required type, or {@code null} in case of SQL NULL + * @throws IncorrectResultSizeDataAccessException if the query does not return + * exactly one row, or does not return exactly one column in that row + * @throws DataAccessException if the query fails + * @since 3.0.1 + * @see #queryForObject(String, Class) + */ + @Nullable + T queryForObject(String sql, Class requiredType, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, expecting a result map. + *

The query is expected to be a single row query; the result row will be + * mapped to a Map (one entry for each column, using the column name as the key). + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * @param argTypes the SQL types of the arguments + * (constants from {@code java.sql.Types}) + * @return the result Map (one entry per column, with column name as key) + * @throws IncorrectResultSizeDataAccessException if the query does not + * return exactly one row + * @throws DataAccessException if the query fails + * @see #queryForMap(String) + * @see ColumnMapRowMapper + * @see java.sql.Types + */ + Map queryForMap(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, expecting a result map. + *

The {@code queryForMap} methods defined by this interface are appropriate + * when you don't have a domain model. Otherwise, consider using one of the + * {@code queryForObject} methods. + *

The query is expected to be a single row query; the result row will be + * mapped to a Map (one entry for each column, using the column name as the key). + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @return the result Map (one entry for each column, using the + * column name as the key) + * @throws IncorrectResultSizeDataAccessException if the query does not + * return exactly one row + * @throws DataAccessException if the query fails + * @see #queryForMap(String) + * @see ColumnMapRowMapper + */ + Map queryForMap(String sql, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, expecting a result list. + *

The results will be mapped to a List (one entry for each row) of + * result objects, each of them matching the specified element type. + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * @param argTypes the SQL types of the arguments + * (constants from {@code java.sql.Types}) + * @param elementType the required type of element in the result list + * (for example, {@code Integer.class}) + * @return a List of objects that match the specified element type + * @throws DataAccessException if the query fails + * @see #queryForList(String, Class) + * @see SingleColumnRowMapper + */ + List queryForList(String sql, Object[] args, int[] argTypes, Class elementType, String[] broadcastTableNames) + throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, expecting a result list. + *

The results will be mapped to a List (one entry for each row) of + * result objects, each of them matching the specified element type. + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @param elementType the required type of element in the result list + * (for example, {@code Integer.class}) + * @return a List of objects that match the specified element type + * @throws DataAccessException if the query fails + * @see #queryForList(String, Class) + * @see SingleColumnRowMapper + */ + List queryForList(String sql, Object[] args, Class elementType, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, expecting a result list. + *

The results will be mapped to a List (one entry for each row) of + * result objects, each of them matching the specified element type. + * @param sql the SQL query to execute + * @param elementType the required type of element in the result list + * (for example, {@code Integer.class}) + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @return a List of objects that match the specified element type + * @throws DataAccessException if the query fails + * @since 3.0.1 + * @see #queryForList(String, Class) + * @see SingleColumnRowMapper + */ + List queryForList(String sql, Class elementType, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, expecting a result list. + *

The results will be mapped to a List (one entry for each row) of + * Maps (one entry for each column, using the column name as the key). + * Each element in the list will be of the form returned by this interface's + * {@code queryForMap} methods. + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * @param argTypes the SQL types of the arguments + * (constants from {@code java.sql.Types}) + * @return a List that contains a Map per row + * @throws DataAccessException if the query fails + * @see #queryForList(String) + * @see java.sql.Types + */ + List> queryForList(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, expecting a result list. + *

The results will be mapped to a List (one entry for each row) of + * Maps (one entry for each column, using the column name as the key). + * Each element in the list will be of the form returned by this interface's + * {@code queryForMap} methods. + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @return a List that contains a Map per row + * @throws DataAccessException if the query fails + * @see #queryForList(String) + */ + List> queryForList(String sql, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, expecting a SqlRowSet. + *

The results will be mapped to an SqlRowSet which holds the data in a + * disconnected fashion. This wrapper will translate any SQLExceptions thrown. + *

Note that, for the default implementation, JDBC RowSet support needs to + * be available at runtime: by default, Sun's {@code com.sun.rowset.CachedRowSetImpl} + * class is used, which is part of JDK 1.5+ and also available separately as part of + * Sun's JDBC RowSet Implementations download (rowset.jar). + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * @param argTypes the SQL types of the arguments + * (constants from {@code java.sql.Types}) + * @return a SqlRowSet representation (possibly a wrapper around a + * {@code javax.sql.rowset.CachedRowSet}) + * @throws DataAccessException if there is any problem executing the query + * @see #queryForRowSet(String) + * @see SqlRowSetResultSetExtractor + * @see javax.sql.rowset.CachedRowSet + * @see java.sql.Types + */ + SqlRowSet queryForRowSet(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames) throws DataAccessException; + + /** + * Query given SQL to create a prepared statement from SQL and a list of + * arguments to bind to the query, expecting a SqlRowSet. + *

The results will be mapped to an SqlRowSet which holds the data in a + * disconnected fashion. This wrapper will translate any SQLExceptions thrown. + *

Note that, for the default implementation, JDBC RowSet support needs to + * be available at runtime: by default, Sun's {@code com.sun.rowset.CachedRowSetImpl} + * class is used, which is part of JDK 1.5+ and also available separately as part of + * Sun's JDBC RowSet Implementations download (rowset.jar). + * @param sql the SQL query to execute + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @return a SqlRowSet representation (possibly a wrapper around a + * {@code javax.sql.rowset.CachedRowSet}) + * @throws DataAccessException if there is any problem executing the query + * @see #queryForRowSet(String) + * @see SqlRowSetResultSetExtractor + * @see javax.sql.rowset.CachedRowSet + */ + SqlRowSet queryForRowSet(String sql, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException; + + /** + * Issue a single SQL update operation (such as an insert, update or delete + * statement) using a PreparedStatementCreator to provide SQL and any + * required parameters. + *

A PreparedStatementCreator can either be implemented directly or + * configured through a PreparedStatementCreatorFactory. + * @param psc a callback that provides SQL and any necessary parameters + * @return the number of rows affected + * @throws DataAccessException if there is any problem issuing the update + * @see PreparedStatementCreatorFactory + */ + int update(PreparedStatementCreator psc, String[] broadcastTableNames) throws DataAccessException; + + /** + * Issue an update statement using a PreparedStatementCreator to provide SQL and + * any required parameters. Generated keys will be put into the given KeyHolder. + *

Note that the given PreparedStatementCreator has to create a statement + * with activated extraction of generated keys (a JDBC 3.0 feature). This can + * either be done directly or through using a PreparedStatementCreatorFactory. + * @param psc a callback that provides SQL and any necessary parameters + * @param generatedKeyHolder a KeyHolder that will hold the generated keys + * @return the number of rows affected + * @throws DataAccessException if there is any problem issuing the update + * @see PreparedStatementCreatorFactory + * @see org.springframework.jdbc.support.GeneratedKeyHolder + */ + int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder, String[] broadcastTableNames) throws DataAccessException; + + /** + * Issue an update statement using a PreparedStatementSetter to set bind parameters, + * with given SQL. Simpler than using a PreparedStatementCreator as this method + * will create the PreparedStatement: The PreparedStatementSetter just needs to + * set parameters. + * @param sql the SQL containing bind parameters + * @param pss helper that sets bind parameters. If this is {@code null} + * we run an update with static SQL. + * @return the number of rows affected + * @throws DataAccessException if there is any problem issuing the update + */ + int update(String sql, @Nullable PreparedStatementSetter pss, String[] broadcastTableNames) throws DataAccessException; + + /** + * Issue a single SQL update operation (such as an insert, update or delete statement) + * via a prepared statement, binding the given arguments. + * @param sql the SQL containing bind parameters + * @param args arguments to bind to the query + * @param argTypes the SQL types of the arguments + * (constants from {@code java.sql.Types}) + * @return the number of rows affected + * @throws DataAccessException if there is any problem issuing the update + * @see java.sql.Types + */ + int update(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames) throws DataAccessException; + + /** + * Issue a single SQL update operation (such as an insert, update or delete statement) + * via a prepared statement, binding the given arguments. + * @param sql the SQL containing bind parameters + * @param args arguments to bind to the query + * (leaving it to the PreparedStatement to guess the corresponding SQL type); + * may also contain {@link SqlParameterValue} objects which indicate not + * only the argument value but also the SQL type and optionally the scale + * @return the number of rows affected + * @throws DataAccessException if there is any problem issuing the update + */ + int update(String sql, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException; + + /** + * Issue multiple update statements on a single PreparedStatement, + * using batch updates and a BatchPreparedStatementSetter to set values. + *

Will fall back to separate updates on a single PreparedStatement + * if the JDBC driver does not support batch updates. + * @param sql defining PreparedStatement that will be reused. + * All statements in the batch will use the same SQL. + * @param pss object to set parameters on the PreparedStatement + * created by this method + * @return an array of the number of rows affected by each statement + * @throws DataAccessException if there is any problem issuing the update + */ + int[] batchUpdate(String sql, BatchPreparedStatementSetter pss, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute a batch using the supplied SQL statement with the batch of supplied arguments. + * @param sql the SQL statement to execute + * @param batchArgs the List of Object arrays containing the batch of arguments for the query + * @return an array containing the numbers of rows affected by each update in the batch + */ + int[] batchUpdate(String sql, List batchArgs, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute a batch using the supplied SQL statement with the batch of supplied arguments. + * @param sql the SQL statement to execute. + * @param batchArgs the List of Object arrays containing the batch of arguments for the query + * @param argTypes the SQL types of the arguments + * (constants from {@code java.sql.Types}) + * @return an array containing the numbers of rows affected by each update in the batch + */ + int[] batchUpdate(String sql, List batchArgs, int[] argTypes, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute multiple batches using the supplied SQL statement with the collect of supplied arguments. + * The arguments' values will be set using the ParameterizedPreparedStatementSetter. + * Each batch should be of size indicated in 'batchSize'. + * @param sql the SQL statement to execute. + * @param batchArgs the List of Object arrays containing the batch of arguments for the query + * @param batchSize batch size + * @param pss the ParameterizedPreparedStatementSetter to use + * @return an array containing for each batch another array containing the numbers of rows affected + * by each update in the batch + * @since 3.1 + */ + int[][] batchUpdate(String sql, Collection batchArgs, int batchSize, + ParameterizedPreparedStatementSetter pss, String[] broadcastTableNames) throws DataAccessException; + + + //------------------------------------------------------------------------- + // Methods dealing with callable statements + //------------------------------------------------------------------------- + + /** + * Execute a JDBC data access operation, implemented as callback action + * working on a JDBC CallableStatement. This allows for implementing arbitrary + * data access operations on a single Statement, within Spring's managed JDBC + * environment: that is, participating in Spring-managed transactions and + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy. + *

The callback action can return a result object, for example a domain + * object or a collection of domain objects. + * @param csc a callback that creates a CallableStatement given a Connection + * @param action a callback that specifies the action + * @return a result object returned by the action, or {@code null} if none + * @throws DataAccessException if there is any problem + */ + @Nullable + T execute(CallableStatementCreator csc, CallableStatementCallback action, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute a JDBC data access operation, implemented as callback action + * working on a JDBC CallableStatement. This allows for implementing arbitrary + * data access operations on a single Statement, within Spring's managed JDBC + * environment: that is, participating in Spring-managed transactions and + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy. + *

The callback action can return a result object, for example a domain + * object or a collection of domain objects. + * @param callString the SQL call string to execute + * @param action a callback that specifies the action + * @return a result object returned by the action, or {@code null} if none + * @throws DataAccessException if there is any problem + */ + @Nullable + T execute(String callString, CallableStatementCallback action, String[] broadcastTableNames) throws DataAccessException; + + /** + * Execute a SQL call using a CallableStatementCreator to provide SQL and + * any required parameters. + * @param csc a callback that provides SQL and any necessary parameters + * @param declaredParameters list of declared SqlParameter objects + * @return a Map of extracted out parameters + * @throws DataAccessException if there is any problem issuing the update + */ + Map call(CallableStatementCreator csc, List declaredParameters, String[] broadcastTableNames) throws DataAccessException; +} diff --git a/src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateBroadcastImpl.java b/src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateBroadcastImpl.java new file mode 100644 index 0000000..331b7b8 --- /dev/null +++ b/src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateBroadcastImpl.java @@ -0,0 +1,667 @@ +package com.taover.repository.jdbctemplate; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.apache.shardingsphere.api.hint.HintManager; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.BatchPreparedStatementSetter; +import org.springframework.jdbc.core.CallableStatementCallback; +import org.springframework.jdbc.core.CallableStatementCreator; +import org.springframework.jdbc.core.ConnectionCallback; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter; +import org.springframework.jdbc.core.PreparedStatementCallback; +import org.springframework.jdbc.core.PreparedStatementCreator; +import org.springframework.jdbc.core.PreparedStatementSetter; +import org.springframework.jdbc.core.ResultSetExtractor; +import org.springframework.jdbc.core.RowCallbackHandler; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.SqlParameter; +import org.springframework.jdbc.core.StatementCallback; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.jdbc.support.rowset.SqlRowSet; + +import com.taover.repository.shardingsphere.ShardingInfoEntity; +import com.taover.repository.shardingsphere.ShardingSphereService; + +public class JdbcTemplateBroadcastImpl implements JdbcTemplateBroadcast { + private JdbcTemplate jdbcTemplate; + private ShardingSphereService shardingSphereService; + + public JdbcTemplateBroadcastImpl(JdbcTemplate jdbcTemplate, ShardingSphereService shardingSphereService) { + this.jdbcTemplate = jdbcTemplate; + this.shardingSphereService = shardingSphereService; + } + + @Override + public void loadShardingInfo(String[] broadcastTableNames) { + List shardingInfo = this.shardingSphereService.getShardingInfoByTableNames(broadcastTableNames); + if(shardingInfo == null || shardingInfo.isEmpty()) { + return; + } + HintManager.clear(); + HintManager instance = HintManager.getInstance(); + for(ShardingInfoEntity item: shardingInfo) { + instance.addTableShardingValue(item.getTableName(), item.getTableSuffix()); + instance.addDatabaseShardingValue(item.getTableName(), item.getDsName()); + } + } + + @Override + public void clearShardingInfo() { + HintManager.clear(); + } + + @Override + public E execute(ConnectionCallback action, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.execute(action); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E execute(StatementCallback action, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.execute(action); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public void execute(String sql, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + this.jdbcTemplate.execute(sql); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E query(String sql, ResultSetExtractor rse, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.query(sql, rse); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public void query(String sql, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + this.jdbcTemplate.query(sql, rch); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public List query(String sql, RowMapper rowMapper, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.query(sql, rowMapper); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E queryForObject(String sql, RowMapper rowMapper, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForObject(sql, rowMapper); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E queryForObject(String sql, Class requiredType, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForObject(sql, requiredType); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public Map queryForMap(String sql, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForMap(sql); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public List queryForList(String sql, Class elementType, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForList(sql, elementType); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public List> queryForList(String sql, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForList(sql); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public SqlRowSet queryForRowSet(String sql, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForRowSet(sql); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public int update(String sql, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.update(sql); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public int[] batchUpdate(String[] broadcastTableNames, String... sql) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.batchUpdate(sql); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E execute(PreparedStatementCreator psc, PreparedStatementCallback action, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.execute(psc, action); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E execute(String sql, PreparedStatementCallback action, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.execute(sql, action); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E query(PreparedStatementCreator psc, ResultSetExtractor rse, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.query(psc, rse); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E query(String sql, PreparedStatementSetter pss, ResultSetExtractor rse, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.query(sql, pss, rse); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E query(String sql, Object[] args, int[] argTypes, ResultSetExtractor rse, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.query(sql, args, argTypes, rse); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E query(String sql, Object[] args, ResultSetExtractor rse, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.query(sql, args, rse); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E query(String sql, ResultSetExtractor rse, String[] broadcastTableNames, Object... args) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.query(sql, rse, args); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public void query(PreparedStatementCreator psc, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + this.jdbcTemplate.query(psc, rch); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public void query(String sql, PreparedStatementSetter pss, RowCallbackHandler rch, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + this.jdbcTemplate.query(sql, pss, rch); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public void query(String sql, Object[] args, int[] argTypes, RowCallbackHandler rch, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + this.jdbcTemplate.query(sql, args, argTypes, rch); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public void query(String sql, Object[] args, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + this.jdbcTemplate.query(sql, args, rch); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public void query(String sql, RowCallbackHandler rch, String[] broadcastTableNames, Object... args) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + this.jdbcTemplate.query(sql, rch, args); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public List query(PreparedStatementCreator psc, RowMapper rowMapper, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.query(psc, rowMapper); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public List query(String sql, PreparedStatementSetter pss, RowMapper rowMapper, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.query(sql, pss, rowMapper); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public List query(String sql, Object[] args, int[] argTypes, RowMapper rowMapper, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.query(sql, args, argTypes, rowMapper); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public List query(String sql, Object[] args, RowMapper rowMapper, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.query(sql, args, rowMapper); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public List query(String sql, RowMapper rowMapper, String[] broadcastTableNames, Object... args) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.query(sql, rowMapper, args); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E queryForObject(String sql, Object[] args, int[] argTypes, RowMapper rowMapper, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForObject(sql, args, argTypes, rowMapper); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E queryForObject(String sql, Object[] args, RowMapper rowMapper, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForObject(sql, args, rowMapper); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E queryForObject(String sql, RowMapper rowMapper, String[] broadcastTableNames, Object... args) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForObject(sql, rowMapper, args); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E queryForObject(String sql, Object[] args, int[] argTypes, Class requiredType, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForObject(sql, args, argTypes, requiredType); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E queryForObject(String sql, Object[] args, Class requiredType, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForObject(sql, args, requiredType); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E queryForObject(String sql, Class requiredType, String[] broadcastTableNames, Object... args) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForObject(sql, requiredType, args); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public Map queryForMap(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForMap(sql, args, argTypes); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public Map queryForMap(String sql, String[] broadcastTableNames, Object... args) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForMap(sql, args); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public List queryForList(String sql, Object[] args, int[] argTypes, Class elementType, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForList(sql, args, argTypes, elementType); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public List queryForList(String sql, Object[] args, Class elementType, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForList(sql, args, elementType); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public List queryForList(String sql, Class elementType, String[] broadcastTableNames, Object... args) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForList(sql, elementType, args); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public List> queryForList(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForList(sql, args, argTypes); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public List> queryForList(String sql, String[] broadcastTableNames, Object... args) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForList(sql, args); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public SqlRowSet queryForRowSet(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForRowSet(sql, args, argTypes); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public SqlRowSet queryForRowSet(String sql, String[] broadcastTableNames, Object... args) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.queryForRowSet(sql, args); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public int update(PreparedStatementCreator psc, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.update(psc); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.update(psc, generatedKeyHolder); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public int update(String sql, PreparedStatementSetter pss, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.update(sql, pss); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public int update(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.update(sql, args, argTypes); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public int update(String sql, String[] broadcastTableNames, Object... args) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.update(sql, args); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public int[] batchUpdate(String sql, BatchPreparedStatementSetter pss, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.batchUpdate(sql, pss); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public int[] batchUpdate(String sql, List batchArgs, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.batchUpdate(sql, batchArgs); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public int[] batchUpdate(String sql, List batchArgs, int[] argTypes, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.batchUpdate(sql, batchArgs); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public int[][] batchUpdate(String sql, Collection batchArgs, int batchSize, + ParameterizedPreparedStatementSetter pss, String[] broadcastTableNames) throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.batchUpdate(sql, batchArgs, batchSize, pss); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E execute(CallableStatementCreator csc, CallableStatementCallback action, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.execute(csc, action); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public E execute(String callString, CallableStatementCallback action, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.execute(callString, action); + }finally { + this.clearShardingInfo(); + } + } + + @Override + public Map call(CallableStatementCreator csc, List declaredParameters, String[] broadcastTableNames) + throws DataAccessException { + try { + this.loadShardingInfo(broadcastTableNames); + return this.jdbcTemplate.call(csc, declaredParameters); + }finally { + this.clearShardingInfo(); + } + } +} diff --git a/src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateWrapperTenant.java b/src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateWrapperTenant.java index 9be7663..957ecc8 100644 --- a/src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateWrapperTenant.java +++ b/src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateWrapperTenant.java @@ -29,7 +29,17 @@ import org.springframework.jdbc.support.rowset.SqlRowSet; import org.springframework.lang.Nullable; public interface JdbcTemplateWrapperTenant { - + /** + * 加载分片信息 + * @param tenantId + */ + public void loadShardingInfo(Long tenantId); + + /** + * 清空分片信息 + */ + public void clearShardingInfo(); + //------------------------------------------------------------------------- // Methods dealing with a plain java.sql.Connection //------------------------------------------------------------------------- diff --git a/src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateWrapperTenantImpl.java b/src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateWrapperTenantImpl.java index 8fdea27..825f4c0 100644 --- a/src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateWrapperTenantImpl.java +++ b/src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateWrapperTenantImpl.java @@ -4,8 +4,6 @@ import java.util.Collection; import java.util.List; import java.util.Map; -import javax.annotation.Resource; - import org.apache.shardingsphere.api.hint.HintManager; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.BatchPreparedStatementSetter; @@ -29,13 +27,17 @@ import com.taover.repository.shardingsphere.ShardingInfoEntity; import com.taover.repository.shardingsphere.ShardingSphereService; public class JdbcTemplateWrapperTenantImpl implements JdbcTemplateWrapperTenant { - @Resource private JdbcTemplate jdbcTemplate; - @Resource private ShardingSphereService shardingSphereService; - private void loadShardingInfo(Long tenantId) { - List shardingInfo = this.shardingSphereService.getShardingInfoMapByTenantId(tenantId); + public JdbcTemplateWrapperTenantImpl(JdbcTemplate jdbcTemplate, ShardingSphereService shardingSphereService) { + this.jdbcTemplate = jdbcTemplate; + this.shardingSphereService = shardingSphereService; + } + + @Override + public void loadShardingInfo(Long tenantId) { + List shardingInfo = this.shardingSphereService.getShardingInfoByTenantId(tenantId); if(shardingInfo == null || shardingInfo.isEmpty()) { return; } @@ -47,7 +49,8 @@ public class JdbcTemplateWrapperTenantImpl implements JdbcTemplateWrapperTenant } } - private void clearShardingInfo() { + @Override + public void clearShardingInfo() { HintManager.clear(); } diff --git a/src/main/java/com/taover/repository/shardingsphere/ShardingSphereService.java b/src/main/java/com/taover/repository/shardingsphere/ShardingSphereService.java index 251d9af..7153bc4 100644 --- a/src/main/java/com/taover/repository/shardingsphere/ShardingSphereService.java +++ b/src/main/java/com/taover/repository/shardingsphere/ShardingSphereService.java @@ -14,6 +14,7 @@ import com.taover.repository.autoconfigure.ShardingSphereKeyGeneratorConfigurati @Service public class ShardingSphereService { private Map> CACHED_TABLE_SUFFIX_BY_TENANT = null; + private Map> CACHED_TABLE_SUFFIX_BY_TABLE_NAME = null; private Map GENERATOR_HOLDER = new HashMap(); @Resource @@ -31,25 +32,31 @@ public class ShardingSphereService { return GENERATOR_HOLDER.get(tableName).generateKeyList(number); } - public List getShardingInfoMapByTenantId(Long tenantId) { + public List getShardingInfoByTenantId(Long tenantId) { if(CACHED_TABLE_SUFFIX_BY_TENANT == null) { - loadCacheTableShardingInfoByTenantId(); + loadCacheTableShardingInfo(); } return CACHED_TABLE_SUFFIX_BY_TENANT.get(tenantId); } - private synchronized void loadCacheTableShardingInfoByTenantId() { - if(CACHED_TABLE_SUFFIX_BY_TENANT != null) { + private synchronized void loadCacheTableShardingInfo() { + if(CACHED_TABLE_SUFFIX_BY_TENANT != null && CACHED_TABLE_SUFFIX_BY_TABLE_NAME != null) { return; - } + } List dataList = this.shardingInfoRepository.findListBySql("1=1"); Map> tempData = new HashMap>(); + Map> tempDataTableName = new HashMap>(); for(ShardingInfoEntity item: dataList) { List tempItem = tempData.getOrDefault(item.getTenantId(), new ArrayList()); tempItem.add(item); tempData.put(item.getTenantId(), tempItem); + + List tempItemTableName = tempDataTableName.getOrDefault(item.getTableName(), new ArrayList()); + tempItemTableName.add(item); + tempDataTableName.put(item.getTableName(), tempItemTableName); } CACHED_TABLE_SUFFIX_BY_TENANT = tempData; + CACHED_TABLE_SUFFIX_BY_TABLE_NAME = tempDataTableName; } private synchronized void loadShardingKeyGenerator(String tableName) { @@ -60,4 +67,21 @@ public class ShardingSphereService { generator.loalConfig(config); GENERATOR_HOLDER.put(tableName, generator); } + + public List getShardingInfoByTableNames(String[] broadcastTableNames) { + if(broadcastTableNames == null || broadcastTableNames.length == 0) { + return null; + } + if(CACHED_TABLE_SUFFIX_BY_TABLE_NAME == null) { + loadCacheTableShardingInfo(); + } + List dataList = new ArrayList(); + for(String item: broadcastTableNames) { + List tempData = CACHED_TABLE_SUFFIX_BY_TABLE_NAME.get(item); + if(tempData != null && !tempData.isEmpty()) { + dataList.addAll(tempData); + } + } + return dataList; + } } diff --git a/src/test/java/com/taover/repository/test/TestAutoconfigure.java b/src/test/java/com/taover/repository/test/TestAutoconfigure.java index 093b167..b30c82b 100644 --- a/src/test/java/com/taover/repository/test/TestAutoconfigure.java +++ b/src/test/java/com/taover/repository/test/TestAutoconfigure.java @@ -5,6 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.scheduling.annotation.EnableScheduling; +import com.taover.repository.jdbctemplate.JdbcTemplateBroadcast; import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenant; @SpringBootApplication @@ -12,10 +13,14 @@ import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenant; public class TestAutoconfigure { public static void main(String args[]) { ConfigurableApplicationContext context = SpringApplication.run(TestAutoconfigure.class, args); - JdbcTemplateWrapperTenant jdbcTemplate = context.getBean(JdbcTemplateWrapperTenant.class); - System.out.println(jdbcTemplate.queryForObject("select id from wxorder_order limit 1", Long.class, 1L)); - System.out.println(jdbcTemplate.queryForList("select * from wxorder_order limit 1", 1L)); - System.out.println(jdbcTemplate.queryForList("select * from wxorder_order limit 1", 2L)); - System.out.println(jdbcTemplate.queryForList("select * from wxorder_order_express limit 1", 1L)); + + JdbcTemplateBroadcast jdbcTemplateB = context.getBean(JdbcTemplateBroadcast.class); + System.out.println(jdbcTemplateB.queryForObject("select id from wxorder_order order by id desc limit 5 ", String.class, new String[]{"wxorder_order"})); + +// JdbcTemplateWrapperTenant jdbcTemplate = context.getBean(JdbcTemplateWrapperTenant.class); +// System.out.println(jdbcTemplate.queryForObject("select id from wxorder_order limit 1", Long.class, 1L)); +// System.out.println(jdbcTemplate.queryForList("select * from wxorder_order limit 1", 1L)); +// System.out.println(jdbcTemplate.queryForList("select * from wxorder_order limit 1", 2L)); +// System.out.println(jdbcTemplate.queryForList("select * from wxorder_order_express limit 1", 1L)); } } diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index 7c3dd14..007fa12 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -13,12 +13,9 @@ spring.gson.serialize-nulls=true spring.mvc.dispatch-options-request=true # shardingspere -spring.shardingsphere.datasource.names=ds0 +spring.shardingsphere.datasource.names=ds0,ds1 spring.shardingsphere.datasource.ds0.type=com.alibaba.druid.pool.DruidDataSource spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver -#spring.shardingsphere.datasource.ds_0.url=jdbc:mysql://121.42.142.102:3306/bzyun_wxorder?characterEncoding=UTF-8&zeroDateTimeBehavior=CONVERT_TO_NULL -#spring.shardingsphere.datasource.ds_0.username=dev -#spring.shardingsphere.datasource.ds_0.password=taover02 spring.shardingsphere.datasource.ds0.url=jdbc:mysql://rdsifmezqifmezqo.mysql.rds.aliyuncs.com:3306/bzyun_wxorder?characterEncoding=UTF-8 spring.shardingsphere.datasource.ds0.username=tylife spring.shardingsphere.datasource.ds0.password=lexi365 @@ -27,7 +24,17 @@ spring.shardingsphere.datasource.ds0.max-active=20 spring.shardingsphere.datasource.ds0.min-idle=5 spring.shardingsphere.datasource.ds0.max-wait=60000 -spring.shardingsphere.sharding.tables.wxorder_order.actual-data-nodes=ds0.wxorder_order +spring.shardingsphere.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource +spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver +spring.shardingsphere.datasource.ds1.url=jdbc:mysql://121.42.142.102:3306/bzyun_wxorder?characterEncoding=UTF-8 +spring.shardingsphere.datasource.ds1.username=dev +spring.shardingsphere.datasource.ds1.password=taover02 +spring.shardingsphere.datasource.ds1.initial-size=10 +spring.shardingsphere.datasource.ds1.max-active=20 +spring.shardingsphere.datasource.ds1.min-idle=5 +spring.shardingsphere.datasource.ds1.max-wait=60000 + +spring.shardingsphere.sharding.tables.wxorder_order.actual-data-nodes=ds0.wxorder_order,ds1.wxorder_order spring.shardingsphere.sharding.tables.wxorder_order.database-strategy.hint.algorithm-class-name=com.taover.repository.shardingsphere.ShardingDatabaseAlgorithmHint spring.shardingsphere.sharding.tables.wxorder_order.table-strategy.hint.algorithm-class-name=com.taover.repository.shardingsphere.ShardingTableAlgorithmHint spring.shardingsphere.sharding.tables.wxorder_order.key-generator.column=id -- libgit2 0.21.2