Commit 7de08bb02302ea0169762d508ac55e51eec3356f

Authored by 王彬
1 parent 9fee2037

增加支持广播SQL

build.gradle
... ... @@ -57,7 +57,7 @@ uploadArchives {
57 57 authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD)
58 58 }
59 59 pom.project {
60   - version '2.1.48'
  60 + version '2.1.52'
61 61 artifactId ARTIFACT_Id
62 62 groupId GROUP_ID
63 63 packaging TYPE
... ...
src/main/java/com/taover/repository/CustomJdbcTemplateBroadcast.java 0 → 100644
... ... @@ -0,0 +1,546 @@
  1 +package com.taover.repository;
  2 +
  3 +import java.io.Serializable;
  4 +import java.lang.reflect.Field;
  5 +import java.lang.reflect.ParameterizedType;
  6 +import java.math.BigDecimal;
  7 +import java.util.ArrayList;
  8 +import java.util.HashMap;
  9 +import java.util.Iterator;
  10 +import java.util.List;
  11 +import java.util.Map;
  12 +
  13 +import javax.annotation.Resource;
  14 +import javax.persistence.Column;
  15 +import javax.persistence.Id;
  16 +import javax.persistence.Table;
  17 +
  18 +import org.springframework.dao.DataAccessException;
  19 +
  20 +import com.taover.repository.exception.MultiRowException;
  21 +import com.taover.repository.exception.NoContainTenantException;
  22 +import com.taover.repository.exception.NotFoundException;
  23 +import com.taover.repository.exception.ObjectReflectException;
  24 +import com.taover.repository.jdbctemplate.JdbcTemplateBroadcast;
  25 +import com.taover.repository.mapper.CustomJdbcTemplateRowMapper;
  26 +import com.taover.repository.util.UtilsSql;
  27 +
  28 +/**
  29 + *
  30 + * @author root
  31 + *
  32 + * @param <T>
  33 + * @param <ID>
  34 + */
  35 +public class CustomJdbcTemplateBroadcast<T, ID extends Serializable> implements CustomJdbcTemplateBroadcastInterface<T, ID>{
  36 + @Resource
  37 + private JdbcTemplateBroadcast _jdbcTemplateBroadcast;
  38 +
  39 + private Map<String, String> _beanToTableField;
  40 + private Map<String, String> _tableToBeanField;
  41 + private String _tableFieldNameListGapWithComma;
  42 + private String _idTableFieldName;
  43 + private String _dbName;
  44 + private String _tableName;
  45 + private Class<T> _tClassInfo;
  46 + private CustomJdbcTemplateRowMapper<T> _customJdbcTemplateRowMapper;
  47 +
  48 + public CustomJdbcTemplateRowMapper<T> getCustomJdbcTemplateRowMapper(){
  49 + return this._customJdbcTemplateRowMapper;
  50 + }
  51 +
  52 + @SuppressWarnings("unchecked")
  53 + public CustomJdbcTemplateBroadcast() throws Exception{
  54 + //获取泛型类Class
  55 + this._tClassInfo = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
  56 +
  57 + //检查实体声明
  58 + Table annoTable = (Table) _tClassInfo.getAnnotation(Table.class);
  59 + if(annoTable == null){
  60 + throw new Exception("DAO层初始化失败,失败原因:"+_tClassInfo.getName()+"实体类,没有@Table注解指定表名");
  61 + }
  62 + this._tableName = annoTable.name();
  63 + String schema = annoTable.schema();
  64 + String catalog = annoTable.catalog();
  65 + if(schema != null && !"".equals(schema)){
  66 + this._dbName = schema;
  67 + }else if(catalog != null && !"".equals(catalog)){
  68 + this._dbName = catalog;
  69 + }
  70 +
  71 + //初始化数据
  72 + _beanToTableField = new HashMap<String, String>();
  73 + _tableToBeanField = new HashMap<String, String>();
  74 + _tableFieldNameListGapWithComma = "";
  75 + Field[] declaredFields = _tClassInfo.getDeclaredFields();
  76 + for(int i=0; i<declaredFields.length; ++i){
  77 + Field currField = declaredFields[i];
  78 + String fieldName = currField.getName();
  79 + Id annoId = (Id)currField.getAnnotation(Id.class);
  80 + Column annoColumn = (Column)currField.getAnnotation(Column.class);
  81 + if(annoId != null){
  82 + if(annoColumn == null){
  83 + _idTableFieldName = this.camelToUnderline(fieldName);
  84 + }else{
  85 + _idTableFieldName = annoColumn.name();
  86 + }
  87 + _tableFieldNameListGapWithComma += _idTableFieldName+",";
  88 + _beanToTableField.put(fieldName, _idTableFieldName);
  89 + _tableToBeanField.put(_idTableFieldName, fieldName);
  90 + }else{
  91 + if(annoColumn != null){
  92 + String tableFieldName = annoColumn.name();
  93 + _tableFieldNameListGapWithComma += tableFieldName+",";
  94 + _beanToTableField.put(fieldName, tableFieldName);
  95 + _tableToBeanField.put(tableFieldName, fieldName);
  96 + }
  97 + }
  98 + }
  99 +
  100 + //检验是否有属性
  101 + if(_beanToTableField.isEmpty()){
  102 + throw new Exception("DAO层初始化失败,失败原因:"+this._tClassInfo.getName()+"实体类,没有在实体中找到属性信息");
  103 + }
  104 +
  105 + //去除逗号
  106 + _tableFieldNameListGapWithComma = _tableFieldNameListGapWithComma.substring(0, _tableFieldNameListGapWithComma.length()-1);
  107 +
  108 + //创建rowmapper
  109 + this._customJdbcTemplateRowMapper = new CustomJdbcTemplateRowMapper<T>(this._tClassInfo, this._tableToBeanField);
  110 + }
  111 +
  112 + /**
  113 + * 将驼峰式命名的字符串转换为下划线大写方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。</br>
  114 + * 例如:HelloWorld->HELLO_WORLD
  115 + * @param name 转换前的驼峰式命名的字符串
  116 + * @return 转换后下划线大写方式命名的字符串
  117 + */
  118 + private String camelToUnderline(String name) {
  119 + StringBuilder result = new StringBuilder();
  120 + if (name != null && name.length() > 0) {
  121 + // 将第一个字符处理成大写
  122 + result.append(name.substring(0, 1).toUpperCase());
  123 + // 循环处理其余字符
  124 + for (int i = 1; i < name.length(); i++) {
  125 + String s = name.substring(i, i + 1);
  126 + // 在大写字母前添加下划线
  127 + if (Character.isUpperCase(s.charAt(0)) && Character.isLetter(s.charAt(0))) {
  128 + result.append("_");
  129 + }
  130 + // 其他字符直接转成大写
  131 + result.append(s.toUpperCase());
  132 + }
  133 + }
  134 + return result.toString();
  135 + }
  136 +
  137 + private void appendWhereCondition(StringBuffer sql, StringBuffer pql, List<Object> list, List<Object[]> condition) {
  138 + if (condition == null || condition.size() == 0) return;
  139 + Object[] con = condition.get(0);
  140 + int iLen = condition.size();
  141 + sql.append(" WHERE ");
  142 + pql.append(" WHERE ");
  143 + sql.append(con[0]);
  144 + pql.append(con[0]);
  145 + if (null != con[1] && con[1] != "" && con[1] != "useArg[0]") {
  146 + sql.append(" " + con[1] + " ?");
  147 + pql.append(" " + con[1] + " " + con[2]);
  148 + list.add(con[2]);
  149 + }
  150 + for (int i = 1; i < iLen; i++) {
  151 + con = condition.get(i);
  152 + sql.append(" AND ");
  153 + pql.append(" AND ");
  154 + sql.append(con[0]);
  155 + pql.append(con[0]);
  156 + if (null == con[1] || "" == con[1] || con[1] == "useArg[0]") continue;
  157 + sql.append(" " + con[1] + " ?");
  158 + pql.append(" " + con[1] + " " + con[2]);
  159 + list.add(con[2]);
  160 + }
  161 + }
  162 +
  163 + private void appendWhereConditionForCount(StringBuffer sql, List<Object[]> condition) {
  164 + if (condition == null || condition.size() == 0) return;
  165 + Object[] con = condition.get(0);
  166 + int iLen = condition.size();
  167 + sql.append(" WHERE ");
  168 + sql.append(con[0]);
  169 + if (null != con[1] && con[1] != "" && con[1] != "useArg[0]") {
  170 + sql.append(" " + con[1] + " ?");
  171 + }
  172 + for (int i = 1; i < iLen; i++) {
  173 + con = condition.get(i);
  174 + sql.append(" AND ");
  175 + sql.append(con[0]);
  176 + if (null == con[1] || "" == con[1] || con[1] == "useArg[0]") continue;
  177 + sql.append(" " + con[1] + " ?");
  178 + }
  179 + }
  180 +
  181 + private void appendSetSql(StringBuffer sql, StringBuffer pql, List<Object> list, List<Object[]> obj) {
  182 + for (Object[] arg : obj) {
  183 + if (arg.length > 2) {
  184 + sql.append(" " + arg[0] + " = " + arg[0] + arg[2] + " ?,");
  185 + pql.append(" " + arg[0] + " = " + arg[0] + arg[2] + arg[1] +",");
  186 + list.add(arg[1]);
  187 + }else if(arg.length == 2) {
  188 + sql.append(" " + arg[0] + " = ?,");
  189 + pql.append(" " + arg[0] + " = " + arg[1] + ",");
  190 + list.add(arg[1]);
  191 + }else if(arg.length == 1) {
  192 + sql.append(" " + arg[0] + ",");
  193 + pql.append(" " + arg[0] + ",");
  194 + }
  195 + }
  196 + }
  197 +
  198 + private String getTableSql(){
  199 + return (this._dbName == null || "".equals(this._dbName.trim()))?
  200 + ("`"+this._tableName+"`"):
  201 + ("`"+this._dbName+"`.`"+this._tableName+"`");
  202 + }
  203 +
  204 + private String constructUpdateSql(T entity, List<Field> beanFieldList) {
  205 + StringBuffer sqlInsertPart = new StringBuffer("INSERT INTO "+this.getTableSql()+"(");
  206 + Iterator<String> beanFieldIter = this._beanToTableField.keySet().iterator();
  207 + while(beanFieldIter.hasNext()){
  208 + String beanFieldName = beanFieldIter.next();
  209 + String tableFieldName = this._beanToTableField.get(beanFieldName);
  210 + Field beanField = null;
  211 + try {
  212 + beanField = this._tClassInfo.getDeclaredField(beanFieldName);
  213 + beanField.setAccessible(true);
  214 + if(beanField.get(entity) == null) {
  215 + continue;
  216 + }
  217 + } catch (Exception e) {
  218 + continue;
  219 + }
  220 +
  221 + if(tableFieldName == null || beanFieldName == null){
  222 + continue;
  223 + }
  224 +
  225 + beanFieldList.add(beanField);
  226 + sqlInsertPart.append("`"+tableFieldName+"`,");
  227 + }
  228 + return sqlInsertPart.substring(0, sqlInsertPart.length()-1)+")";
  229 + }
  230 +
  231 + private Object getDefaultValueByFieldType(Field itemField) {
  232 + String simpleName = itemField.getType().getSimpleName();
  233 + if("String".equals(simpleName)) {
  234 + return "";
  235 + }else if("Date".equals(simpleName) || "Timestamp".equals(simpleName)) {
  236 + return "2000-01-01 00:00:00";
  237 + }else if("BigDecimal".equals(simpleName)){
  238 + return BigDecimal.ZERO;
  239 + }else {
  240 + return 0;
  241 + }
  242 + }
  243 +
  244 + @Override
  245 + public T findEntityByID(ID id) throws NotFoundException {
  246 + return findEntityByID(id, false);
  247 + }
  248 +
  249 + @Override
  250 + public T findEntityByID(ID id, boolean isLock) throws NotFoundException {
  251 + StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql());
  252 + sql.append(" WHERE "+_idTableFieldName+" = ? ");
  253 + if (isLock) {
  254 + sql.append(" FOR UPDATE");
  255 + }
  256 + try {
  257 + return (T) _jdbcTemplateBroadcast.queryForObject(sql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName}, id);
  258 + }catch (DataAccessException e) {
  259 + throw new NotFoundException(e);
  260 + }
  261 + }
  262 +
  263 + @Override
  264 + public T findEntityByCondition(List<Object[]> condition) throws NotFoundException, MultiRowException, NoContainTenantException {
  265 + List<T> tempList = findListByCondition(condition);
  266 + if(tempList == null || tempList.size() == 0){
  267 + throw new NotFoundException();
  268 + }
  269 + if(tempList != null && tempList.size() == 1){
  270 + return tempList.get(0);
  271 + }else{
  272 + throw new MultiRowException();
  273 + }
  274 + }
  275 +
  276 + @Override
  277 + public T findEntityBySql(String sqlCondition) throws NotFoundException, MultiRowException {
  278 + List<T> tempList = findListBySql(sqlCondition);
  279 + if(tempList == null || tempList.size() == 0){
  280 + throw new NotFoundException();
  281 + }
  282 + if(tempList != null && tempList.size() == 1){
  283 + return tempList.get(0);
  284 + }else{
  285 + throw new MultiRowException();
  286 + }
  287 + }
  288 +
  289 + @Override
  290 + public List<T> findListByCondition(List<Object[]> condition){
  291 + return findListByCondition(condition, null);
  292 + }
  293 +
  294 + @Override
  295 + public List<T> findListByCondition(List<Object[]> condition, String sortCondition){
  296 + StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql());
  297 + List<Object> list = new ArrayList<Object>();
  298 + this.appendWhereCondition(sql, new StringBuffer(), list, condition);
  299 + if(sortCondition != null && !sortCondition.equals("")){
  300 + sql.append(" " + sortCondition + " ");
  301 + }
  302 + return (List<T>)_jdbcTemplateBroadcast.query(sql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName}, list.toArray());
  303 + }
  304 +
  305 + @Override
  306 + public List<T> findListBySql(String sqlCondition){
  307 + StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql()+" WHERE " + sqlCondition);
  308 + return (List<T>)_jdbcTemplateBroadcast.query(sql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName});
  309 + }
  310 +
  311 + @Override
  312 + public Map<String, Object> findPageByCondition(List<Object[]> condition, int page, int pageSize){
  313 + return findPageByCondition(condition, null , page, pageSize);
  314 + }
  315 +
  316 + @Override
  317 + public Map<String, Object> findPageByCondition(List<Object[]> condition, String sortCondition, int page, int pageSize){
  318 + StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql());
  319 + StringBuffer pql = new StringBuffer(sql.toString());
  320 + StringBuffer sqlCount = new StringBuffer("SELECT COUNT(1) rowCount FROM "+this.getTableSql());
  321 + List<Object> count_list = new ArrayList<Object>();
  322 + List<Object> page_list = new ArrayList<Object>();
  323 + this.appendWhereConditionForCount(sqlCount, condition);
  324 + this.appendWhereCondition(sql, pql, count_list, condition);
  325 + for (int i = 0; i < count_list.size(); i++)
  326 + page_list.add(count_list.get(i));
  327 +
  328 + page_list.add((page - 1) * pageSize);
  329 + page_list.add(pageSize);
  330 +
  331 + if(sortCondition != null && !sortCondition.equals("")){
  332 + sql.append(" " + sortCondition + " ");
  333 + pql.append(" " + sortCondition + " ");
  334 + }
  335 +
  336 + String pageSql = sql.toString() + " limit ?, ?";
  337 + Map<String, Object> totalRowsMap = _jdbcTemplateBroadcast.queryForMap(sqlCount.toString(), new String[] {this._tableName}, count_list.toArray()) ;
  338 + List<T> resultList = _jdbcTemplateBroadcast.query(pageSql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName}, page_list.toArray());
  339 + return UtilsSql.createPage(page, pageSize, Integer.valueOf(totalRowsMap.get("rowCount").toString()), resultList);
  340 + }
  341 +
  342 + @Override
  343 + public Map<String, Object> findPageBySql(String sqlCondition, int page, int pageSize){
  344 + StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql()+" WHERE " + sqlCondition);
  345 + StringBuffer sqlCount = new StringBuffer("SELECT count(1) rowCount FROM "+this.getTableSql()+" WHERE " + sqlCondition);
  346 + sql.append(" limit ?, ?");
  347 + List<Object> page_list = new ArrayList<Object>();
  348 + page_list.add((page - 1) * pageSize);
  349 + page_list.add(page * pageSize);
  350 +
  351 + Map<String, Object> totalRowsMap = _jdbcTemplateBroadcast.queryForMap(sqlCount.toString(), new String[] {this._tableName});
  352 + List<T> resultList = _jdbcTemplateBroadcast.query(sql.toString(), this._customJdbcTemplateRowMapper, new String[] {this._tableName}, page_list.toArray());
  353 + return UtilsSql.createPage(page, pageSize, Integer.valueOf(totalRowsMap.get("rowCount").toString()), resultList);
  354 + }
  355 +
  356 + @Override
  357 + public void addEntity(T entity) {
  358 + StringBuffer sqlInsertPart = new StringBuffer("INSERT INTO "+this.getTableSql()+"(");
  359 + StringBuffer sqlColumnPart = new StringBuffer(") VALUES (");
  360 + List<Object> paramList = new ArrayList<Object>();
  361 +
  362 + Iterator<String> beanFieldIter = this._beanToTableField.keySet().iterator();
  363 + while(beanFieldIter.hasNext()){
  364 + String beanFieldName = beanFieldIter.next();
  365 + String tableFieldName = this._beanToTableField.get(beanFieldName);
  366 + Field beanField;
  367 + Object beanFieldValue = null;
  368 + try {
  369 + beanField = this._tClassInfo.getDeclaredField(beanFieldName);
  370 + beanField.setAccessible(true);
  371 + beanFieldValue = beanField.get(entity);
  372 + } catch (Exception e) {
  373 + e.printStackTrace();
  374 + }
  375 +
  376 + if(tableFieldName == null || beanFieldName == null || beanFieldValue == null){
  377 + continue;
  378 + }
  379 + sqlInsertPart.append("`"+tableFieldName+"`,");
  380 + sqlColumnPart.append(" ?,");
  381 + paramList.add(beanFieldValue);
  382 + }
  383 +
  384 + //执行SQL
  385 + String exeSql = sqlInsertPart.substring(0, sqlInsertPart.length()-1)+sqlColumnPart.substring(0, sqlColumnPart.length()-1)+")";
  386 + _jdbcTemplateBroadcast.update(exeSql, new String[] {this._tableName}, paramList.toArray());
  387 + }
  388 +
  389 + @Override
  390 + public void addEntityList(List<T> entityList) {
  391 + if(entityList == null || entityList.isEmpty()) {
  392 + return;
  393 + }
  394 + //构造SQL语句及Entity Field列表
  395 + List<Field> beanFieldList = new ArrayList<Field>(this._beanToTableField.size());
  396 + StringBuffer exeSql = new StringBuffer(this.constructUpdateSql(entityList.get(0), beanFieldList));
  397 +
  398 + //构造参数信息
  399 + List<Object> args = new ArrayList<Object>();
  400 + exeSql.append(" VALUES");
  401 + for(int itemIndex=0; itemIndex<entityList.size(); ++itemIndex) {
  402 + T item = entityList.get(itemIndex);
  403 + exeSql.append("(");
  404 + for(int i=0; i<beanFieldList.size(); ++i) {
  405 + Field itemField = beanFieldList.get(i);
  406 + Object itemData = null;
  407 + try {
  408 + itemData = itemField.get(item);
  409 + } catch (Exception e) {
  410 + throw new ObjectReflectException();
  411 + }
  412 + if(itemData == null) {
  413 + args.add(this.getDefaultValueByFieldType(itemField));
  414 + }else {
  415 + args.add(itemData);
  416 + }
  417 + exeSql.append("?,");
  418 + }
  419 + exeSql.setCharAt(exeSql.length()-1, ' ');
  420 + exeSql.append("),");
  421 + }
  422 + exeSql.setCharAt(exeSql.length()-1, ';');
  423 +
  424 + //执行SQL
  425 + this._jdbcTemplateBroadcast.update(exeSql.toString(), new String[] {this._tableName}, args.toArray());
  426 + }
  427 +
  428 + @Override
  429 + public int deleteEntityByID(ID id) {
  430 + StringBuffer sql = new StringBuffer("DELETE FROM "+this.getTableSql()+" WHERE");
  431 + sql.append(" "+this._idTableFieldName+" = ? ");
  432 + return _jdbcTemplateBroadcast.update(sql.toString(), new String[] {this._tableName}, id);
  433 + }
  434 +
  435 + @Override
  436 + public int deleteEntityByCondition(List<Object[]> condition){
  437 + if (null == condition || condition.size() == 0) {
  438 + throw new RuntimeException("params[condition] is empty");
  439 + }
  440 +
  441 + List<Object> list = new ArrayList<Object>();
  442 + StringBuffer sql = new StringBuffer("DELETE FROM "+this.getTableSql()+"");
  443 + StringBuffer pql = new StringBuffer(sql.toString());
  444 + this.appendWhereCondition(sql, pql, list, condition);
  445 + return _jdbcTemplateBroadcast.update( sql.toString(), new String[] {this._tableName}, list.toArray());
  446 + }
  447 +
  448 + @Override
  449 + public int deleteEntityBySql(String sqlCondition){
  450 + if("".equals(sqlCondition.trim())) {
  451 + throw new RuntimeException("params[sqlCondition] is empty");
  452 + }
  453 + return _jdbcTemplateBroadcast.update( "DELETE FROM "+this.getTableSql()+" WHERE " + sqlCondition, new String[] {this._tableName});
  454 + }
  455 +
  456 + @Override
  457 + public int deleteEntityList(List<ID> idList){
  458 + StringBuffer idSb = new StringBuffer();
  459 + for(ID id: idList) {
  460 + idSb.append(id);
  461 + }
  462 + return this.deleteEntityBySql(this._idTableFieldName + " in ("+idSb.toString().substring(0, idSb.length()-1)+") ");
  463 + }
  464 +
  465 + @Override
  466 + public int updateEntityById(List<Object[]> changeList, ID id) {
  467 + if(null == id){
  468 + throw new RuntimeException("params[id] is null");
  469 + }
  470 + if (null == changeList || changeList.size() == 0) {
  471 + throw new RuntimeException("params[changeList] is empty");
  472 + }
  473 +
  474 + StringBuffer sql = new StringBuffer("UPDATE "+this.getTableSql()+" SET");
  475 + StringBuffer pql = new StringBuffer(sql.toString());
  476 + List<Object> list = new ArrayList<Object>();
  477 + this.appendSetSql(sql, pql, list, changeList);
  478 +
  479 + String where = " WHERE "+this._idTableFieldName+"=? ";
  480 + String updateSql = sql.substring(0, sql.length()-1)+where;
  481 + list.add(id);
  482 + return _jdbcTemplateBroadcast.update(updateSql, new String[] {this._tableName}, list.toArray());
  483 + }
  484 +
  485 + @Override
  486 + public int updateEntityByCondition(List<Object[]> updateObj, List<Object[]> condition){
  487 + if (null == updateObj || updateObj.size() == 0) {
  488 + throw new RuntimeException("params[updateObj] is empty");
  489 + }
  490 + if (null == condition || condition.size() == 0) {
  491 + throw new RuntimeException("params[condition] is empty");
  492 + }
  493 +
  494 + StringBuffer sql = new StringBuffer("UPDATE "+this.getTableSql()+" SET");
  495 + StringBuffer pql = new StringBuffer(sql.toString());
  496 + List<Object> list = new ArrayList<Object>();
  497 + this.appendSetSql(sql, pql, list, updateObj);
  498 +
  499 + StringBuffer where = new StringBuffer("");
  500 + StringBuffer pwhere = new StringBuffer("");
  501 + this.appendWhereCondition(where, pwhere, list, condition);
  502 +
  503 + String updateSql = sql.substring(0, sql.length()-1)+where.toString();
  504 + return _jdbcTemplateBroadcast.update(updateSql, new String[] {this._tableName}, list.toArray());
  505 + }
  506 +
  507 + @Override
  508 + public int updateEntityBySql(List<Object[]> updateObj, String sqlCondition){
  509 + if (null == updateObj || updateObj.size() == 0) {
  510 + throw new RuntimeException("params[updateObj] is empty");
  511 + }
  512 + if ("".equals(sqlCondition)) {
  513 + throw new RuntimeException("params[sqlCondition] is empty");
  514 + }
  515 +
  516 + StringBuffer sql = new StringBuffer("UPDATE "+this.getTableSql()+" SET");
  517 + StringBuffer pql = new StringBuffer(sql.toString());
  518 + List<Object> list = new ArrayList<Object>();
  519 + this.appendSetSql(sql, pql, list, updateObj);
  520 +
  521 + String updateSql = sql.toString().substring(0, sql.length()-1) + " WHERE "+sqlCondition;
  522 + return _jdbcTemplateBroadcast.update(updateSql, new String[] {this._tableName}, list.toArray());
  523 + }
  524 +
  525 + @Override
  526 + public Map<String, Object> getPageData(String coreSql, String orderByPartSql, Integer page, Integer pageSize){
  527 + String[] splitedSql = UtilsSql.splitCoreSql(coreSql);
  528 + return this.getPageData(splitedSql[0], splitedSql[1], orderByPartSql, page, pageSize);
  529 + }
  530 +
  531 + @Override
  532 + public Map<String, Object> getPageData(String selectSql, String fromAndWhereSql, String orderByPartSql, Integer page, Integer pageSize){
  533 + //构造查询语句
  534 + String querySql = selectSql+" "+fromAndWhereSql+" "+orderByPartSql+" "+UtilsSql.getLimitCondition(page, pageSize);
  535 +
  536 + //构造统计计数语句
  537 + String countSql = "select count(*) rowsCount from ( select 1 "+fromAndWhereSql+" ) t ";
  538 +
  539 + //执行查询
  540 + List<Map<String, Object>> queryData = new ArrayList<Map<String, Object>>();
  541 + Map<String, Object> countData = new HashMap<String, Object>();
  542 + queryData = this._jdbcTemplateBroadcast.queryForList(querySql, new String[] {this._tableName});
  543 + countData = this._jdbcTemplateBroadcast.queryForMap(countSql, new String[] {this._tableName});
  544 + return UtilsSql.createPage(page, pageSize, Integer.valueOf(countData.get("rowsCount").toString()), queryData);
  545 + }
  546 +}
... ...
src/main/java/com/taover/repository/CustomJdbcTemplateBroadcastInterface.java 0 → 100644
... ... @@ -0,0 +1,153 @@
  1 +package com.taover.repository;
  2 +
  3 +import java.io.Serializable;
  4 +import java.util.List;
  5 +import java.util.Map;
  6 +
  7 +import com.taover.repository.exception.MultiRowException;
  8 +import com.taover.repository.exception.NoContainTenantException;
  9 +import com.taover.repository.exception.NotFoundException;
  10 +
  11 +public interface CustomJdbcTemplateBroadcastInterface<T, ID extends Serializable> {
  12 +
  13 + /**
  14 + * 按主键查询
  15 + */
  16 + public T findEntityByID(ID id) throws NotFoundException;
  17 +
  18 + /**
  19 + * 按主键查询
  20 + * isLock 是否锁定, 默认不锁
  21 + * fromWriteDB 是否从写库读写,默认从读库查询
  22 + */
  23 + public T findEntityByID(ID id, boolean isLock) throws NotFoundException;
  24 +
  25 + /**
  26 + * 根据条件List<Object[]>查询
  27 + * Object[]数组长度是3
  28 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
  29 + */
  30 + public T findEntityByCondition(List<Object[]> condition) throws NotFoundException,MultiRowException,NoContainTenantException;
  31 +
  32 + /**
  33 + * 根据条件sql查询
  34 + * sqlCondition 为where 后面的条件。
  35 + */
  36 + public T findEntityBySql(String sqlCondition) throws NotFoundException,MultiRowException,NoContainTenantException;
  37 +
  38 + /**
  39 + * 根据条件List<Object[]>查询
  40 + * Object[]数组长度是3
  41 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
  42 + */
  43 + public List<T> findListByCondition(List<Object[]> condition);
  44 +
  45 + /**
  46 + * 根据条件List<Object[]>查询
  47 + * Object[]数组长度是3
  48 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
  49 + */
  50 + public List<T> findListByCondition(List<Object[]> condition, String sortCondition);
  51 +
  52 + /**
  53 + * 根据条件sql查询
  54 + * sqlCondition 为where 后面的条件。
  55 + */
  56 + public List<T> findListBySql(String sqlCondition);
  57 +
  58 + /**
  59 + * 按条件分页查询
  60 + * Object[]数组长度是3
  61 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
  62 + */
  63 + public Map<String, Object> findPageByCondition(List<Object[]> condition, int page, int pageSize);
  64 +
  65 + /**
  66 + * 按条件分页查询
  67 + * Object[]数组长度是3
  68 + * Object[]第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
  69 + * boolean isUseCache, 是否用缓存,默认用。
  70 + * boolean isAddCache, 是否添加缓存,默认添加。
  71 + */
  72 + public Map<String, Object> findPageByCondition(List<Object[]> condition, String sortCondition, int page, int pageSize);
  73 +
  74 + /**
  75 + * 按sql分页查询, sqlCondition为where 后条件sql
  76 + */
  77 + public Map<String, Object> findPageBySql(String sqlCondition, int page, int pageSize);
  78 +
  79 + /**
  80 + * 添加
  81 + */
  82 + public void addEntity(T entity);
  83 +
  84 + /**
  85 + * 批量添加
  86 + * @throws Exception
  87 + */
  88 + public void addEntityList(List<T> entityList);
  89 +
  90 + /**
  91 + * 按ID删除
  92 + */
  93 + public int deleteEntityByID(ID id);
  94 +
  95 + /**
  96 + * 删除按List<Object[]>条件
  97 + * Object[]数组长度是3
  98 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
  99 + */
  100 + public int deleteEntityByCondition(List<Object[]> condition);
  101 +
  102 + /**
  103 + * 删除按condition条件
  104 + * 建议使用deleteTByCondition(List<Object[]> condition), 如果removeTByCondition(List<Object[]> condition)满足不了where条件可以使用此方法。
  105 + * condition为where后面的条件,condition不能为空。
  106 + */
  107 + public int deleteEntityBySql(String sqlCondition);
  108 +
  109 + /**
  110 + * 根据list对象逐个删除。
  111 + * @throws NoContainTenantException
  112 + */
  113 + public int deleteEntityList(List<ID> idList);
  114 +
  115 + /**
  116 + * 根据ID修改指定的值
  117 + */
  118 + public int updateEntityById(List<Object[]> changeList, ID id);
  119 +
  120 + /**
  121 + * List<Object[]> updateObj 要修改成的值,数组长度为2,第一个值为列名,第二个值是要改成的值。
  122 + * List<Object[]> condition 修改的条件, 数组长度是3, 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
  123 + */
  124 + public int updateEntityByCondition(List<Object[]> updateObj, List<Object[]> condition);
  125 +
  126 + /**
  127 + * List<Object[]> updateObj 要修改成的值,数组长度为2,第一个值为列名,第二个值是要改成的值。
  128 + * String sqlCondition 修改的条件。
  129 + */
  130 + public int updateEntityBySql(List<Object[]> updateObj, String sqlCondition);
  131 +
  132 + /**
  133 + * 获取分页数据
  134 + * @param coreSql
  135 + * @param orderByPartSql
  136 + * @param page
  137 + * @param pageSize
  138 + * @return
  139 + */
  140 + public Map<String, Object> getPageData(String coreSql, String orderByPartSql, Integer page, Integer pageSize);
  141 +
  142 + /**
  143 + * 获取分页数据
  144 + * @param selectSql
  145 + * @param fromAndWhereSql
  146 + * @param orderByPartSql
  147 + * @param page
  148 + * @param pageSize
  149 + * @return
  150 + */
  151 + public Map<String, Object> getPageData(String selectSql, String fromAndWhereSql, String orderByPartSql, Integer page, Integer pageSize);
  152 +
  153 +}
... ...
src/main/java/com/taover/repository/autoconfigure/TaoverRepositoryAutoConfiguration.java
... ... @@ -10,7 +10,10 @@ import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
10 10 import org.springframework.boot.context.properties.EnableConfigurationProperties;
11 11 import org.springframework.context.annotation.Bean;
12 12 import org.springframework.context.annotation.Configuration;
  13 +import org.springframework.jdbc.core.JdbcTemplate;
13 14  
  15 +import com.taover.repository.jdbctemplate.JdbcTemplateBroadcast;
  16 +import com.taover.repository.jdbctemplate.JdbcTemplateBroadcastImpl;
14 17 import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenant;
15 18 import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenantImpl;
16 19 import com.taover.repository.shardingsphere.ShardingInfoRepository;
... ... @@ -23,9 +26,12 @@ import com.taover.repository.shardingsphere.ShardingSphereService;
23 26 @ConditionalOnClass({ShardingSphereService.class})
24 27 @ConditionalOnMissingBean(ShardingSphereService.class)
25 28 public class TaoverRepositoryAutoConfiguration {
26   -
  29 + @Resource
  30 + private JdbcTemplate jdbcTemplate;
27 31 @Resource
28 32 private ShardingSphereKeyGeneratorConfiguration config;
  33 + @Resource
  34 + private ShardingSphereService shardingSphereService;
29 35  
30 36 @Bean
31 37 public ShardingSphereService shardingSphereService() {
... ... @@ -39,6 +45,11 @@ public class TaoverRepositoryAutoConfiguration {
39 45  
40 46 @Bean
41 47 public JdbcTemplateWrapperTenant jdbcTemplateWrapperTenant() {
42   - return new JdbcTemplateWrapperTenantImpl();
  48 + return new JdbcTemplateWrapperTenantImpl(this.jdbcTemplate, this.shardingSphereService);
  49 + }
  50 +
  51 + @Bean
  52 + public JdbcTemplateBroadcast jdbcTemplateWrapperBroadcast() {
  53 + return new JdbcTemplateBroadcastImpl(this.jdbcTemplate, this.shardingSphereService);
43 54 }
44 55 }
... ...
src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateBroadcast.java 0 → 100644
... ... @@ -0,0 +1,976 @@
  1 +package com.taover.repository.jdbctemplate;
  2 +
  3 +import java.util.Collection;
  4 +import java.util.List;
  5 +import java.util.Map;
  6 +
  7 +import org.springframework.dao.DataAccessException;
  8 +import org.springframework.dao.IncorrectResultSizeDataAccessException;
  9 +import org.springframework.jdbc.core.BatchPreparedStatementSetter;
  10 +import org.springframework.jdbc.core.CallableStatementCallback;
  11 +import org.springframework.jdbc.core.CallableStatementCreator;
  12 +import org.springframework.jdbc.core.ColumnMapRowMapper;
  13 +import org.springframework.jdbc.core.ConnectionCallback;
  14 +import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter;
  15 +import org.springframework.jdbc.core.PreparedStatementCallback;
  16 +import org.springframework.jdbc.core.PreparedStatementCreator;
  17 +import org.springframework.jdbc.core.PreparedStatementCreatorFactory;
  18 +import org.springframework.jdbc.core.PreparedStatementSetter;
  19 +import org.springframework.jdbc.core.ResultSetExtractor;
  20 +import org.springframework.jdbc.core.RowCallbackHandler;
  21 +import org.springframework.jdbc.core.RowMapper;
  22 +import org.springframework.jdbc.core.SingleColumnRowMapper;
  23 +import org.springframework.jdbc.core.SqlParameter;
  24 +import org.springframework.jdbc.core.SqlParameterValue;
  25 +import org.springframework.jdbc.core.SqlRowSetResultSetExtractor;
  26 +import org.springframework.jdbc.core.StatementCallback;
  27 +import org.springframework.jdbc.support.KeyHolder;
  28 +import org.springframework.jdbc.support.rowset.SqlRowSet;
  29 +import org.springframework.lang.Nullable;
  30 +
  31 +public interface JdbcTemplateBroadcast {
  32 + /**
  33 + * 加载分片信息
  34 + * @param tenantId
  35 + */
  36 + public void loadShardingInfo(String[] broadcastTableNames);
  37 +
  38 + /**
  39 + * 清空分片信息
  40 + */
  41 + public void clearShardingInfo();
  42 +
  43 + //-------------------------------------------------------------------------
  44 + // Methods dealing with a plain java.sql.Connection
  45 + //-------------------------------------------------------------------------
  46 +
  47 + /**
  48 + * Execute a JDBC data access operation, implemented as callback action
  49 + * working on a JDBC Connection. This allows for implementing arbitrary
  50 + * data access operations, within Spring's managed JDBC environment:
  51 + * that is, participating in Spring-managed transactions and converting
  52 + * JDBC SQLExceptions into Spring's DataAccessException hierarchy.
  53 + * <p>The callback action can return a result object, for example a domain
  54 + * object or a collection of domain objects.
  55 + * @param action a callback object that specifies the action
  56 + * @return a result object returned by the action, or {@code null} if none
  57 + * @throws DataAccessException if there is any problem
  58 + */
  59 + @Nullable
  60 + <T> T execute(ConnectionCallback<T> action, String[] broadcastTableNames) throws DataAccessException;
  61 +
  62 +
  63 + //-------------------------------------------------------------------------
  64 + // Methods dealing with static SQL (java.sql.Statement)
  65 + //-------------------------------------------------------------------------
  66 +
  67 + /**
  68 + * Execute a JDBC data access operation, implemented as callback action
  69 + * working on a JDBC Statement. This allows for implementing arbitrary data
  70 + * access operations on a single Statement, within Spring's managed JDBC
  71 + * environment: that is, participating in Spring-managed transactions and
  72 + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy.
  73 + * <p>The callback action can return a result object, for example a domain
  74 + * object or a collection of domain objects.
  75 + * @param action a callback that specifies the action
  76 + * @return a result object returned by the action, or {@code null} if none
  77 + * @throws DataAccessException if there is any problem
  78 + */
  79 + @Nullable
  80 + <T> T execute(StatementCallback<T> action, String[] broadcastTableNames) throws DataAccessException;
  81 +
  82 + /**
  83 + * Issue a single SQL execute, typically a DDL statement.
  84 + * @param sql static SQL to execute
  85 + * @throws DataAccessException if there is any problem
  86 + */
  87 + void execute(String sql, String[] broadcastTableNames) throws DataAccessException;
  88 +
  89 + /**
  90 + * Execute a query given static SQL, reading the ResultSet with a
  91 + * ResultSetExtractor.
  92 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  93 + * execute a static query with a PreparedStatement, use the overloaded
  94 + * {@code query} method with {@code null} as argument array.
  95 + * @param sql the SQL query to execute
  96 + * @param rse a callback that will extract all rows of results
  97 + * @return an arbitrary result object, as returned by the ResultSetExtractor
  98 + * @throws DataAccessException if there is any problem executing the query
  99 + * @see #query(String, Object[], ResultSetExtractor)
  100 + */
  101 + @Nullable
  102 + <T> T query(String sql, ResultSetExtractor<T> rse, String[] broadcastTableNames) throws DataAccessException;
  103 +
  104 + /**
  105 + * Execute a query given static SQL, reading the ResultSet on a per-row
  106 + * basis with a RowCallbackHandler.
  107 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  108 + * execute a static query with a PreparedStatement, use the overloaded
  109 + * {@code query} method with {@code null} as argument array.
  110 + * @param sql the SQL query to execute
  111 + * @param rch a callback that will extract results, one row at a time
  112 + * @throws DataAccessException if there is any problem executing the query
  113 + * @see #query(String, Object[], RowCallbackHandler)
  114 + */
  115 + void query(String sql, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException;
  116 +
  117 + /**
  118 + * Execute a query given static SQL, mapping each row to a result object
  119 + * via a RowMapper.
  120 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  121 + * execute a static query with a PreparedStatement, use the overloaded
  122 + * {@code query} method with {@code null} as argument array.
  123 + * @param sql the SQL query to execute
  124 + * @param rowMapper a callback that will map one object per row
  125 + * @return the result List, containing mapped objects
  126 + * @throws DataAccessException if there is any problem executing the query
  127 + * @see #query(String, Object[], RowMapper)
  128 + */
  129 + <T> List<T> query(String sql, RowMapper<T> rowMapper, String[] broadcastTableNames) throws DataAccessException;
  130 +
  131 + /**
  132 + * Execute a query given static SQL, mapping a single result row to a
  133 + * result object via a RowMapper.
  134 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  135 + * execute a static query with a PreparedStatement, use the overloaded
  136 + * {@link #queryForObject(String, RowMapper, Object...)} method with
  137 + * {@code null} as argument array.
  138 + * @param sql the SQL query to execute
  139 + * @param rowMapper a callback that will map one object per row
  140 + * @return the single mapped object (may be {@code null} if the given
  141 + * {@link RowMapper} returned {@code} null)
  142 + * @throws IncorrectResultSizeDataAccessException if the query does not
  143 + * return exactly one row
  144 + * @throws DataAccessException if there is any problem executing the query
  145 + * @see #queryForObject(String, Object[], RowMapper)
  146 + */
  147 + @Nullable
  148 + <T> T queryForObject(String sql, RowMapper<T> rowMapper, String[] broadcastTableNames) throws DataAccessException;
  149 +
  150 + /**
  151 + * Execute a query for a result object, given static SQL.
  152 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  153 + * execute a static query with a PreparedStatement, use the overloaded
  154 + * {@link #queryForObject(String, Class, Object...)} method with
  155 + * {@code null} as argument array.
  156 + * <p>This method is useful for running static SQL with a known outcome.
  157 + * The query is expected to be a single row/single column query; the returned
  158 + * result will be directly mapped to the corresponding object type.
  159 + * @param sql the SQL query to execute
  160 + * @param requiredType the type that the result object is expected to match
  161 + * @return the result object of the required type, or {@code null} in case of SQL NULL
  162 + * @throws IncorrectResultSizeDataAccessException if the query does not return
  163 + * exactly one row, or does not return exactly one column in that row
  164 + * @throws DataAccessException if there is any problem executing the query
  165 + * @see #queryForObject(String, Object[], Class)
  166 + */
  167 + @Nullable
  168 + <T> T queryForObject(String sql, Class<T> requiredType, String[] broadcastTableNames) throws DataAccessException;
  169 +
  170 + /**
  171 + * Execute a query for a result map, given static SQL.
  172 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  173 + * execute a static query with a PreparedStatement, use the overloaded
  174 + * {@link #queryForMap(String, Object...)} method with {@code null}
  175 + * as argument array.
  176 + * <p>The query is expected to be a single row query; the result row will be
  177 + * mapped to a Map (one entry for each column, using the column name as the key).
  178 + * @param sql the SQL query to execute
  179 + * @return the result Map (one entry per column, with column name as key)
  180 + * @throws IncorrectResultSizeDataAccessException if the query does not
  181 + * return exactly one row
  182 + * @throws DataAccessException if there is any problem executing the query
  183 + * @see #queryForMap(String, Object[])
  184 + * @see ColumnMapRowMapper
  185 + */
  186 + Map<String, Object> queryForMap(String sql, String[] broadcastTableNames) throws DataAccessException;
  187 +
  188 + /**
  189 + * Execute a query for a result list, given static SQL.
  190 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  191 + * execute a static query with a PreparedStatement, use the overloaded
  192 + * {@code queryForList} method with {@code null} as argument array.
  193 + * <p>The results will be mapped to a List (one entry for each row) of
  194 + * result objects, each of them matching the specified element type.
  195 + * @param sql the SQL query to execute
  196 + * @param elementType the required type of element in the result list
  197 + * (for example, {@code Integer.class})
  198 + * @return a List of objects that match the specified element type
  199 + * @throws DataAccessException if there is any problem executing the query
  200 + * @see #queryForList(String, Object[], Class)
  201 + * @see SingleColumnRowMapper
  202 + */
  203 + <T> List<T> queryForList(String sql, Class<T> elementType, String[] broadcastTableNames) throws DataAccessException;
  204 +
  205 + /**
  206 + * Execute a query for a result list, given static SQL.
  207 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  208 + * execute a static query with a PreparedStatement, use the overloaded
  209 + * {@code queryForList} method with {@code null} as argument array.
  210 + * <p>The results will be mapped to a List (one entry for each row) of
  211 + * Maps (one entry for each column using the column name as the key).
  212 + * Each element in the list will be of the form returned by this interface's
  213 + * {@code queryForMap} methods.
  214 + * @param sql the SQL query to execute
  215 + * @return an List that contains a Map per row
  216 + * @throws DataAccessException if there is any problem executing the query
  217 + * @see #queryForList(String, Object[])
  218 + */
  219 + List<Map<String, Object>> queryForList(String sql, String[] broadcastTableNames) throws DataAccessException;
  220 +
  221 + /**
  222 + * Execute a query for a SqlRowSet, given static SQL.
  223 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  224 + * execute a static query with a PreparedStatement, use the overloaded
  225 + * {@code queryForRowSet} method with {@code null} as argument array.
  226 + * <p>The results will be mapped to an SqlRowSet which holds the data in a
  227 + * disconnected fashion. This wrapper will translate any SQLExceptions thrown.
  228 + * <p>Note that, for the default implementation, JDBC RowSet support needs to
  229 + * be available at runtime: by default, Sun's {@code com.sun.rowset.CachedRowSetImpl}
  230 + * class is used, which is part of JDK 1.5+ and also available separately as part of
  231 + * Sun's JDBC RowSet Implementations download (rowset.jar).
  232 + * @param sql the SQL query to execute
  233 + * @return a SqlRowSet representation (possibly a wrapper around a
  234 + * {@code javax.sql.rowset.CachedRowSet})
  235 + * @throws DataAccessException if there is any problem executing the query
  236 + * @see #queryForRowSet(String, Object[])
  237 + * @see SqlRowSetResultSetExtractor
  238 + * @see javax.sql.rowset.CachedRowSet
  239 + */
  240 + SqlRowSet queryForRowSet(String sql, String[] broadcastTableNames) throws DataAccessException;
  241 +
  242 + /**
  243 + * Issue a single SQL update operation (such as an insert, update or delete statement).
  244 + * @param sql static SQL to execute
  245 + * @return the number of rows affected
  246 + * @throws DataAccessException if there is any problem.
  247 + */
  248 + int update(String sql, String[] broadcastTableNames) throws DataAccessException;
  249 +
  250 + /**
  251 + * Issue multiple SQL updates on a single JDBC Statement using batching.
  252 + * <p>Will fall back to separate updates on a single Statement if the JDBC
  253 + * driver does not support batch updates.
  254 + * @param sql defining an array of SQL statements that will be executed.
  255 + * @return an array of the number of rows affected by each statement
  256 + * @throws DataAccessException if there is any problem executing the batch
  257 + */
  258 + int[] batchUpdate(String[] broadcastTableNames, String... sql) throws DataAccessException;
  259 +
  260 +
  261 + //-------------------------------------------------------------------------
  262 + // Methods dealing with prepared statements
  263 + //-------------------------------------------------------------------------
  264 +
  265 + /**
  266 + * Execute a JDBC data access operation, implemented as callback action
  267 + * working on a JDBC PreparedStatement. This allows for implementing arbitrary
  268 + * data access operations on a single Statement, within Spring's managed JDBC
  269 + * environment: that is, participating in Spring-managed transactions and
  270 + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy.
  271 + * <p>The callback action can return a result object, for example a domain
  272 + * object or a collection of domain objects.
  273 + * @param psc a callback that creates a PreparedStatement given a Connection
  274 + * @param action a callback that specifies the action
  275 + * @return a result object returned by the action, or {@code null} if none
  276 + * @throws DataAccessException if there is any problem
  277 + */
  278 + @Nullable
  279 + <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action, String[] broadcastTableNames) throws DataAccessException;
  280 +
  281 + /**
  282 + * Execute a JDBC data access operation, implemented as callback action
  283 + * working on a JDBC PreparedStatement. This allows for implementing arbitrary
  284 + * data access operations on a single Statement, within Spring's managed JDBC
  285 + * environment: that is, participating in Spring-managed transactions and
  286 + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy.
  287 + * <p>The callback action can return a result object, for example a domain
  288 + * object or a collection of domain objects.
  289 + * @param sql the SQL to execute
  290 + * @param action a callback that specifies the action
  291 + * @return a result object returned by the action, or {@code null} if none
  292 + * @throws DataAccessException if there is any problem
  293 + */
  294 + @Nullable
  295 + <T> T execute(String sql, PreparedStatementCallback<T> action, String[] broadcastTableNames) throws DataAccessException;
  296 +
  297 + /**
  298 + * Query using a prepared statement, reading the ResultSet with a ResultSetExtractor.
  299 + * <p>A PreparedStatementCreator can either be implemented directly or
  300 + * configured through a PreparedStatementCreatorFactory.
  301 + * @param psc a callback that creates a PreparedStatement given a Connection
  302 + * @param rse a callback that will extract results
  303 + * @return an arbitrary result object, as returned by the ResultSetExtractor
  304 + * @throws DataAccessException if there is any problem
  305 + * @see PreparedStatementCreatorFactory
  306 + */
  307 + @Nullable
  308 + <T> T query(PreparedStatementCreator psc, ResultSetExtractor<T> rse, String[] broadcastTableNames) throws DataAccessException;
  309 +
  310 + /**
  311 + * Query using a prepared statement, reading the ResultSet with a ResultSetExtractor.
  312 + * @param sql the SQL query to execute
  313 + * @param pss a callback that knows how to set values on the prepared statement.
  314 + * If this is {@code null}, the SQL will be assumed to contain no bind parameters.
  315 + * Even if there are no bind parameters, this callback may be used to set the
  316 + * fetch size and other performance options.
  317 + * @param rse a callback that will extract results
  318 + * @return an arbitrary result object, as returned by the ResultSetExtractor
  319 + * @throws DataAccessException if there is any problem
  320 + */
  321 + @Nullable
  322 + <T> T query(String sql, @Nullable PreparedStatementSetter pss, ResultSetExtractor<T> rse, String[] broadcastTableNames) throws DataAccessException;
  323 +
  324 + /**
  325 + * Query given SQL to create a prepared statement from SQL and a list of arguments
  326 + * to bind to the query, reading the ResultSet with a ResultSetExtractor.
  327 + * @param sql the SQL query to execute
  328 + * @param args arguments to bind to the query
  329 + * @param argTypes the SQL types of the arguments
  330 + * (constants from {@code java.sql.Types})
  331 + * @param rse a callback that will extract results
  332 + * @return an arbitrary result object, as returned by the ResultSetExtractor
  333 + * @throws DataAccessException if the query fails
  334 + * @see java.sql.Types
  335 + */
  336 + @Nullable
  337 + <T> T query(String sql, Object[] args, int[] argTypes, ResultSetExtractor<T> rse, String[] broadcastTableNames) throws DataAccessException;
  338 +
  339 + /**
  340 + * Query given SQL to create a prepared statement from SQL and a list of arguments
  341 + * to bind to the query, reading the ResultSet with a ResultSetExtractor.
  342 + * @param sql the SQL query to execute
  343 + * @param args arguments to bind to the query
  344 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  345 + * may also contain {@link SqlParameterValue} objects which indicate not
  346 + * only the argument value but also the SQL type and optionally the scale
  347 + * @param rse a callback that will extract results
  348 + * @return an arbitrary result object, as returned by the ResultSetExtractor
  349 + * @throws DataAccessException if the query fails
  350 + */
  351 + @Nullable
  352 + <T> T query(String sql, Object[] args, ResultSetExtractor<T> rse, String[] broadcastTableNames) throws DataAccessException;
  353 +
  354 + /**
  355 + * Query given SQL to create a prepared statement from SQL and a list of arguments
  356 + * to bind to the query, reading the ResultSet with a ResultSetExtractor.
  357 + * @param sql the SQL query to execute
  358 + * @param rse a callback that will extract results
  359 + * @param args arguments to bind to the query
  360 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  361 + * may also contain {@link SqlParameterValue} objects which indicate not
  362 + * only the argument value but also the SQL type and optionally the scale
  363 + * @return an arbitrary result object, as returned by the ResultSetExtractor
  364 + * @throws DataAccessException if the query fails
  365 + * @since 3.0.1
  366 + */
  367 + @Nullable
  368 + <T> T query(String sql, ResultSetExtractor<T> rse, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException;
  369 +
  370 + /**
  371 + * Query using a prepared statement, reading the ResultSet on a per-row basis
  372 + * with a RowCallbackHandler.
  373 + * <p>A PreparedStatementCreator can either be implemented directly or
  374 + * configured through a PreparedStatementCreatorFactory.
  375 + * @param psc a callback that creates a PreparedStatement given a Connection
  376 + * @param rch a callback that will extract results, one row at a time
  377 + * @throws DataAccessException if there is any problem
  378 + * @see PreparedStatementCreatorFactory
  379 + */
  380 + void query(PreparedStatementCreator psc, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException;
  381 +
  382 + /**
  383 + * Query given SQL to create a prepared statement from SQL and a
  384 + * PreparedStatementSetter implementation that knows how to bind values to the
  385 + * query, reading the ResultSet on a per-row basis with a RowCallbackHandler.
  386 + * @param sql the SQL query to execute
  387 + * @param pss a callback that knows how to set values on the prepared statement.
  388 + * If this is {@code null}, the SQL will be assumed to contain no bind parameters.
  389 + * Even if there are no bind parameters, this callback may be used to set the
  390 + * fetch size and other performance options.
  391 + * @param rch a callback that will extract results, one row at a time
  392 + * @throws DataAccessException if the query fails
  393 + */
  394 + void query(String sql, @Nullable PreparedStatementSetter pss, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException;
  395 +
  396 + /**
  397 + * Query given SQL to create a prepared statement from SQL and a list of
  398 + * arguments to bind to the query, reading the ResultSet on a per-row basis
  399 + * with a RowCallbackHandler.
  400 + * @param sql the SQL query to execute
  401 + * @param args arguments to bind to the query
  402 + * @param argTypes the SQL types of the arguments
  403 + * (constants from {@code java.sql.Types})
  404 + * @param rch a callback that will extract results, one row at a time
  405 + * @throws DataAccessException if the query fails
  406 + * @see java.sql.Types
  407 + */
  408 + void query(String sql, Object[] args, int[] argTypes, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException;
  409 +
  410 + /**
  411 + * Query given SQL to create a prepared statement from SQL and a list of
  412 + * arguments to bind to the query, reading the ResultSet on a per-row basis
  413 + * with a RowCallbackHandler.
  414 + * @param sql the SQL query to execute
  415 + * @param args arguments to bind to the query
  416 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  417 + * may also contain {@link SqlParameterValue} objects which indicate not
  418 + * only the argument value but also the SQL type and optionally the scale
  419 + * @param rch a callback that will extract results, one row at a time
  420 + * @throws DataAccessException if the query fails
  421 + */
  422 + void query(String sql, Object[] args, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException;
  423 +
  424 + /**
  425 + * Query given SQL to create a prepared statement from SQL and a list of
  426 + * arguments to bind to the query, reading the ResultSet on a per-row basis
  427 + * with a RowCallbackHandler.
  428 + * @param sql the SQL query to execute
  429 + * @param rch a callback that will extract results, one row at a time
  430 + * @param args arguments to bind to the query
  431 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  432 + * may also contain {@link SqlParameterValue} objects which indicate not
  433 + * only the argument value but also the SQL type and optionally the scale
  434 + * @throws DataAccessException if the query fails
  435 + * @since 3.0.1
  436 + */
  437 + void query(String sql, RowCallbackHandler rch, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException;
  438 +
  439 + /**
  440 + * Query using a prepared statement, mapping each row to a result object
  441 + * via a RowMapper.
  442 + * <p>A PreparedStatementCreator can either be implemented directly or
  443 + * configured through a PreparedStatementCreatorFactory.
  444 + * @param psc a callback that creates a PreparedStatement given a Connection
  445 + * @param rowMapper a callback that will map one object per row
  446 + * @return the result List, containing mapped objects
  447 + * @throws DataAccessException if there is any problem
  448 + * @see PreparedStatementCreatorFactory
  449 + */
  450 + <T> List<T> query(PreparedStatementCreator psc, RowMapper<T> rowMapper, String[] broadcastTableNames) throws DataAccessException;
  451 +
  452 + /**
  453 + * Query given SQL to create a prepared statement from SQL and a
  454 + * PreparedStatementSetter implementation that knows how to bind values
  455 + * to the query, mapping each row to a result object via a RowMapper.
  456 + * @param sql the SQL query to execute
  457 + * @param pss a callback that knows how to set values on the prepared statement.
  458 + * If this is {@code null}, the SQL will be assumed to contain no bind parameters.
  459 + * Even if there are no bind parameters, this callback may be used to set the
  460 + * fetch size and other performance options.
  461 + * @param rowMapper a callback that will map one object per row
  462 + * @return the result List, containing mapped objects
  463 + * @throws DataAccessException if the query fails
  464 + */
  465 + <T> List<T> query(String sql, @Nullable PreparedStatementSetter pss, RowMapper<T> rowMapper, String[] broadcastTableNames) throws DataAccessException;
  466 +
  467 + /**
  468 + * Query given SQL to create a prepared statement from SQL and a list of
  469 + * arguments to bind to the query, mapping each row to a result object
  470 + * via a RowMapper.
  471 + * @param sql the SQL query to execute
  472 + * @param args arguments to bind to the query
  473 + * @param argTypes the SQL types of the arguments
  474 + * (constants from {@code java.sql.Types})
  475 + * @param rowMapper a callback that will map one object per row
  476 + * @return the result List, containing mapped objects
  477 + * @throws DataAccessException if the query fails
  478 + * @see java.sql.Types
  479 + */
  480 + <T> List<T> query(String sql, Object[] args, int[] argTypes, RowMapper<T> rowMapper, String[] broadcastTableNames) throws DataAccessException;
  481 +
  482 + /**
  483 + * Query given SQL to create a prepared statement from SQL and a list of
  484 + * arguments to bind to the query, mapping each row to a result object
  485 + * via a RowMapper.
  486 + * @param sql the SQL query to execute
  487 + * @param args arguments to bind to the query
  488 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  489 + * may also contain {@link SqlParameterValue} objects which indicate not
  490 + * only the argument value but also the SQL type and optionally the scale
  491 + * @param rowMapper a callback that will map one object per row
  492 + * @return the result List, containing mapped objects
  493 + * @throws DataAccessException if the query fails
  494 + */
  495 + <T> List<T> query(String sql, Object[] args, RowMapper<T> rowMapper, String[] broadcastTableNames) throws DataAccessException;
  496 +
  497 + /**
  498 + * Query given SQL to create a prepared statement from SQL and a list of
  499 + * arguments to bind to the query, mapping each row to a result object
  500 + * via a RowMapper.
  501 + * @param sql the SQL query to execute
  502 + * @param rowMapper a callback that will map one object per row
  503 + * @param args arguments to bind to the query
  504 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  505 + * may also contain {@link SqlParameterValue} objects which indicate not
  506 + * only the argument value but also the SQL type and optionally the scale
  507 + * @return the result List, containing mapped objects
  508 + * @throws DataAccessException if the query fails
  509 + * @since 3.0.1
  510 + */
  511 + <T> List<T> query(String sql, RowMapper<T> rowMapper, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException;
  512 +
  513 + /**
  514 + * Query given SQL to create a prepared statement from SQL and a list
  515 + * of arguments to bind to the query, mapping a single result row to a
  516 + * result object via a RowMapper.
  517 + * @param sql the SQL query to execute
  518 + * @param args arguments to bind to the query
  519 + * (leaving it to the PreparedStatement to guess the corresponding SQL type)
  520 + * @param argTypes the SQL types of the arguments
  521 + * (constants from {@code java.sql.Types})
  522 + * @param rowMapper a callback that will map one object per row
  523 + * @return the single mapped object (may be {@code null} if the given
  524 + * {@link RowMapper} returned {@code} null)
  525 + * @throws IncorrectResultSizeDataAccessException if the query does not
  526 + * return exactly one row
  527 + * @throws DataAccessException if the query fails
  528 + */
  529 + @Nullable
  530 + <T> T queryForObject(String sql, Object[] args, int[] argTypes, RowMapper<T> rowMapper, String[] broadcastTableNames)
  531 + throws DataAccessException;
  532 +
  533 + /**
  534 + * Query given SQL to create a prepared statement from SQL and a list
  535 + * of arguments to bind to the query, mapping a single result row to a
  536 + * result object via a RowMapper.
  537 + * @param sql the SQL query to execute
  538 + * @param args arguments to bind to the query
  539 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  540 + * may also contain {@link SqlParameterValue} objects which indicate not
  541 + * only the argument value but also the SQL type and optionally the scale
  542 + * @param rowMapper a callback that will map one object per row
  543 + * @return the single mapped object (may be {@code null} if the given
  544 + * {@link RowMapper} returned {@code} null)
  545 + * @throws IncorrectResultSizeDataAccessException if the query does not
  546 + * return exactly one row
  547 + * @throws DataAccessException if the query fails
  548 + */
  549 + @Nullable
  550 + <T> T queryForObject(String sql, Object[] args, RowMapper<T> rowMapper, String[] broadcastTableNames) throws DataAccessException;
  551 +
  552 + /**
  553 + * Query given SQL to create a prepared statement from SQL and a list
  554 + * of arguments to bind to the query, mapping a single result row to a
  555 + * result object via a RowMapper.
  556 + * @param sql the SQL query to execute
  557 + * @param rowMapper a callback that will map one object per row
  558 + * @param args arguments to bind to the query
  559 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  560 + * may also contain {@link SqlParameterValue} objects which indicate not
  561 + * only the argument value but also the SQL type and optionally the scale
  562 + * @return the single mapped object (may be {@code null} if the given
  563 + * {@link RowMapper} returned {@code} null)
  564 + * @throws IncorrectResultSizeDataAccessException if the query does not
  565 + * return exactly one row
  566 + * @throws DataAccessException if the query fails
  567 + * @since 3.0.1
  568 + */
  569 + @Nullable
  570 + <T> T queryForObject(String sql, RowMapper<T> rowMapper, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException;
  571 +
  572 + /**
  573 + * Query given SQL to create a prepared statement from SQL and a list of
  574 + * arguments to bind to the query, expecting a result object.
  575 + * <p>The query is expected to be a single row/single column query; the returned
  576 + * result will be directly mapped to the corresponding object type.
  577 + * @param sql the SQL query to execute
  578 + * @param args arguments to bind to the query
  579 + * @param argTypes the SQL types of the arguments
  580 + * (constants from {@code java.sql.Types})
  581 + * @param requiredType the type that the result object is expected to match
  582 + * @return the result object of the required type, or {@code null} in case of SQL NULL
  583 + * @throws IncorrectResultSizeDataAccessException if the query does not return
  584 + * exactly one row, or does not return exactly one column in that row
  585 + * @throws DataAccessException if the query fails
  586 + * @see #queryForObject(String, Class)
  587 + * @see java.sql.Types
  588 + */
  589 + @Nullable
  590 + <T> T queryForObject(String sql, Object[] args, int[] argTypes, Class<T> requiredType, String[] broadcastTableNames)
  591 + throws DataAccessException;
  592 +
  593 + /**
  594 + * Query given SQL to create a prepared statement from SQL and a list of
  595 + * arguments to bind to the query, expecting a result object.
  596 + * <p>The query is expected to be a single row/single column query; the returned
  597 + * result will be directly mapped to the corresponding object type.
  598 + * @param sql the SQL query to execute
  599 + * @param args arguments to bind to the query
  600 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  601 + * may also contain {@link SqlParameterValue} objects which indicate not
  602 + * only the argument value but also the SQL type and optionally the scale
  603 + * @param requiredType the type that the result object is expected to match
  604 + * @return the result object of the required type, or {@code null} in case of SQL NULL
  605 + * @throws IncorrectResultSizeDataAccessException if the query does not return
  606 + * exactly one row, or does not return exactly one column in that row
  607 + * @throws DataAccessException if the query fails
  608 + * @see #queryForObject(String, Class)
  609 + */
  610 + @Nullable
  611 + <T> T queryForObject(String sql, Object[] args, Class<T> requiredType, String[] broadcastTableNames) throws DataAccessException;
  612 +
  613 + /**
  614 + * Query given SQL to create a prepared statement from SQL and a list of
  615 + * arguments to bind to the query, expecting a result object.
  616 + * <p>The query is expected to be a single row/single column query; the returned
  617 + * result will be directly mapped to the corresponding object type.
  618 + * @param sql the SQL query to execute
  619 + * @param requiredType the type that the result object is expected to match
  620 + * @param args arguments to bind to the query
  621 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  622 + * may also contain {@link SqlParameterValue} objects which indicate not
  623 + * only the argument value but also the SQL type and optionally the scale
  624 + * @return the result object of the required type, or {@code null} in case of SQL NULL
  625 + * @throws IncorrectResultSizeDataAccessException if the query does not return
  626 + * exactly one row, or does not return exactly one column in that row
  627 + * @throws DataAccessException if the query fails
  628 + * @since 3.0.1
  629 + * @see #queryForObject(String, Class)
  630 + */
  631 + @Nullable
  632 + <T> T queryForObject(String sql, Class<T> requiredType, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException;
  633 +
  634 + /**
  635 + * Query given SQL to create a prepared statement from SQL and a list of
  636 + * arguments to bind to the query, expecting a result map.
  637 + * <p>The query is expected to be a single row query; the result row will be
  638 + * mapped to a Map (one entry for each column, using the column name as the key).
  639 + * @param sql the SQL query to execute
  640 + * @param args arguments to bind to the query
  641 + * @param argTypes the SQL types of the arguments
  642 + * (constants from {@code java.sql.Types})
  643 + * @return the result Map (one entry per column, with column name as key)
  644 + * @throws IncorrectResultSizeDataAccessException if the query does not
  645 + * return exactly one row
  646 + * @throws DataAccessException if the query fails
  647 + * @see #queryForMap(String)
  648 + * @see ColumnMapRowMapper
  649 + * @see java.sql.Types
  650 + */
  651 + Map<String, Object> queryForMap(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames) throws DataAccessException;
  652 +
  653 + /**
  654 + * Query given SQL to create a prepared statement from SQL and a list of
  655 + * arguments to bind to the query, expecting a result map.
  656 + * <p>The {@code queryForMap} methods defined by this interface are appropriate
  657 + * when you don't have a domain model. Otherwise, consider using one of the
  658 + * {@code queryForObject} methods.
  659 + * <p>The query is expected to be a single row query; the result row will be
  660 + * mapped to a Map (one entry for each column, using the column name as the key).
  661 + * @param sql the SQL query to execute
  662 + * @param args arguments to bind to the query
  663 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  664 + * may also contain {@link SqlParameterValue} objects which indicate not
  665 + * only the argument value but also the SQL type and optionally the scale
  666 + * @return the result Map (one entry for each column, using the
  667 + * column name as the key)
  668 + * @throws IncorrectResultSizeDataAccessException if the query does not
  669 + * return exactly one row
  670 + * @throws DataAccessException if the query fails
  671 + * @see #queryForMap(String)
  672 + * @see ColumnMapRowMapper
  673 + */
  674 + Map<String, Object> queryForMap(String sql, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException;
  675 +
  676 + /**
  677 + * Query given SQL to create a prepared statement from SQL and a list of
  678 + * arguments to bind to the query, expecting a result list.
  679 + * <p>The results will be mapped to a List (one entry for each row) of
  680 + * result objects, each of them matching the specified element type.
  681 + * @param sql the SQL query to execute
  682 + * @param args arguments to bind to the query
  683 + * @param argTypes the SQL types of the arguments
  684 + * (constants from {@code java.sql.Types})
  685 + * @param elementType the required type of element in the result list
  686 + * (for example, {@code Integer.class})
  687 + * @return a List of objects that match the specified element type
  688 + * @throws DataAccessException if the query fails
  689 + * @see #queryForList(String, Class)
  690 + * @see SingleColumnRowMapper
  691 + */
  692 + <T> List<T> queryForList(String sql, Object[] args, int[] argTypes, Class<T> elementType, String[] broadcastTableNames)
  693 + throws DataAccessException;
  694 +
  695 + /**
  696 + * Query given SQL to create a prepared statement from SQL and a list of
  697 + * arguments to bind to the query, expecting a result list.
  698 + * <p>The results will be mapped to a List (one entry for each row) of
  699 + * result objects, each of them matching the specified element type.
  700 + * @param sql the SQL query to execute
  701 + * @param args arguments to bind to the query
  702 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  703 + * may also contain {@link SqlParameterValue} objects which indicate not
  704 + * only the argument value but also the SQL type and optionally the scale
  705 + * @param elementType the required type of element in the result list
  706 + * (for example, {@code Integer.class})
  707 + * @return a List of objects that match the specified element type
  708 + * @throws DataAccessException if the query fails
  709 + * @see #queryForList(String, Class)
  710 + * @see SingleColumnRowMapper
  711 + */
  712 + <T> List<T> queryForList(String sql, Object[] args, Class<T> elementType, String[] broadcastTableNames) throws DataAccessException;
  713 +
  714 + /**
  715 + * Query given SQL to create a prepared statement from SQL and a list of
  716 + * arguments to bind to the query, expecting a result list.
  717 + * <p>The results will be mapped to a List (one entry for each row) of
  718 + * result objects, each of them matching the specified element type.
  719 + * @param sql the SQL query to execute
  720 + * @param elementType the required type of element in the result list
  721 + * (for example, {@code Integer.class})
  722 + * @param args arguments to bind to the query
  723 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  724 + * may also contain {@link SqlParameterValue} objects which indicate not
  725 + * only the argument value but also the SQL type and optionally the scale
  726 + * @return a List of objects that match the specified element type
  727 + * @throws DataAccessException if the query fails
  728 + * @since 3.0.1
  729 + * @see #queryForList(String, Class)
  730 + * @see SingleColumnRowMapper
  731 + */
  732 + <T> List<T> queryForList(String sql, Class<T> elementType, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException;
  733 +
  734 + /**
  735 + * Query given SQL to create a prepared statement from SQL and a list of
  736 + * arguments to bind to the query, expecting a result list.
  737 + * <p>The results will be mapped to a List (one entry for each row) of
  738 + * Maps (one entry for each column, using the column name as the key).
  739 + * Each element in the list will be of the form returned by this interface's
  740 + * {@code queryForMap} methods.
  741 + * @param sql the SQL query to execute
  742 + * @param args arguments to bind to the query
  743 + * @param argTypes the SQL types of the arguments
  744 + * (constants from {@code java.sql.Types})
  745 + * @return a List that contains a Map per row
  746 + * @throws DataAccessException if the query fails
  747 + * @see #queryForList(String)
  748 + * @see java.sql.Types
  749 + */
  750 + List<Map<String, Object>> queryForList(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames) throws DataAccessException;
  751 +
  752 + /**
  753 + * Query given SQL to create a prepared statement from SQL and a list of
  754 + * arguments to bind to the query, expecting a result list.
  755 + * <p>The results will be mapped to a List (one entry for each row) of
  756 + * Maps (one entry for each column, using the column name as the key).
  757 + * Each element in the list will be of the form returned by this interface's
  758 + * {@code queryForMap} methods.
  759 + * @param sql the SQL query to execute
  760 + * @param args arguments to bind to the query
  761 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  762 + * may also contain {@link SqlParameterValue} objects which indicate not
  763 + * only the argument value but also the SQL type and optionally the scale
  764 + * @return a List that contains a Map per row
  765 + * @throws DataAccessException if the query fails
  766 + * @see #queryForList(String)
  767 + */
  768 + List<Map<String, Object>> queryForList(String sql, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException;
  769 +
  770 + /**
  771 + * Query given SQL to create a prepared statement from SQL and a list of
  772 + * arguments to bind to the query, expecting a SqlRowSet.
  773 + * <p>The results will be mapped to an SqlRowSet which holds the data in a
  774 + * disconnected fashion. This wrapper will translate any SQLExceptions thrown.
  775 + * <p>Note that, for the default implementation, JDBC RowSet support needs to
  776 + * be available at runtime: by default, Sun's {@code com.sun.rowset.CachedRowSetImpl}
  777 + * class is used, which is part of JDK 1.5+ and also available separately as part of
  778 + * Sun's JDBC RowSet Implementations download (rowset.jar).
  779 + * @param sql the SQL query to execute
  780 + * @param args arguments to bind to the query
  781 + * @param argTypes the SQL types of the arguments
  782 + * (constants from {@code java.sql.Types})
  783 + * @return a SqlRowSet representation (possibly a wrapper around a
  784 + * {@code javax.sql.rowset.CachedRowSet})
  785 + * @throws DataAccessException if there is any problem executing the query
  786 + * @see #queryForRowSet(String)
  787 + * @see SqlRowSetResultSetExtractor
  788 + * @see javax.sql.rowset.CachedRowSet
  789 + * @see java.sql.Types
  790 + */
  791 + SqlRowSet queryForRowSet(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames) throws DataAccessException;
  792 +
  793 + /**
  794 + * Query given SQL to create a prepared statement from SQL and a list of
  795 + * arguments to bind to the query, expecting a SqlRowSet.
  796 + * <p>The results will be mapped to an SqlRowSet which holds the data in a
  797 + * disconnected fashion. This wrapper will translate any SQLExceptions thrown.
  798 + * <p>Note that, for the default implementation, JDBC RowSet support needs to
  799 + * be available at runtime: by default, Sun's {@code com.sun.rowset.CachedRowSetImpl}
  800 + * class is used, which is part of JDK 1.5+ and also available separately as part of
  801 + * Sun's JDBC RowSet Implementations download (rowset.jar).
  802 + * @param sql the SQL query to execute
  803 + * @param args arguments to bind to the query
  804 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  805 + * may also contain {@link SqlParameterValue} objects which indicate not
  806 + * only the argument value but also the SQL type and optionally the scale
  807 + * @return a SqlRowSet representation (possibly a wrapper around a
  808 + * {@code javax.sql.rowset.CachedRowSet})
  809 + * @throws DataAccessException if there is any problem executing the query
  810 + * @see #queryForRowSet(String)
  811 + * @see SqlRowSetResultSetExtractor
  812 + * @see javax.sql.rowset.CachedRowSet
  813 + */
  814 + SqlRowSet queryForRowSet(String sql, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException;
  815 +
  816 + /**
  817 + * Issue a single SQL update operation (such as an insert, update or delete
  818 + * statement) using a PreparedStatementCreator to provide SQL and any
  819 + * required parameters.
  820 + * <p>A PreparedStatementCreator can either be implemented directly or
  821 + * configured through a PreparedStatementCreatorFactory.
  822 + * @param psc a callback that provides SQL and any necessary parameters
  823 + * @return the number of rows affected
  824 + * @throws DataAccessException if there is any problem issuing the update
  825 + * @see PreparedStatementCreatorFactory
  826 + */
  827 + int update(PreparedStatementCreator psc, String[] broadcastTableNames) throws DataAccessException;
  828 +
  829 + /**
  830 + * Issue an update statement using a PreparedStatementCreator to provide SQL and
  831 + * any required parameters. Generated keys will be put into the given KeyHolder.
  832 + * <p>Note that the given PreparedStatementCreator has to create a statement
  833 + * with activated extraction of generated keys (a JDBC 3.0 feature). This can
  834 + * either be done directly or through using a PreparedStatementCreatorFactory.
  835 + * @param psc a callback that provides SQL and any necessary parameters
  836 + * @param generatedKeyHolder a KeyHolder that will hold the generated keys
  837 + * @return the number of rows affected
  838 + * @throws DataAccessException if there is any problem issuing the update
  839 + * @see PreparedStatementCreatorFactory
  840 + * @see org.springframework.jdbc.support.GeneratedKeyHolder
  841 + */
  842 + int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder, String[] broadcastTableNames) throws DataAccessException;
  843 +
  844 + /**
  845 + * Issue an update statement using a PreparedStatementSetter to set bind parameters,
  846 + * with given SQL. Simpler than using a PreparedStatementCreator as this method
  847 + * will create the PreparedStatement: The PreparedStatementSetter just needs to
  848 + * set parameters.
  849 + * @param sql the SQL containing bind parameters
  850 + * @param pss helper that sets bind parameters. If this is {@code null}
  851 + * we run an update with static SQL.
  852 + * @return the number of rows affected
  853 + * @throws DataAccessException if there is any problem issuing the update
  854 + */
  855 + int update(String sql, @Nullable PreparedStatementSetter pss, String[] broadcastTableNames) throws DataAccessException;
  856 +
  857 + /**
  858 + * Issue a single SQL update operation (such as an insert, update or delete statement)
  859 + * via a prepared statement, binding the given arguments.
  860 + * @param sql the SQL containing bind parameters
  861 + * @param args arguments to bind to the query
  862 + * @param argTypes the SQL types of the arguments
  863 + * (constants from {@code java.sql.Types})
  864 + * @return the number of rows affected
  865 + * @throws DataAccessException if there is any problem issuing the update
  866 + * @see java.sql.Types
  867 + */
  868 + int update(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames) throws DataAccessException;
  869 +
  870 + /**
  871 + * Issue a single SQL update operation (such as an insert, update or delete statement)
  872 + * via a prepared statement, binding the given arguments.
  873 + * @param sql the SQL containing bind parameters
  874 + * @param args arguments to bind to the query
  875 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  876 + * may also contain {@link SqlParameterValue} objects which indicate not
  877 + * only the argument value but also the SQL type and optionally the scale
  878 + * @return the number of rows affected
  879 + * @throws DataAccessException if there is any problem issuing the update
  880 + */
  881 + int update(String sql, String[] broadcastTableNames, @Nullable Object... args) throws DataAccessException;
  882 +
  883 + /**
  884 + * Issue multiple update statements on a single PreparedStatement,
  885 + * using batch updates and a BatchPreparedStatementSetter to set values.
  886 + * <p>Will fall back to separate updates on a single PreparedStatement
  887 + * if the JDBC driver does not support batch updates.
  888 + * @param sql defining PreparedStatement that will be reused.
  889 + * All statements in the batch will use the same SQL.
  890 + * @param pss object to set parameters on the PreparedStatement
  891 + * created by this method
  892 + * @return an array of the number of rows affected by each statement
  893 + * @throws DataAccessException if there is any problem issuing the update
  894 + */
  895 + int[] batchUpdate(String sql, BatchPreparedStatementSetter pss, String[] broadcastTableNames) throws DataAccessException;
  896 +
  897 + /**
  898 + * Execute a batch using the supplied SQL statement with the batch of supplied arguments.
  899 + * @param sql the SQL statement to execute
  900 + * @param batchArgs the List of Object arrays containing the batch of arguments for the query
  901 + * @return an array containing the numbers of rows affected by each update in the batch
  902 + */
  903 + int[] batchUpdate(String sql, List<Object[]> batchArgs, String[] broadcastTableNames) throws DataAccessException;
  904 +
  905 + /**
  906 + * Execute a batch using the supplied SQL statement with the batch of supplied arguments.
  907 + * @param sql the SQL statement to execute.
  908 + * @param batchArgs the List of Object arrays containing the batch of arguments for the query
  909 + * @param argTypes the SQL types of the arguments
  910 + * (constants from {@code java.sql.Types})
  911 + * @return an array containing the numbers of rows affected by each update in the batch
  912 + */
  913 + int[] batchUpdate(String sql, List<Object[]> batchArgs, int[] argTypes, String[] broadcastTableNames) throws DataAccessException;
  914 +
  915 + /**
  916 + * Execute multiple batches using the supplied SQL statement with the collect of supplied arguments.
  917 + * The arguments' values will be set using the ParameterizedPreparedStatementSetter.
  918 + * Each batch should be of size indicated in 'batchSize'.
  919 + * @param sql the SQL statement to execute.
  920 + * @param batchArgs the List of Object arrays containing the batch of arguments for the query
  921 + * @param batchSize batch size
  922 + * @param pss the ParameterizedPreparedStatementSetter to use
  923 + * @return an array containing for each batch another array containing the numbers of rows affected
  924 + * by each update in the batch
  925 + * @since 3.1
  926 + */
  927 + <T> int[][] batchUpdate(String sql, Collection<T> batchArgs, int batchSize,
  928 + ParameterizedPreparedStatementSetter<T> pss, String[] broadcastTableNames) throws DataAccessException;
  929 +
  930 +
  931 + //-------------------------------------------------------------------------
  932 + // Methods dealing with callable statements
  933 + //-------------------------------------------------------------------------
  934 +
  935 + /**
  936 + * Execute a JDBC data access operation, implemented as callback action
  937 + * working on a JDBC CallableStatement. This allows for implementing arbitrary
  938 + * data access operations on a single Statement, within Spring's managed JDBC
  939 + * environment: that is, participating in Spring-managed transactions and
  940 + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy.
  941 + * <p>The callback action can return a result object, for example a domain
  942 + * object or a collection of domain objects.
  943 + * @param csc a callback that creates a CallableStatement given a Connection
  944 + * @param action a callback that specifies the action
  945 + * @return a result object returned by the action, or {@code null} if none
  946 + * @throws DataAccessException if there is any problem
  947 + */
  948 + @Nullable
  949 + <T> T execute(CallableStatementCreator csc, CallableStatementCallback<T> action, String[] broadcastTableNames) throws DataAccessException;
  950 +
  951 + /**
  952 + * Execute a JDBC data access operation, implemented as callback action
  953 + * working on a JDBC CallableStatement. This allows for implementing arbitrary
  954 + * data access operations on a single Statement, within Spring's managed JDBC
  955 + * environment: that is, participating in Spring-managed transactions and
  956 + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy.
  957 + * <p>The callback action can return a result object, for example a domain
  958 + * object or a collection of domain objects.
  959 + * @param callString the SQL call string to execute
  960 + * @param action a callback that specifies the action
  961 + * @return a result object returned by the action, or {@code null} if none
  962 + * @throws DataAccessException if there is any problem
  963 + */
  964 + @Nullable
  965 + <T> T execute(String callString, CallableStatementCallback<T> action, String[] broadcastTableNames) throws DataAccessException;
  966 +
  967 + /**
  968 + * Execute a SQL call using a CallableStatementCreator to provide SQL and
  969 + * any required parameters.
  970 + * @param csc a callback that provides SQL and any necessary parameters
  971 + * @param declaredParameters list of declared SqlParameter objects
  972 + * @return a Map of extracted out parameters
  973 + * @throws DataAccessException if there is any problem issuing the update
  974 + */
  975 + Map<String, Object> call(CallableStatementCreator csc, List<SqlParameter> declaredParameters, String[] broadcastTableNames) throws DataAccessException;
  976 +}
... ...
src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateBroadcastImpl.java 0 → 100644
... ... @@ -0,0 +1,667 @@
  1 +package com.taover.repository.jdbctemplate;
  2 +
  3 +import java.util.Collection;
  4 +import java.util.List;
  5 +import java.util.Map;
  6 +
  7 +import org.apache.shardingsphere.api.hint.HintManager;
  8 +import org.springframework.dao.DataAccessException;
  9 +import org.springframework.jdbc.core.BatchPreparedStatementSetter;
  10 +import org.springframework.jdbc.core.CallableStatementCallback;
  11 +import org.springframework.jdbc.core.CallableStatementCreator;
  12 +import org.springframework.jdbc.core.ConnectionCallback;
  13 +import org.springframework.jdbc.core.JdbcTemplate;
  14 +import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter;
  15 +import org.springframework.jdbc.core.PreparedStatementCallback;
  16 +import org.springframework.jdbc.core.PreparedStatementCreator;
  17 +import org.springframework.jdbc.core.PreparedStatementSetter;
  18 +import org.springframework.jdbc.core.ResultSetExtractor;
  19 +import org.springframework.jdbc.core.RowCallbackHandler;
  20 +import org.springframework.jdbc.core.RowMapper;
  21 +import org.springframework.jdbc.core.SqlParameter;
  22 +import org.springframework.jdbc.core.StatementCallback;
  23 +import org.springframework.jdbc.support.KeyHolder;
  24 +import org.springframework.jdbc.support.rowset.SqlRowSet;
  25 +
  26 +import com.taover.repository.shardingsphere.ShardingInfoEntity;
  27 +import com.taover.repository.shardingsphere.ShardingSphereService;
  28 +
  29 +public class JdbcTemplateBroadcastImpl implements JdbcTemplateBroadcast {
  30 + private JdbcTemplate jdbcTemplate;
  31 + private ShardingSphereService shardingSphereService;
  32 +
  33 + public JdbcTemplateBroadcastImpl(JdbcTemplate jdbcTemplate, ShardingSphereService shardingSphereService) {
  34 + this.jdbcTemplate = jdbcTemplate;
  35 + this.shardingSphereService = shardingSphereService;
  36 + }
  37 +
  38 + @Override
  39 + public void loadShardingInfo(String[] broadcastTableNames) {
  40 + List<ShardingInfoEntity> shardingInfo = this.shardingSphereService.getShardingInfoByTableNames(broadcastTableNames);
  41 + if(shardingInfo == null || shardingInfo.isEmpty()) {
  42 + return;
  43 + }
  44 + HintManager.clear();
  45 + HintManager instance = HintManager.getInstance();
  46 + for(ShardingInfoEntity item: shardingInfo) {
  47 + instance.addTableShardingValue(item.getTableName(), item.getTableSuffix());
  48 + instance.addDatabaseShardingValue(item.getTableName(), item.getDsName());
  49 + }
  50 + }
  51 +
  52 + @Override
  53 + public void clearShardingInfo() {
  54 + HintManager.clear();
  55 + }
  56 +
  57 + @Override
  58 + public <E> E execute(ConnectionCallback<E> action, String[] broadcastTableNames) throws DataAccessException {
  59 + try {
  60 + this.loadShardingInfo(broadcastTableNames);
  61 + return this.jdbcTemplate.execute(action);
  62 + }finally {
  63 + this.clearShardingInfo();
  64 + }
  65 + }
  66 +
  67 + @Override
  68 + public <E> E execute(StatementCallback<E> action, String[] broadcastTableNames) throws DataAccessException {
  69 + try {
  70 + this.loadShardingInfo(broadcastTableNames);
  71 + return this.jdbcTemplate.execute(action);
  72 + }finally {
  73 + this.clearShardingInfo();
  74 + }
  75 + }
  76 +
  77 + @Override
  78 + public void execute(String sql, String[] broadcastTableNames) throws DataAccessException {
  79 + try {
  80 + this.loadShardingInfo(broadcastTableNames);
  81 + this.jdbcTemplate.execute(sql);
  82 + }finally {
  83 + this.clearShardingInfo();
  84 + }
  85 + }
  86 +
  87 + @Override
  88 + public <E> E query(String sql, ResultSetExtractor<E> rse, String[] broadcastTableNames) throws DataAccessException {
  89 + try {
  90 + this.loadShardingInfo(broadcastTableNames);
  91 + return this.jdbcTemplate.query(sql, rse);
  92 + }finally {
  93 + this.clearShardingInfo();
  94 + }
  95 + }
  96 +
  97 + @Override
  98 + public void query(String sql, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException {
  99 + try {
  100 + this.loadShardingInfo(broadcastTableNames);
  101 + this.jdbcTemplate.query(sql, rch);
  102 + }finally {
  103 + this.clearShardingInfo();
  104 + }
  105 + }
  106 +
  107 + @Override
  108 + public <E> List<E> query(String sql, RowMapper<E> rowMapper, String[] broadcastTableNames) throws DataAccessException {
  109 + try {
  110 + this.loadShardingInfo(broadcastTableNames);
  111 + return this.jdbcTemplate.query(sql, rowMapper);
  112 + }finally {
  113 + this.clearShardingInfo();
  114 + }
  115 + }
  116 +
  117 + @Override
  118 + public <E> E queryForObject(String sql, RowMapper<E> rowMapper, String[] broadcastTableNames) throws DataAccessException {
  119 + try {
  120 + this.loadShardingInfo(broadcastTableNames);
  121 + return this.jdbcTemplate.queryForObject(sql, rowMapper);
  122 + }finally {
  123 + this.clearShardingInfo();
  124 + }
  125 + }
  126 +
  127 + @Override
  128 + public <E> E queryForObject(String sql, Class<E> requiredType, String[] broadcastTableNames) throws DataAccessException {
  129 + try {
  130 + this.loadShardingInfo(broadcastTableNames);
  131 + return this.jdbcTemplate.queryForObject(sql, requiredType);
  132 + }finally {
  133 + this.clearShardingInfo();
  134 + }
  135 + }
  136 +
  137 + @Override
  138 + public Map<String, Object> queryForMap(String sql, String[] broadcastTableNames) throws DataAccessException {
  139 + try {
  140 + this.loadShardingInfo(broadcastTableNames);
  141 + return this.jdbcTemplate.queryForMap(sql);
  142 + }finally {
  143 + this.clearShardingInfo();
  144 + }
  145 + }
  146 +
  147 + @Override
  148 + public <E> List<E> queryForList(String sql, Class<E> elementType, String[] broadcastTableNames) throws DataAccessException {
  149 + try {
  150 + this.loadShardingInfo(broadcastTableNames);
  151 + return this.jdbcTemplate.queryForList(sql, elementType);
  152 + }finally {
  153 + this.clearShardingInfo();
  154 + }
  155 + }
  156 +
  157 + @Override
  158 + public List<Map<String, Object>> queryForList(String sql, String[] broadcastTableNames) throws DataAccessException {
  159 + try {
  160 + this.loadShardingInfo(broadcastTableNames);
  161 + return this.jdbcTemplate.queryForList(sql);
  162 + }finally {
  163 + this.clearShardingInfo();
  164 + }
  165 + }
  166 +
  167 + @Override
  168 + public SqlRowSet queryForRowSet(String sql, String[] broadcastTableNames) throws DataAccessException {
  169 + try {
  170 + this.loadShardingInfo(broadcastTableNames);
  171 + return this.jdbcTemplate.queryForRowSet(sql);
  172 + }finally {
  173 + this.clearShardingInfo();
  174 + }
  175 + }
  176 +
  177 + @Override
  178 + public int update(String sql, String[] broadcastTableNames) throws DataAccessException {
  179 + try {
  180 + this.loadShardingInfo(broadcastTableNames);
  181 + return this.jdbcTemplate.update(sql);
  182 + }finally {
  183 + this.clearShardingInfo();
  184 + }
  185 + }
  186 +
  187 + @Override
  188 + public int[] batchUpdate(String[] broadcastTableNames, String... sql) throws DataAccessException {
  189 + try {
  190 + this.loadShardingInfo(broadcastTableNames);
  191 + return this.jdbcTemplate.batchUpdate(sql);
  192 + }finally {
  193 + this.clearShardingInfo();
  194 + }
  195 + }
  196 +
  197 + @Override
  198 + public <E> E execute(PreparedStatementCreator psc, PreparedStatementCallback<E> action, String[] broadcastTableNames)
  199 + throws DataAccessException {
  200 + try {
  201 + this.loadShardingInfo(broadcastTableNames);
  202 + return this.jdbcTemplate.execute(psc, action);
  203 + }finally {
  204 + this.clearShardingInfo();
  205 + }
  206 + }
  207 +
  208 + @Override
  209 + public <E> E execute(String sql, PreparedStatementCallback<E> action, String[] broadcastTableNames) throws DataAccessException {
  210 + try {
  211 + this.loadShardingInfo(broadcastTableNames);
  212 + return this.jdbcTemplate.execute(sql, action);
  213 + }finally {
  214 + this.clearShardingInfo();
  215 + }
  216 + }
  217 +
  218 + @Override
  219 + public <E> E query(PreparedStatementCreator psc, ResultSetExtractor<E> rse, String[] broadcastTableNames)
  220 + throws DataAccessException {
  221 + try {
  222 + this.loadShardingInfo(broadcastTableNames);
  223 + return this.jdbcTemplate.query(psc, rse);
  224 + }finally {
  225 + this.clearShardingInfo();
  226 + }
  227 + }
  228 +
  229 + @Override
  230 + public <E> E query(String sql, PreparedStatementSetter pss, ResultSetExtractor<E> rse, String[] broadcastTableNames)
  231 + throws DataAccessException {
  232 + try {
  233 + this.loadShardingInfo(broadcastTableNames);
  234 + return this.jdbcTemplate.query(sql, pss, rse);
  235 + }finally {
  236 + this.clearShardingInfo();
  237 + }
  238 + }
  239 +
  240 + @Override
  241 + public <E> E query(String sql, Object[] args, int[] argTypes, ResultSetExtractor<E> rse, String[] broadcastTableNames)
  242 + throws DataAccessException {
  243 + try {
  244 + this.loadShardingInfo(broadcastTableNames);
  245 + return this.jdbcTemplate.query(sql, args, argTypes, rse);
  246 + }finally {
  247 + this.clearShardingInfo();
  248 + }
  249 + }
  250 +
  251 + @Override
  252 + public <E> E query(String sql, Object[] args, ResultSetExtractor<E> rse, String[] broadcastTableNames) throws DataAccessException {
  253 + try {
  254 + this.loadShardingInfo(broadcastTableNames);
  255 + return this.jdbcTemplate.query(sql, args, rse);
  256 + }finally {
  257 + this.clearShardingInfo();
  258 + }
  259 + }
  260 +
  261 + @Override
  262 + public <E> E query(String sql, ResultSetExtractor<E> rse, String[] broadcastTableNames, Object... args)
  263 + throws DataAccessException {
  264 + try {
  265 + this.loadShardingInfo(broadcastTableNames);
  266 + return this.jdbcTemplate.query(sql, rse, args);
  267 + }finally {
  268 + this.clearShardingInfo();
  269 + }
  270 + }
  271 +
  272 + @Override
  273 + public void query(PreparedStatementCreator psc, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException {
  274 + try {
  275 + this.loadShardingInfo(broadcastTableNames);
  276 + this.jdbcTemplate.query(psc, rch);
  277 + }finally {
  278 + this.clearShardingInfo();
  279 + }
  280 + }
  281 +
  282 + @Override
  283 + public void query(String sql, PreparedStatementSetter pss, RowCallbackHandler rch, String[] broadcastTableNames)
  284 + throws DataAccessException {
  285 + try {
  286 + this.loadShardingInfo(broadcastTableNames);
  287 + this.jdbcTemplate.query(sql, pss, rch);
  288 + }finally {
  289 + this.clearShardingInfo();
  290 + }
  291 + }
  292 +
  293 + @Override
  294 + public void query(String sql, Object[] args, int[] argTypes, RowCallbackHandler rch, String[] broadcastTableNames)
  295 + throws DataAccessException {
  296 + try {
  297 + this.loadShardingInfo(broadcastTableNames);
  298 + this.jdbcTemplate.query(sql, args, argTypes, rch);
  299 + }finally {
  300 + this.clearShardingInfo();
  301 + }
  302 + }
  303 +
  304 + @Override
  305 + public void query(String sql, Object[] args, RowCallbackHandler rch, String[] broadcastTableNames) throws DataAccessException {
  306 + try {
  307 + this.loadShardingInfo(broadcastTableNames);
  308 + this.jdbcTemplate.query(sql, args, rch);
  309 + }finally {
  310 + this.clearShardingInfo();
  311 + }
  312 + }
  313 +
  314 + @Override
  315 + public void query(String sql, RowCallbackHandler rch, String[] broadcastTableNames, Object... args) throws DataAccessException {
  316 + try {
  317 + this.loadShardingInfo(broadcastTableNames);
  318 + this.jdbcTemplate.query(sql, rch, args);
  319 + }finally {
  320 + this.clearShardingInfo();
  321 + }
  322 + }
  323 +
  324 + @Override
  325 + public <E> List<E> query(PreparedStatementCreator psc, RowMapper<E> rowMapper, String[] broadcastTableNames)
  326 + throws DataAccessException {
  327 + try {
  328 + this.loadShardingInfo(broadcastTableNames);
  329 + return this.jdbcTemplate.query(psc, rowMapper);
  330 + }finally {
  331 + this.clearShardingInfo();
  332 + }
  333 + }
  334 +
  335 + @Override
  336 + public <E> List<E> query(String sql, PreparedStatementSetter pss, RowMapper<E> rowMapper, String[] broadcastTableNames)
  337 + throws DataAccessException {
  338 + try {
  339 + this.loadShardingInfo(broadcastTableNames);
  340 + return this.jdbcTemplate.query(sql, pss, rowMapper);
  341 + }finally {
  342 + this.clearShardingInfo();
  343 + }
  344 + }
  345 +
  346 + @Override
  347 + public <E> List<E> query(String sql, Object[] args, int[] argTypes, RowMapper<E> rowMapper, String[] broadcastTableNames)
  348 + throws DataAccessException {
  349 + try {
  350 + this.loadShardingInfo(broadcastTableNames);
  351 + return this.jdbcTemplate.query(sql, args, argTypes, rowMapper);
  352 + }finally {
  353 + this.clearShardingInfo();
  354 + }
  355 + }
  356 +
  357 + @Override
  358 + public <E> List<E> query(String sql, Object[] args, RowMapper<E> rowMapper, String[] broadcastTableNames)
  359 + throws DataAccessException {
  360 + try {
  361 + this.loadShardingInfo(broadcastTableNames);
  362 + return this.jdbcTemplate.query(sql, args, rowMapper);
  363 + }finally {
  364 + this.clearShardingInfo();
  365 + }
  366 + }
  367 +
  368 + @Override
  369 + public <E> List<E> query(String sql, RowMapper<E> rowMapper, String[] broadcastTableNames, Object... args)
  370 + throws DataAccessException {
  371 + try {
  372 + this.loadShardingInfo(broadcastTableNames);
  373 + return this.jdbcTemplate.query(sql, rowMapper, args);
  374 + }finally {
  375 + this.clearShardingInfo();
  376 + }
  377 + }
  378 +
  379 + @Override
  380 + public <E> E queryForObject(String sql, Object[] args, int[] argTypes, RowMapper<E> rowMapper, String[] broadcastTableNames)
  381 + throws DataAccessException {
  382 + try {
  383 + this.loadShardingInfo(broadcastTableNames);
  384 + return this.jdbcTemplate.queryForObject(sql, args, argTypes, rowMapper);
  385 + }finally {
  386 + this.clearShardingInfo();
  387 + }
  388 + }
  389 +
  390 + @Override
  391 + public <E> E queryForObject(String sql, Object[] args, RowMapper<E> rowMapper, String[] broadcastTableNames)
  392 + throws DataAccessException {
  393 + try {
  394 + this.loadShardingInfo(broadcastTableNames);
  395 + return this.jdbcTemplate.queryForObject(sql, args, rowMapper);
  396 + }finally {
  397 + this.clearShardingInfo();
  398 + }
  399 + }
  400 +
  401 + @Override
  402 + public <E> E queryForObject(String sql, RowMapper<E> rowMapper, String[] broadcastTableNames, Object... args)
  403 + throws DataAccessException {
  404 + try {
  405 + this.loadShardingInfo(broadcastTableNames);
  406 + return this.jdbcTemplate.queryForObject(sql, rowMapper, args);
  407 + }finally {
  408 + this.clearShardingInfo();
  409 + }
  410 + }
  411 +
  412 + @Override
  413 + public <E> E queryForObject(String sql, Object[] args, int[] argTypes, Class<E> requiredType, String[] broadcastTableNames)
  414 + throws DataAccessException {
  415 + try {
  416 + this.loadShardingInfo(broadcastTableNames);
  417 + return this.jdbcTemplate.queryForObject(sql, args, argTypes, requiredType);
  418 + }finally {
  419 + this.clearShardingInfo();
  420 + }
  421 + }
  422 +
  423 + @Override
  424 + public <E> E queryForObject(String sql, Object[] args, Class<E> requiredType, String[] broadcastTableNames)
  425 + throws DataAccessException {
  426 + try {
  427 + this.loadShardingInfo(broadcastTableNames);
  428 + return this.jdbcTemplate.queryForObject(sql, args, requiredType);
  429 + }finally {
  430 + this.clearShardingInfo();
  431 + }
  432 + }
  433 +
  434 + @Override
  435 + public <E> E queryForObject(String sql, Class<E> requiredType, String[] broadcastTableNames, Object... args)
  436 + throws DataAccessException {
  437 + try {
  438 + this.loadShardingInfo(broadcastTableNames);
  439 + return this.jdbcTemplate.queryForObject(sql, requiredType, args);
  440 + }finally {
  441 + this.clearShardingInfo();
  442 + }
  443 + }
  444 +
  445 + @Override
  446 + public Map<String, Object> queryForMap(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames)
  447 + throws DataAccessException {
  448 + try {
  449 + this.loadShardingInfo(broadcastTableNames);
  450 + return this.jdbcTemplate.queryForMap(sql, args, argTypes);
  451 + }finally {
  452 + this.clearShardingInfo();
  453 + }
  454 + }
  455 +
  456 + @Override
  457 + public Map<String, Object> queryForMap(String sql, String[] broadcastTableNames, Object... args) throws DataAccessException {
  458 + try {
  459 + this.loadShardingInfo(broadcastTableNames);
  460 + return this.jdbcTemplate.queryForMap(sql, args);
  461 + }finally {
  462 + this.clearShardingInfo();
  463 + }
  464 + }
  465 +
  466 + @Override
  467 + public <E> List<E> queryForList(String sql, Object[] args, int[] argTypes, Class<E> elementType, String[] broadcastTableNames)
  468 + throws DataAccessException {
  469 + try {
  470 + this.loadShardingInfo(broadcastTableNames);
  471 + return this.jdbcTemplate.queryForList(sql, args, argTypes, elementType);
  472 + }finally {
  473 + this.clearShardingInfo();
  474 + }
  475 + }
  476 +
  477 + @Override
  478 + public <E> List<E> queryForList(String sql, Object[] args, Class<E> elementType, String[] broadcastTableNames)
  479 + throws DataAccessException {
  480 + try {
  481 + this.loadShardingInfo(broadcastTableNames);
  482 + return this.jdbcTemplate.queryForList(sql, args, elementType);
  483 + }finally {
  484 + this.clearShardingInfo();
  485 + }
  486 + }
  487 +
  488 + @Override
  489 + public <E> List<E> queryForList(String sql, Class<E> elementType, String[] broadcastTableNames, Object... args)
  490 + throws DataAccessException {
  491 + try {
  492 + this.loadShardingInfo(broadcastTableNames);
  493 + return this.jdbcTemplate.queryForList(sql, elementType, args);
  494 + }finally {
  495 + this.clearShardingInfo();
  496 + }
  497 + }
  498 +
  499 + @Override
  500 + public List<Map<String, Object>> queryForList(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames)
  501 + throws DataAccessException {
  502 + try {
  503 + this.loadShardingInfo(broadcastTableNames);
  504 + return this.jdbcTemplate.queryForList(sql, args, argTypes);
  505 + }finally {
  506 + this.clearShardingInfo();
  507 + }
  508 + }
  509 +
  510 + @Override
  511 + public List<Map<String, Object>> queryForList(String sql, String[] broadcastTableNames, Object... args)
  512 + throws DataAccessException {
  513 + try {
  514 + this.loadShardingInfo(broadcastTableNames);
  515 + return this.jdbcTemplate.queryForList(sql, args);
  516 + }finally {
  517 + this.clearShardingInfo();
  518 + }
  519 + }
  520 +
  521 + @Override
  522 + public SqlRowSet queryForRowSet(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames)
  523 + throws DataAccessException {
  524 + try {
  525 + this.loadShardingInfo(broadcastTableNames);
  526 + return this.jdbcTemplate.queryForRowSet(sql, args, argTypes);
  527 + }finally {
  528 + this.clearShardingInfo();
  529 + }
  530 + }
  531 +
  532 + @Override
  533 + public SqlRowSet queryForRowSet(String sql, String[] broadcastTableNames, Object... args) throws DataAccessException {
  534 + try {
  535 + this.loadShardingInfo(broadcastTableNames);
  536 + return this.jdbcTemplate.queryForRowSet(sql, args);
  537 + }finally {
  538 + this.clearShardingInfo();
  539 + }
  540 + }
  541 +
  542 + @Override
  543 + public int update(PreparedStatementCreator psc, String[] broadcastTableNames) throws DataAccessException {
  544 + try {
  545 + this.loadShardingInfo(broadcastTableNames);
  546 + return this.jdbcTemplate.update(psc);
  547 + }finally {
  548 + this.clearShardingInfo();
  549 + }
  550 + }
  551 +
  552 + @Override
  553 + public int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder, String[] broadcastTableNames)
  554 + throws DataAccessException {
  555 + try {
  556 + this.loadShardingInfo(broadcastTableNames);
  557 + return this.jdbcTemplate.update(psc, generatedKeyHolder);
  558 + }finally {
  559 + this.clearShardingInfo();
  560 + }
  561 + }
  562 +
  563 + @Override
  564 + public int update(String sql, PreparedStatementSetter pss, String[] broadcastTableNames) throws DataAccessException {
  565 + try {
  566 + this.loadShardingInfo(broadcastTableNames);
  567 + return this.jdbcTemplate.update(sql, pss);
  568 + }finally {
  569 + this.clearShardingInfo();
  570 + }
  571 + }
  572 +
  573 + @Override
  574 + public int update(String sql, Object[] args, int[] argTypes, String[] broadcastTableNames) throws DataAccessException {
  575 + try {
  576 + this.loadShardingInfo(broadcastTableNames);
  577 + return this.jdbcTemplate.update(sql, args, argTypes);
  578 + }finally {
  579 + this.clearShardingInfo();
  580 + }
  581 + }
  582 +
  583 + @Override
  584 + public int update(String sql, String[] broadcastTableNames, Object... args) throws DataAccessException {
  585 + try {
  586 + this.loadShardingInfo(broadcastTableNames);
  587 + return this.jdbcTemplate.update(sql, args);
  588 + }finally {
  589 + this.clearShardingInfo();
  590 + }
  591 + }
  592 +
  593 + @Override
  594 + public int[] batchUpdate(String sql, BatchPreparedStatementSetter pss, String[] broadcastTableNames) throws DataAccessException {
  595 + try {
  596 + this.loadShardingInfo(broadcastTableNames);
  597 + return this.jdbcTemplate.batchUpdate(sql, pss);
  598 + }finally {
  599 + this.clearShardingInfo();
  600 + }
  601 + }
  602 +
  603 + @Override
  604 + public int[] batchUpdate(String sql, List<Object[]> batchArgs, String[] broadcastTableNames) throws DataAccessException {
  605 + try {
  606 + this.loadShardingInfo(broadcastTableNames);
  607 + return this.jdbcTemplate.batchUpdate(sql, batchArgs);
  608 + }finally {
  609 + this.clearShardingInfo();
  610 + }
  611 + }
  612 +
  613 + @Override
  614 + public int[] batchUpdate(String sql, List<Object[]> batchArgs, int[] argTypes, String[] broadcastTableNames)
  615 + throws DataAccessException {
  616 + try {
  617 + this.loadShardingInfo(broadcastTableNames);
  618 + return this.jdbcTemplate.batchUpdate(sql, batchArgs);
  619 + }finally {
  620 + this.clearShardingInfo();
  621 + }
  622 + }
  623 +
  624 + @Override
  625 + public <E> int[][] batchUpdate(String sql, Collection<E> batchArgs, int batchSize,
  626 + ParameterizedPreparedStatementSetter<E> pss, String[] broadcastTableNames) throws DataAccessException {
  627 + try {
  628 + this.loadShardingInfo(broadcastTableNames);
  629 + return this.jdbcTemplate.batchUpdate(sql, batchArgs, batchSize, pss);
  630 + }finally {
  631 + this.clearShardingInfo();
  632 + }
  633 + }
  634 +
  635 + @Override
  636 + public <E> E execute(CallableStatementCreator csc, CallableStatementCallback<E> action, String[] broadcastTableNames)
  637 + throws DataAccessException {
  638 + try {
  639 + this.loadShardingInfo(broadcastTableNames);
  640 + return this.jdbcTemplate.execute(csc, action);
  641 + }finally {
  642 + this.clearShardingInfo();
  643 + }
  644 + }
  645 +
  646 + @Override
  647 + public <E> E execute(String callString, CallableStatementCallback<E> action, String[] broadcastTableNames)
  648 + throws DataAccessException {
  649 + try {
  650 + this.loadShardingInfo(broadcastTableNames);
  651 + return this.jdbcTemplate.execute(callString, action);
  652 + }finally {
  653 + this.clearShardingInfo();
  654 + }
  655 + }
  656 +
  657 + @Override
  658 + public Map<String, Object> call(CallableStatementCreator csc, List<SqlParameter> declaredParameters, String[] broadcastTableNames)
  659 + throws DataAccessException {
  660 + try {
  661 + this.loadShardingInfo(broadcastTableNames);
  662 + return this.jdbcTemplate.call(csc, declaredParameters);
  663 + }finally {
  664 + this.clearShardingInfo();
  665 + }
  666 + }
  667 +}
... ...
src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateWrapperTenant.java
... ... @@ -29,7 +29,17 @@ import org.springframework.jdbc.support.rowset.SqlRowSet;
29 29 import org.springframework.lang.Nullable;
30 30  
31 31 public interface JdbcTemplateWrapperTenant {
32   -
  32 + /**
  33 + * 加载分片信息
  34 + * @param tenantId
  35 + */
  36 + public void loadShardingInfo(Long tenantId);
  37 +
  38 + /**
  39 + * 清空分片信息
  40 + */
  41 + public void clearShardingInfo();
  42 +
33 43 //-------------------------------------------------------------------------
34 44 // Methods dealing with a plain java.sql.Connection
35 45 //-------------------------------------------------------------------------
... ...
src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateWrapperTenantImpl.java
... ... @@ -4,8 +4,6 @@ import java.util.Collection;
4 4 import java.util.List;
5 5 import java.util.Map;
6 6  
7   -import javax.annotation.Resource;
8   -
9 7 import org.apache.shardingsphere.api.hint.HintManager;
10 8 import org.springframework.dao.DataAccessException;
11 9 import org.springframework.jdbc.core.BatchPreparedStatementSetter;
... ... @@ -29,13 +27,17 @@ import com.taover.repository.shardingsphere.ShardingInfoEntity;
29 27 import com.taover.repository.shardingsphere.ShardingSphereService;
30 28  
31 29 public class JdbcTemplateWrapperTenantImpl implements JdbcTemplateWrapperTenant {
32   - @Resource
33 30 private JdbcTemplate jdbcTemplate;
34   - @Resource
35 31 private ShardingSphereService shardingSphereService;
36 32  
37   - private void loadShardingInfo(Long tenantId) {
38   - List<ShardingInfoEntity> shardingInfo = this.shardingSphereService.getShardingInfoMapByTenantId(tenantId);
  33 + public JdbcTemplateWrapperTenantImpl(JdbcTemplate jdbcTemplate, ShardingSphereService shardingSphereService) {
  34 + this.jdbcTemplate = jdbcTemplate;
  35 + this.shardingSphereService = shardingSphereService;
  36 + }
  37 +
  38 + @Override
  39 + public void loadShardingInfo(Long tenantId) {
  40 + List<ShardingInfoEntity> shardingInfo = this.shardingSphereService.getShardingInfoByTenantId(tenantId);
39 41 if(shardingInfo == null || shardingInfo.isEmpty()) {
40 42 return;
41 43 }
... ... @@ -47,7 +49,8 @@ public class JdbcTemplateWrapperTenantImpl implements JdbcTemplateWrapperTenant
47 49 }
48 50 }
49 51  
50   - private void clearShardingInfo() {
  52 + @Override
  53 + public void clearShardingInfo() {
51 54 HintManager.clear();
52 55 }
53 56  
... ...
src/main/java/com/taover/repository/shardingsphere/ShardingSphereService.java
... ... @@ -14,6 +14,7 @@ import com.taover.repository.autoconfigure.ShardingSphereKeyGeneratorConfigurati
14 14 @Service
15 15 public class ShardingSphereService {
16 16 private Map<Long, List<ShardingInfoEntity>> CACHED_TABLE_SUFFIX_BY_TENANT = null;
  17 + private Map<String, List<ShardingInfoEntity>> CACHED_TABLE_SUFFIX_BY_TABLE_NAME = null;
17 18 private Map<String, ShardingKeyGeneratorExt> GENERATOR_HOLDER = new HashMap<String, ShardingKeyGeneratorExt>();
18 19  
19 20 @Resource
... ... @@ -31,25 +32,31 @@ public class ShardingSphereService {
31 32 return GENERATOR_HOLDER.get(tableName).generateKeyList(number);
32 33 }
33 34  
34   - public List<ShardingInfoEntity> getShardingInfoMapByTenantId(Long tenantId) {
  35 + public List<ShardingInfoEntity> getShardingInfoByTenantId(Long tenantId) {
35 36 if(CACHED_TABLE_SUFFIX_BY_TENANT == null) {
36   - loadCacheTableShardingInfoByTenantId();
  37 + loadCacheTableShardingInfo();
37 38 }
38 39 return CACHED_TABLE_SUFFIX_BY_TENANT.get(tenantId);
39 40 }
40 41  
41   - private synchronized void loadCacheTableShardingInfoByTenantId() {
42   - if(CACHED_TABLE_SUFFIX_BY_TENANT != null) {
  42 + private synchronized void loadCacheTableShardingInfo() {
  43 + if(CACHED_TABLE_SUFFIX_BY_TENANT != null && CACHED_TABLE_SUFFIX_BY_TABLE_NAME != null) {
43 44 return;
44   - }
  45 + }
45 46 List<ShardingInfoEntity> dataList = this.shardingInfoRepository.findListBySql("1=1");
46 47 Map<Long, List<ShardingInfoEntity>> tempData = new HashMap<Long, List<ShardingInfoEntity>>();
  48 + Map<String, List<ShardingInfoEntity>> tempDataTableName = new HashMap<String, List<ShardingInfoEntity>>();
47 49 for(ShardingInfoEntity item: dataList) {
48 50 List<ShardingInfoEntity> tempItem = tempData.getOrDefault(item.getTenantId(), new ArrayList<ShardingInfoEntity>());
49 51 tempItem.add(item);
50 52 tempData.put(item.getTenantId(), tempItem);
  53 +
  54 + List<ShardingInfoEntity> tempItemTableName = tempDataTableName.getOrDefault(item.getTableName(), new ArrayList<ShardingInfoEntity>());
  55 + tempItemTableName.add(item);
  56 + tempDataTableName.put(item.getTableName(), tempItemTableName);
51 57 }
52 58 CACHED_TABLE_SUFFIX_BY_TENANT = tempData;
  59 + CACHED_TABLE_SUFFIX_BY_TABLE_NAME = tempDataTableName;
53 60 }
54 61  
55 62 private synchronized void loadShardingKeyGenerator(String tableName) {
... ... @@ -60,4 +67,21 @@ public class ShardingSphereService {
60 67 generator.loalConfig(config);
61 68 GENERATOR_HOLDER.put(tableName, generator);
62 69 }
  70 +
  71 + public List<ShardingInfoEntity> getShardingInfoByTableNames(String[] broadcastTableNames) {
  72 + if(broadcastTableNames == null || broadcastTableNames.length == 0) {
  73 + return null;
  74 + }
  75 + if(CACHED_TABLE_SUFFIX_BY_TABLE_NAME == null) {
  76 + loadCacheTableShardingInfo();
  77 + }
  78 + List<ShardingInfoEntity> dataList = new ArrayList<ShardingInfoEntity>();
  79 + for(String item: broadcastTableNames) {
  80 + List<ShardingInfoEntity> tempData = CACHED_TABLE_SUFFIX_BY_TABLE_NAME.get(item);
  81 + if(tempData != null && !tempData.isEmpty()) {
  82 + dataList.addAll(tempData);
  83 + }
  84 + }
  85 + return dataList;
  86 + }
63 87 }
... ...
src/test/java/com/taover/repository/test/TestAutoconfigure.java
... ... @@ -5,6 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
5 5 import org.springframework.context.ConfigurableApplicationContext;
6 6 import org.springframework.scheduling.annotation.EnableScheduling;
7 7  
  8 +import com.taover.repository.jdbctemplate.JdbcTemplateBroadcast;
8 9 import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenant;
9 10  
10 11 @SpringBootApplication
... ... @@ -12,10 +13,14 @@ import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenant;
12 13 public class TestAutoconfigure {
13 14 public static void main(String args[]) {
14 15 ConfigurableApplicationContext context = SpringApplication.run(TestAutoconfigure.class, args);
15   - JdbcTemplateWrapperTenant jdbcTemplate = context.getBean(JdbcTemplateWrapperTenant.class);
16   - System.out.println(jdbcTemplate.queryForObject("select id from wxorder_order limit 1", Long.class, 1L));
17   - System.out.println(jdbcTemplate.queryForList("select * from wxorder_order limit 1", 1L));
18   - System.out.println(jdbcTemplate.queryForList("select * from wxorder_order limit 1", 2L));
19   - System.out.println(jdbcTemplate.queryForList("select * from wxorder_order_express limit 1", 1L));
  16 +
  17 + JdbcTemplateBroadcast jdbcTemplateB = context.getBean(JdbcTemplateBroadcast.class);
  18 + System.out.println(jdbcTemplateB.queryForObject("select id from wxorder_order order by id desc limit 5 ", String.class, new String[]{"wxorder_order"}));
  19 +
  20 +// JdbcTemplateWrapperTenant jdbcTemplate = context.getBean(JdbcTemplateWrapperTenant.class);
  21 +// System.out.println(jdbcTemplate.queryForObject("select id from wxorder_order limit 1", Long.class, 1L));
  22 +// System.out.println(jdbcTemplate.queryForList("select * from wxorder_order limit 1", 1L));
  23 +// System.out.println(jdbcTemplate.queryForList("select * from wxorder_order limit 1", 2L));
  24 +// System.out.println(jdbcTemplate.queryForList("select * from wxorder_order_express limit 1", 1L));
20 25 }
21 26 }
... ...
src/test/resources/application.properties
... ... @@ -13,12 +13,9 @@ spring.gson.serialize-nulls=true
13 13 spring.mvc.dispatch-options-request=true
14 14  
15 15 # shardingspere
16   -spring.shardingsphere.datasource.names=ds0
  16 +spring.shardingsphere.datasource.names=ds0,ds1
17 17 spring.shardingsphere.datasource.ds0.type=com.alibaba.druid.pool.DruidDataSource
18 18 spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
19   -#spring.shardingsphere.datasource.ds_0.url=jdbc:mysql://121.42.142.102:3306/bzyun_wxorder?characterEncoding=UTF-8&zeroDateTimeBehavior=CONVERT_TO_NULL
20   -#spring.shardingsphere.datasource.ds_0.username=dev
21   -#spring.shardingsphere.datasource.ds_0.password=taover02
22 19 spring.shardingsphere.datasource.ds0.url=jdbc:mysql://rdsifmezqifmezqo.mysql.rds.aliyuncs.com:3306/bzyun_wxorder?characterEncoding=UTF-8
23 20 spring.shardingsphere.datasource.ds0.username=tylife
24 21 spring.shardingsphere.datasource.ds0.password=lexi365
... ... @@ -27,7 +24,17 @@ spring.shardingsphere.datasource.ds0.max-active=20
27 24 spring.shardingsphere.datasource.ds0.min-idle=5
28 25 spring.shardingsphere.datasource.ds0.max-wait=60000
29 26  
30   -spring.shardingsphere.sharding.tables.wxorder_order.actual-data-nodes=ds0.wxorder_order
  27 +spring.shardingsphere.datasource.ds1.type=com.alibaba.druid.pool.DruidDataSource
  28 +spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
  29 +spring.shardingsphere.datasource.ds1.url=jdbc:mysql://121.42.142.102:3306/bzyun_wxorder?characterEncoding=UTF-8
  30 +spring.shardingsphere.datasource.ds1.username=dev
  31 +spring.shardingsphere.datasource.ds1.password=taover02
  32 +spring.shardingsphere.datasource.ds1.initial-size=10
  33 +spring.shardingsphere.datasource.ds1.max-active=20
  34 +spring.shardingsphere.datasource.ds1.min-idle=5
  35 +spring.shardingsphere.datasource.ds1.max-wait=60000
  36 +
  37 +spring.shardingsphere.sharding.tables.wxorder_order.actual-data-nodes=ds0.wxorder_order,ds1.wxorder_order
31 38 spring.shardingsphere.sharding.tables.wxorder_order.database-strategy.hint.algorithm-class-name=com.taover.repository.shardingsphere.ShardingDatabaseAlgorithmHint
32 39 spring.shardingsphere.sharding.tables.wxorder_order.table-strategy.hint.algorithm-class-name=com.taover.repository.shardingsphere.ShardingTableAlgorithmHint
33 40 spring.shardingsphere.sharding.tables.wxorder_order.key-generator.column=id
... ...