Commit f0611848f6313a6020b3d6b02ef2929585c1d6fa

Authored by 王彬
1 parent 7a32a07a

extend to sharding sphere

Showing 30 changed files with 2924 additions and 718 deletions   Show diff stats
build.gradle
... ... @@ -5,7 +5,6 @@
5 5 * For more details take a look at the Java Libraries chapter in the Gradle
6 6 * user guide available at https://docs.gradle.org/4.5.1/userguide/java_library_plugin.html
7 7 */
8   -
9 8 plugins {
10 9 // Apply the java-library plugin to add support for Java Library
11 10 id 'java'
... ... @@ -19,10 +18,12 @@ group = 'com.taover.repository'
19 18 mainClassName = 'com.taover.repository.UtilsString'
20 19  
21 20 dependencies {
  21 + compile("org.springframework.boot:spring-boot-starter:2.0.5.RELEASE")
22 22 compile("org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final")
23 23 compile('org.springframework:spring-jdbc:5.1.9.RELEASE')
24 24 compile('mysql:mysql-connector-java:5.1.47')
25 25 compile('com.alibaba:druid:1.2.4')
  26 + compile("org.apache.shardingsphere:sharding-jdbc-spring-boot-starter:4.1.1")
26 27 }
27 28  
28 29 repositories {
... ... @@ -56,7 +57,7 @@ uploadArchives {
56 57 authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD)
57 58 }
58 59 pom.project {
59   - version '2.1.38'
  60 + version '2.1.44'
60 61 artifactId ARTIFACT_Id
61 62 groupId GROUP_ID
62 63 packaging TYPE
... ...
gradle.properties
... ... @@ -12,7 +12,7 @@ NEXUS_PASSWORD=Nexus@dev
12 12 # groupid
13 13 GROUP_ID=com.taover
14 14  
15   -ARTIFACT_Id=com-taover-repository
  15 +ARTIFACT_Id=com-taover-repository-starter
16 16  
17 17 # type
18 18 TYPE=jar
... ...
src/main/java/com/taover/repository/CustomJdbcTemplate.java
... ... @@ -18,6 +18,8 @@ import javax.persistence.Table;
18 18  
19 19 import org.springframework.jdbc.core.JdbcTemplate;
20 20  
  21 +import com.taover.repository.util.UtilsSql;
  22 +
21 23 /**
22 24 *
23 25 * @author root
... ...
src/main/java/com/taover/repository/CustomJdbcTemplateWrapperTenant.java
... ... @@ -16,12 +16,13 @@ import javax.persistence.Id;
16 16 import javax.persistence.Table;
17 17  
18 18 import org.springframework.dao.DataAccessException;
19   -import org.springframework.jdbc.core.JdbcTemplate;
20 19  
21 20 import com.taover.repository.exception.MultiRowException;
22 21 import com.taover.repository.exception.NoContainTenantException;
23 22 import com.taover.repository.exception.NotFoundException;
24 23 import com.taover.repository.exception.ObjectReflectException;
  24 +import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenant;
  25 +import com.taover.repository.util.UtilsSql;
25 26  
26 27 /**
27 28 *
... ... @@ -30,52 +31,47 @@ import com.taover.repository.exception.ObjectReflectException;
30 31 * @param <T>
31 32 * @param <ID>
32 33 */
33   -public class CustomJdbcTemplateWrapperTenant<T, ID extends Serializable> implements JdbcRepositoryWrapperTenant<T, ID>{
  34 +public class CustomJdbcTemplateWrapperTenant<T, ID extends Serializable> implements CustomJdbcTemplateWrapperTenantInterface<T, ID>{
34 35 @Resource
35   - private JdbcTemplate jdbcTemplateWrite;
  36 + private JdbcTemplateWrapperTenant _jdbcTemplateWrapperTenant;
36 37  
37   - private Map<String, String> beanToTableField;
38   - private Map<String, String> tableToBeanField;
39   - private String tableFieldNameListGapWithComma;
40   - private String idTableFieldName;
41   - private String idBeanFieldName;
42   - private String dbName;
43   - private String tableName;
44   - private Class<T> tClassInfo;
45   - private CustomJdbcTemplateRowMapper customJdbcTemplateRowMapper;
  38 + private Map<String, String> _beanToTableField;
  39 + private Map<String, String> _tableToBeanField;
  40 + private String _tableFieldNameListGapWithComma;
  41 + private String _idTableFieldName;
  42 + private String _dbName;
  43 + private String _tableName;
  44 + private Class<T> _tClassInfo;
  45 + private CustomJdbcTemplateRowMapper<T> _customJdbcTemplateRowMapper;
46 46  
47   - public CustomJdbcTemplateRowMapper getCustomJdbcTemplateRowMapper(){
48   - return this.customJdbcTemplateRowMapper;
49   - }
50   -
51   - public CustomJdbcTemplateWrapperTenant(JdbcTemplate jdbcTemplateWrite) throws Exception{
52   - this();
53   - this.jdbcTemplateWrite = jdbcTemplateWrite;
54   - }
  47 + public CustomJdbcTemplateRowMapper<T> getCustomJdbcTemplateRowMapper(){
  48 + return this._customJdbcTemplateRowMapper;
  49 + }
55 50  
  51 + @SuppressWarnings("unchecked")
56 52 public CustomJdbcTemplateWrapperTenant() throws Exception{
57 53 //获取泛型类Class
58   - this.tClassInfo = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
  54 + this._tClassInfo = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
59 55  
60 56 //检查实体声明
61   - Table annoTable = (Table) tClassInfo.getAnnotation(Table.class);
  57 + Table annoTable = (Table) _tClassInfo.getAnnotation(Table.class);
62 58 if(annoTable == null){
63   - throw new Exception("DAO层初始化失败,失败原因:"+tClassInfo.getName()+"实体类,没有@Table注解指定表名");
  59 + throw new Exception("DAO层初始化失败,失败原因:"+_tClassInfo.getName()+"实体类,没有@Table注解指定表名");
64 60 }
65   - this.tableName = annoTable.name();
  61 + this._tableName = annoTable.name();
66 62 String schema = annoTable.schema();
67 63 String catalog = annoTable.catalog();
68 64 if(schema != null && !"".equals(schema)){
69   - this.dbName = schema;
  65 + this._dbName = schema;
70 66 }else if(catalog != null && !"".equals(catalog)){
71   - this.dbName = catalog;
  67 + this._dbName = catalog;
72 68 }
73 69  
74 70 //初始化数据
75   - beanToTableField = new HashMap<String, String>();
76   - tableToBeanField = new HashMap<String, String>();
77   - tableFieldNameListGapWithComma = "";
78   - Field[] declaredFields = tClassInfo.getDeclaredFields();
  71 + _beanToTableField = new HashMap<String, String>();
  72 + _tableToBeanField = new HashMap<String, String>();
  73 + _tableFieldNameListGapWithComma = "";
  74 + Field[] declaredFields = _tClassInfo.getDeclaredFields();
79 75 for(int i=0; i<declaredFields.length; ++i){
80 76 Field currField = declaredFields[i];
81 77 String fieldName = currField.getName();
... ... @@ -83,34 +79,33 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
83 79 Column annoColumn = (Column)currField.getAnnotation(Column.class);
84 80 if(annoId != null){
85 81 if(annoColumn == null){
86   - idTableFieldName = this.camelToUnderline(fieldName);
  82 + _idTableFieldName = this.camelToUnderline(fieldName);
87 83 }else{
88   - idTableFieldName = annoColumn.name();
  84 + _idTableFieldName = annoColumn.name();
89 85 }
90   - idBeanFieldName = fieldName;
91   - tableFieldNameListGapWithComma += idTableFieldName+",";
92   - beanToTableField.put(fieldName, idTableFieldName);
93   - tableToBeanField.put(idTableFieldName, fieldName);
  86 + _tableFieldNameListGapWithComma += _idTableFieldName+",";
  87 + _beanToTableField.put(fieldName, _idTableFieldName);
  88 + _tableToBeanField.put(_idTableFieldName, fieldName);
94 89 }else{
95 90 if(annoColumn != null){
96 91 String tableFieldName = annoColumn.name();
97   - tableFieldNameListGapWithComma += tableFieldName+",";
98   - beanToTableField.put(fieldName, tableFieldName);
99   - tableToBeanField.put(tableFieldName, fieldName);
  92 + _tableFieldNameListGapWithComma += tableFieldName+",";
  93 + _beanToTableField.put(fieldName, tableFieldName);
  94 + _tableToBeanField.put(tableFieldName, fieldName);
100 95 }
101 96 }
102 97 }
103 98  
104 99 //检验是否有属性
105   - if(beanToTableField.isEmpty()){
106   - throw new Exception("DAO层初始化失败,失败原因:"+this.tClassInfo.getName()+"实体类,没有在实体中找到属性信息");
  100 + if(_beanToTableField.isEmpty()){
  101 + throw new Exception("DAO层初始化失败,失败原因:"+this._tClassInfo.getName()+"实体类,没有在实体中找到属性信息");
107 102 }
108 103  
109 104 //去除逗号
110   - tableFieldNameListGapWithComma = tableFieldNameListGapWithComma.substring(0, tableFieldNameListGapWithComma.length()-1);
  105 + _tableFieldNameListGapWithComma = _tableFieldNameListGapWithComma.substring(0, _tableFieldNameListGapWithComma.length()-1);
111 106  
112 107 //创建rowmapper
113   - this.customJdbcTemplateRowMapper = new CustomJdbcTemplateRowMapper(this.tClassInfo, this.tableToBeanField);
  108 + this._customJdbcTemplateRowMapper = new CustomJdbcTemplateRowMapper<T>(this._tClassInfo, this._tableToBeanField);
114 109 }
115 110  
116 111 /**
... ... @@ -137,42 +132,6 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
137 132 }
138 133 return result.toString();
139 134 }
140   -
141   - /**
142   - * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
143   - * 例如:HELLO_WORLD->HelloWorld
144   - * @param name 转换前的下划线大写方式命名的字符串
145   - * @return 转换后的驼峰式命名的字符串
146   - */
147   - private String underlineToCamel(String name) {
148   - StringBuilder result = new StringBuilder();
149   - // 快速检查
150   - if (name == null || name.isEmpty()) {
151   - // 没必要转换
152   - return "";
153   - } else if (!name.contains("_")) {
154   - // 不含下划线,仅将首字母小写
155   - return name.substring(0, 1).toLowerCase() + name.substring(1);
156   - }
157   - // 用下划线将原始字符串分割
158   - String camels[] = name.split("_");
159   - for (String camel : camels) {
160   - // 跳过原始字符串中开头、结尾的下换线或双重下划线
161   - if (camel.isEmpty()) {
162   - continue;
163   - }
164   - // 处理真正的驼峰片段
165   - if (result.length() == 0) {
166   - // 第一个驼峰片段,全部字母都小写
167   - result.append(camel.toLowerCase());
168   - } else {
169   - // 其他的驼峰片段,首字母大写
170   - result.append(camel.substring(0, 1).toUpperCase());
171   - result.append(camel.substring(1).toLowerCase());
172   - }
173   - }
174   - return result.toString();
175   - }
176 135  
177 136 private void appendWhereCondition(StringBuffer sql, StringBuffer pql, List<Object> list, List<Object[]> condition) {
178 137 if (condition == null || condition.size() == 0) return;
... ... @@ -236,20 +195,20 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
236 195 }
237 196  
238 197 private String getTableSql(){
239   - return (this.dbName == null || "".equals(this.dbName.trim()))?
240   - ("`"+this.tableName+"`"):
241   - ("`"+this.dbName+"`.`"+this.tableName+"`");
  198 + return (this._dbName == null || "".equals(this._dbName.trim()))?
  199 + ("`"+this._tableName+"`"):
  200 + ("`"+this._dbName+"`.`"+this._tableName+"`");
242 201 }
243 202  
244 203 private String constructUpdateSql(T entity, List<Field> beanFieldList) {
245 204 StringBuffer sqlInsertPart = new StringBuffer("INSERT INTO "+this.getTableSql()+"(");
246   - Iterator<String> beanFieldIter = this.beanToTableField.keySet().iterator();
  205 + Iterator<String> beanFieldIter = this._beanToTableField.keySet().iterator();
247 206 while(beanFieldIter.hasNext()){
248 207 String beanFieldName = beanFieldIter.next();
249   - String tableFieldName = this.beanToTableField.get(beanFieldName);
  208 + String tableFieldName = this._beanToTableField.get(beanFieldName);
250 209 Field beanField = null;
251 210 try {
252   - beanField = this.tClassInfo.getDeclaredField(beanFieldName);
  211 + beanField = this._tClassInfo.getDeclaredField(beanFieldName);
253 212 beanField.setAccessible(true);
254 213 if(beanField.get(entity) == null) {
255 214 continue;
... ... @@ -280,7 +239,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
280 239 return 0;
281 240 }
282 241 }
283   -
  242 +
284 243 @Override
285 244 public T findEntityByID(ID id, Long tenantId) throws NotFoundException {
286 245 return findEntityByID(id, tenantId, false);
... ... @@ -288,16 +247,16 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
288 247  
289 248 @Override
290 249 public T findEntityByID(ID id, Long tenantId, boolean isLock) throws NotFoundException {
291   - StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql());
292   - sql.append(" WHERE "+idTableFieldName+" = ? and tenant_id="+tenantId);
  250 + StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql());
  251 + sql.append(" WHERE "+_idTableFieldName+" = ? and tenant_id="+tenantId);
293 252 if (isLock) {
294 253 sql.append(" FOR UPDATE");
295 254 }
296 255 try {
297   - return (T) jdbcTemplateWrite.queryForObject(sql.toString(), this.customJdbcTemplateRowMapper, id);
298   - }catch (DataAccessException e) {
299   - throw new NotFoundException();
300   - }
  256 + return (T) _jdbcTemplateWrapperTenant.queryForObject(sql.toString(), this._customJdbcTemplateRowMapper, tenantId, id);
  257 + }catch (DataAccessException e) {
  258 + throw new NotFoundException(e);
  259 + }
301 260 }
302 261  
303 262 @Override
... ... @@ -333,20 +292,20 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
333 292  
334 293 @Override
335 294 public List<T> findListByCondition(List<Object[]> condition, String sortCondition, Long tenantId){
336   - StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql());
  295 + StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql());
337 296 List<Object> list = new ArrayList<Object>();
338 297 condition.add(new Object[] {"tenant_id", "=", tenantId});
339 298 this.appendWhereCondition(sql, new StringBuffer(), list, condition);
340 299 if(sortCondition != null && !sortCondition.equals("")){
341 300 sql.append(" " + sortCondition + " ");
342 301 }
343   - return (List<T>)jdbcTemplateWrite.query(sql.toString(), this.customJdbcTemplateRowMapper, list.toArray());
  302 + return (List<T>)_jdbcTemplateWrapperTenant.query(sql.toString(), this._customJdbcTemplateRowMapper, tenantId, list.toArray());
344 303 }
345 304  
346 305 @Override
347 306 public List<T> findListBySql(String sqlCondition, Long tenantId){
348   - StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql()+" WHERE tenant_id="+tenantId + " and " + sqlCondition);
349   - return (List<T>)jdbcTemplateWrite.query(sql.toString(), this.customJdbcTemplateRowMapper);
  307 + StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql()+" WHERE tenant_id="+tenantId + " and " + sqlCondition);
  308 + return (List<T>)_jdbcTemplateWrapperTenant.query(sql.toString(), this._customJdbcTemplateRowMapper, tenantId);
350 309 }
351 310  
352 311 @Override
... ... @@ -356,7 +315,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
356 315  
357 316 @Override
358 317 public Map<String, Object> findPageByCondition(List<Object[]> condition, String sortCondition, int page, int pageSize, Long tenantId){
359   - StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql());
  318 + StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql());
360 319 StringBuffer pql = new StringBuffer(sql.toString());
361 320 StringBuffer sqlCount = new StringBuffer("SELECT COUNT(1) rowCount FROM "+this.getTableSql());
362 321 condition.add(new Object[] {"tenant_id", "=", tenantId});
... ... @@ -376,40 +335,39 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
376 335 }
377 336  
378 337 String pageSql = sql.toString() + " limit ?, ?";
379   -
380   - Map<String, Object> totalRowsMap = jdbcTemplateWrite.queryForMap(sqlCount.toString(), count_list.toArray()) ;
381   - List<T> resultList = jdbcTemplateWrite.query(pageSql.toString(), this.customJdbcTemplateRowMapper, page_list.toArray());
  338 + Map<String, Object> totalRowsMap = _jdbcTemplateWrapperTenant.queryForMap(sqlCount.toString(), tenantId, count_list.toArray()) ;
  339 + List<T> resultList = _jdbcTemplateWrapperTenant.query(pageSql.toString(), this._customJdbcTemplateRowMapper, tenantId, page_list.toArray());
382 340 return UtilsSql.createPage(page, pageSize, Integer.valueOf(totalRowsMap.get("rowCount").toString()), resultList);
383 341 }
384 342  
385 343 @Override
386 344 public Map<String, Object> findPageBySql(String sqlCondition, int page, int pageSize, Long tenantId){
387   - StringBuffer sql = new StringBuffer("SELECT "+this.tableFieldNameListGapWithComma+" FROM "+this.getTableSql()+" WHERE tenant_id=" + tenantId + " and " + sqlCondition );
  345 + StringBuffer sql = new StringBuffer("SELECT "+this._tableFieldNameListGapWithComma+" FROM "+this.getTableSql()+" WHERE tenant_id=" + tenantId + " and " + sqlCondition );
388 346 StringBuffer sqlCount = new StringBuffer("SELECT count(1) rowCount FROM "+this.getTableSql()+" WHERE tenant_id=" + tenantId + " and " + sqlCondition);
389 347 sql.append(" limit ?, ?");
390 348 List<Object> page_list = new ArrayList<Object>();
391 349 page_list.add((page - 1) * pageSize);
392 350 page_list.add(page * pageSize);
393 351  
394   - Map<String, Object> totalRowsMap = jdbcTemplateWrite.queryForMap(sqlCount.toString());
395   - List<T> resultList = jdbcTemplateWrite.query(sql.toString(), this.customJdbcTemplateRowMapper, page_list.toArray());
  352 + Map<String, Object> totalRowsMap = _jdbcTemplateWrapperTenant.queryForMap(sqlCount.toString(), tenantId);
  353 + List<T> resultList = _jdbcTemplateWrapperTenant.query(sql.toString(), this._customJdbcTemplateRowMapper, tenantId, page_list.toArray());
396 354 return UtilsSql.createPage(page, pageSize, Integer.valueOf(totalRowsMap.get("rowCount").toString()), resultList);
397 355 }
398 356  
399 357 @Override
400   - public void addEntity(T entity) {
  358 + public void addEntity(T entity, Long tenantId) {
401 359 StringBuffer sqlInsertPart = new StringBuffer("INSERT INTO "+this.getTableSql()+"(");
402 360 StringBuffer sqlColumnPart = new StringBuffer(") VALUES (");
403 361 List<Object> paramList = new ArrayList<Object>();
404 362  
405   - Iterator<String> beanFieldIter = this.beanToTableField.keySet().iterator();
  363 + Iterator<String> beanFieldIter = this._beanToTableField.keySet().iterator();
406 364 while(beanFieldIter.hasNext()){
407 365 String beanFieldName = beanFieldIter.next();
408   - String tableFieldName = this.beanToTableField.get(beanFieldName);
  366 + String tableFieldName = this._beanToTableField.get(beanFieldName);
409 367 Field beanField;
410 368 Object beanFieldValue = null;
411 369 try {
412   - beanField = this.tClassInfo.getDeclaredField(beanFieldName);
  370 + beanField = this._tClassInfo.getDeclaredField(beanFieldName);
413 371 beanField.setAccessible(true);
414 372 beanFieldValue = beanField.get(entity);
415 373 } catch (Exception e) {
... ... @@ -423,19 +381,19 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
423 381 sqlColumnPart.append(" ?,");
424 382 paramList.add(beanFieldValue);
425 383 }
426   -
  384 +
427 385 //执行SQL
428 386 String exeSql = sqlInsertPart.substring(0, sqlInsertPart.length()-1)+sqlColumnPart.substring(0, sqlColumnPart.length()-1)+")";
429   - jdbcTemplateWrite.update(exeSql, paramList.toArray());
  387 + _jdbcTemplateWrapperTenant.update(exeSql, tenantId, paramList.toArray());
430 388 }
431 389  
432 390 @Override
433   - public void addEntityList(List<T> entityList) {
  391 + public void addEntityList(List<T> entityList, Long tenantId) {
434 392 if(entityList == null || entityList.isEmpty()) {
435 393 return;
436 394 }
437 395 //构造SQL语句及Entity Field列表
438   - List<Field> beanFieldList = new ArrayList<Field>(this.beanToTableField.size());
  396 + List<Field> beanFieldList = new ArrayList<Field>(this._beanToTableField.size());
439 397 StringBuffer exeSql = new StringBuffer(this.constructUpdateSql(entityList.get(0), beanFieldList));
440 398  
441 399 //构造参数信息
... ... @@ -464,15 +422,15 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
464 422 }
465 423 exeSql.setCharAt(exeSql.length()-1, ';');
466 424  
467   - //执行SQL
468   - this.jdbcTemplateWrite.update(exeSql.toString(), args.toArray());
  425 + //执行SQL
  426 + this._jdbcTemplateWrapperTenant.update(exeSql.toString(), tenantId, args.toArray());
469 427 }
470 428  
471 429 @Override
472 430 public int deleteEntityByID(ID id, Long tenantId) {
473 431 StringBuffer sql = new StringBuffer("DELETE FROM "+this.getTableSql()+" WHERE");
474   - sql.append(" "+this.idTableFieldName+" = ? and tenant_id="+tenantId);
475   - return jdbcTemplateWrite.update(sql.toString(), id);
  432 + sql.append(" "+this._idTableFieldName+" = ? and tenant_id="+tenantId);
  433 + return _jdbcTemplateWrapperTenant.update(sql.toString(), tenantId, id);
476 434 }
477 435  
478 436 @Override
... ... @@ -486,7 +444,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
486 444 StringBuffer pql = new StringBuffer(sql.toString());
487 445 condition.add(new Object[] {"tenant_id", "=", tenantId});
488 446 this.appendWhereCondition(sql, pql, list, condition);
489   - return jdbcTemplateWrite.update( sql.toString(), list.toArray());
  447 + return _jdbcTemplateWrapperTenant.update( sql.toString(), tenantId, list.toArray());
490 448 }
491 449  
492 450 @Override
... ... @@ -494,7 +452,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
494 452 if("".equals(sqlCondition.trim())) {
495 453 throw new RuntimeException("params[sqlCondition] is empty");
496 454 }
497   - return jdbcTemplateWrite.update( "DELETE FROM "+this.getTableSql()+" WHERE tenant_id="+tenantId + " and " + sqlCondition);
  455 + return _jdbcTemplateWrapperTenant.update( "DELETE FROM "+this.getTableSql()+" WHERE tenant_id="+tenantId + " and " + sqlCondition, tenantId);
498 456 }
499 457  
500 458 @Override
... ... @@ -503,7 +461,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
503 461 for(ID id: idList) {
504 462 idSb.append(id);
505 463 }
506   - return this.deleteEntityBySql(this.idTableFieldName + " in ("+idSb.toString().substring(0, idSb.length()-1)+") and tenant_id="+tenantId, tenantId);
  464 + return this.deleteEntityBySql(this._idTableFieldName + " in ("+idSb.toString().substring(0, idSb.length()-1)+") and tenant_id="+tenantId, tenantId);
507 465 }
508 466  
509 467 @Override
... ... @@ -520,10 +478,10 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
520 478 List<Object> list = new ArrayList<Object>();
521 479 this.appendSetSql(sql, pql, list, changeList);
522 480  
523   - String where = " WHERE "+this.idTableFieldName+"=? and tenant_id="+tenantId;
  481 + String where = " WHERE "+this._idTableFieldName+"=? and tenant_id="+tenantId;
524 482 String updateSql = sql.substring(0, sql.length()-1)+where;
525   - list.add(id);
526   - return jdbcTemplateWrite.update(updateSql, list.toArray());
  483 + list.add(id);
  484 + return _jdbcTemplateWrapperTenant.update(updateSql, tenantId, list.toArray());
527 485 }
528 486  
529 487 @Override
... ... @@ -546,7 +504,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
546 504 this.appendWhereCondition(where, pwhere, list, condition);
547 505  
548 506 String updateSql = sql.substring(0, sql.length()-1)+where.toString();
549   - return jdbcTemplateWrite.update(updateSql, list.toArray());
  507 + return _jdbcTemplateWrapperTenant.update(updateSql, tenantId, list.toArray());
550 508 }
551 509  
552 510 @Override
... ... @@ -564,17 +522,13 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
564 522 this.appendSetSql(sql, pql, list, updateObj);
565 523  
566 524 String updateSql = sql.toString().substring(0, sql.length()-1) + " WHERE tenant_id="+tenantId+" and "+sqlCondition;
567   - return jdbcTemplateWrite.update(updateSql, list.toArray());
  525 + return _jdbcTemplateWrapperTenant.update(updateSql, tenantId, list.toArray());
568 526 }
569 527  
570 528 @Override
571 529 public Map<String, Object> getPageData(String coreSql, String orderByPartSql, Integer page, Integer pageSize, Long tenantId){
572   - try {
573   - String[] splitedSql = UtilsSql.splitCoreSql(coreSql);
574   - return this.getPageData(splitedSql[0], splitedSql[1], orderByPartSql, page, pageSize, tenantId);
575   - }catch (Exception e) {
576   - return UtilsSql.createPage(page, pageSize, 0, new ArrayList<Object>());
577   - }
  530 + String[] splitedSql = UtilsSql.splitCoreSql(coreSql);
  531 + return this.getPageData(splitedSql[0], splitedSql[1], orderByPartSql, page, pageSize, tenantId);
578 532 }
579 533  
580 534 @Override
... ... @@ -589,10 +543,9 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
589 543  
590 544 //执行查询
591 545 List<Map<String, Object>> queryData = new ArrayList<Map<String, Object>>();
592   - Map<String, Object> countData = new HashMap<String, Object>();
593   - queryData = this.jdbcTemplateWrite.queryForList(querySql);
594   - countData = this.jdbcTemplateWrite.queryForMap(countSql);
  546 + Map<String, Object> countData = new HashMap<String, Object>();
  547 + queryData = this._jdbcTemplateWrapperTenant.queryForList(querySql, tenantId);
  548 + countData = this._jdbcTemplateWrapperTenant.queryForMap(countSql, tenantId);
595 549 return UtilsSql.createPage(page, pageSize, Integer.valueOf(countData.get("rowsCount").toString()), queryData);
596 550 }
597   -
598 551 }
... ...
src/main/java/com/taover/repository/CustomJdbcTemplateWrapperTenantInterface.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 CustomJdbcTemplateWrapperTenantInterface<T, ID extends Serializable> {
  12 +
  13 + /**
  14 + * 按主键查询
  15 + */
  16 + public T findEntityByID(ID id, Long tenantId) throws NotFoundException;
  17 +
  18 + /**
  19 + * 按主键查询
  20 + * isLock 是否锁定, 默认不锁
  21 + * fromWriteDB 是否从写库读写,默认从读库查询
  22 + */
  23 + public T findEntityByID(ID id, Long tenantId, boolean isLock) throws NotFoundException;
  24 +
  25 + /**
  26 + * 根据条件List<Object[]>查询
  27 + * Object[]数组长度是3
  28 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
  29 + */
  30 + public T findEntityByCondition(List<Object[]> condition, Long tenantId) throws NotFoundException,MultiRowException,NoContainTenantException;
  31 +
  32 + /**
  33 + * 根据条件sql查询
  34 + * sqlCondition 为where 后面的条件。
  35 + */
  36 + public T findEntityBySql(String sqlCondition, Long tenantId) throws NotFoundException,MultiRowException,NoContainTenantException;
  37 +
  38 + /**
  39 + * 根据条件List<Object[]>查询
  40 + * Object[]数组长度是3
  41 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
  42 + */
  43 + public List<T> findListByCondition(List<Object[]> condition, Long tenantId);
  44 +
  45 + /**
  46 + * 根据条件List<Object[]>查询
  47 + * Object[]数组长度是3
  48 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
  49 + */
  50 + public List<T> findListByCondition(List<Object[]> condition, String sortCondition, Long tenantId);
  51 +
  52 + /**
  53 + * 根据条件sql查询
  54 + * sqlCondition 为where 后面的条件。
  55 + */
  56 + public List<T> findListBySql(String sqlCondition, Long tenantId);
  57 +
  58 + /**
  59 + * 按条件分页查询
  60 + * Object[]数组长度是3
  61 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
  62 + */
  63 + public Map<String, Object> findPageByCondition(List<Object[]> condition, int page, int pageSize, Long tenantId);
  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, Long tenantId);
  73 +
  74 + /**
  75 + * 按sql分页查询, sqlCondition为where 后条件sql
  76 + */
  77 + public Map<String, Object> findPageBySql(String sqlCondition, int page, int pageSize, Long tenantId);
  78 +
  79 + /**
  80 + * 添加
  81 + */
  82 + public void addEntity(T entity, Long tenantId);
  83 +
  84 + /**
  85 + * 批量添加
  86 + * @throws Exception
  87 + */
  88 + public void addEntityList(List<T> entityList, Long tenantId);
  89 +
  90 + /**
  91 + * 按ID删除
  92 + */
  93 + public int deleteEntityByID(ID id, Long tenantId);
  94 +
  95 + /**
  96 + * 删除按List<Object[]>条件
  97 + * Object[]数组长度是3
  98 + * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
  99 + */
  100 + public int deleteEntityByCondition(List<Object[]> condition, Long tenantId);
  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, Long tenantId);
  108 +
  109 + /**
  110 + * 根据list对象逐个删除。
  111 + * @throws NoContainTenantException
  112 + */
  113 + public int deleteEntityList(List<ID> idList, Long tenantId);
  114 +
  115 + /**
  116 + * 根据ID修改指定的值
  117 + */
  118 + public int updateEntityById(List<Object[]> changeList, ID id, Long tenantId);
  119 +
  120 + /**
  121 + * List<Object[]> updateObj 要修改成的值,数组长度为2,第一个值为列名,第二个值是要改成的值。
  122 + * List<Object[]> condition 修改的条件, 数组长度是3, 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
  123 + */
  124 + public int updateEntityByCondition(List<Object[]> updateObj, List<Object[]> condition, Long tenantId);
  125 +
  126 + /**
  127 + * List<Object[]> updateObj 要修改成的值,数组长度为2,第一个值为列名,第二个值是要改成的值。
  128 + * String sqlCondition 修改的条件。
  129 + */
  130 + public int updateEntityBySql(List<Object[]> updateObj, String sqlCondition, Long tenantId);
  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, Long tenantId);
  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, Long tenantId);
  152 +
  153 +}
... ...
src/main/java/com/taover/repository/JdbcRepositoryWrapperTenant.java
... ... @@ -1,152 +0,0 @@
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 JdbcRepositoryWrapperTenant<T, ID extends Serializable> {
12   -
13   - /**
14   - * 按主键查询
15   - */
16   - public T findEntityByID(ID id, Long tenantId) throws NotFoundException;
17   -
18   - /**
19   - * 按主键查询
20   - * isLock 是否锁定, 默认不锁
21   - * fromWriteDB 是否从写库读写,默认从读库查询
22   - */
23   - public T findEntityByID(ID id, Long tenantId, boolean isLock) throws NotFoundException;
24   -
25   - /**
26   - * 根据条件List<Object[]>查询
27   - * Object[]数组长度是3
28   - * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
29   - */
30   - public T findEntityByCondition(List<Object[]> condition, Long tenantId) throws NotFoundException,MultiRowException,NoContainTenantException;
31   -
32   - /**
33   - * 根据条件sql查询
34   - * sqlCondition 为where 后面的条件。
35   - */
36   - public T findEntityBySql(String sqlCondition, Long tenantId) throws NotFoundException,MultiRowException,NoContainTenantException;
37   -
38   - /**
39   - * 根据条件List<Object[]>查询
40   - * Object[]数组长度是3
41   - * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
42   - */
43   - public List<T> findListByCondition(List<Object[]> condition, Long tenantId);
44   -
45   - /**
46   - * 根据条件List<Object[]>查询
47   - * Object[]数组长度是3
48   - * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
49   - */
50   - public List<T> findListByCondition(List<Object[]> condition, String sortCondition, Long tenantId);
51   -
52   - /**
53   - * 根据条件sql查询
54   - * sqlCondition 为where 后面的条件。
55   - */
56   - public List<T> findListBySql(String sqlCondition, Long tenantId);
57   -
58   - /**
59   - * 按条件分页查询
60   - * Object[]数组长度是3
61   - * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
62   - */
63   - public Map<String, Object> findPageByCondition(List<Object[]> condition, int page, int pageSize, Long tenantId);
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, Long tenantId);
73   -
74   - /**
75   - * 按sql分页查询, sqlCondition为where 后条件sql
76   - */
77   - public Map<String, Object> findPageBySql(String sqlCondition, int page, int pageSize, Long tenantId);
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, Long tenantId);
94   -
95   - /**
96   - * 删除按List<Object[]>条件
97   - * Object[]数组长度是3
98   - * Object[], 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
99   - */
100   - public int deleteEntityByCondition(List<Object[]> condition, Long tenantId);
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, Long tenantId);
108   -
109   - /**
110   - * 根据list对象逐个删除。
111   - * @throws NoContainTenantException
112   - */
113   - public int deleteEntityList(List<ID> idList, Long tenantId);
114   -
115   - /**
116   - * 根据ID修改指定的值
117   - */
118   - public int updateEntityById(List<Object[]> changeList, ID id, Long tenantId);
119   -
120   - /**
121   - * List<Object[]> updateObj 要修改成的值,数组长度为2,第一个值为列名,第二个值是要改成的值。
122   - * List<Object[]> condition 修改的条件, 数组长度是3, 第一个参数是列名,第二个参数是操作符,第三个参数是查询条件的值。
123   - */
124   - public int updateEntityByCondition(List<Object[]> updateObj, List<Object[]> condition, Long tenantId);
125   -
126   - /**
127   - * List<Object[]> updateObj 要修改成的值,数组长度为2,第一个值为列名,第二个值是要改成的值。
128   - * String sqlCondition 修改的条件。
129   - */
130   - public int updateEntityBySql(List<Object[]> updateObj, String sqlCondition, Long tenantId);
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, Long tenantId);
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, Long tenantId);
152   -}
src/main/java/com/taover/repository/UtilsSql.java
... ... @@ -1,192 +0,0 @@
1   -package com.taover.repository;
2   -
3   -import java.util.HashMap;
4   -import java.util.Map;
5   -import java.util.Stack;
6   -
7   -import org.springframework.util.StringUtils;
8   -
9   -public class UtilsSql {
10   -
11   - public static String[] splitCoreSql(String coreSql) throws Exception {
12   - //去除''内的信息
13   - int fromIndex = calcFromIndex(coreSql);
14   - if(fromIndex > -1) {
15   - return new String[] {coreSql.substring(0, fromIndex), coreSql.substring(fromIndex, coreSql.length())};
16   - }else {
17   - throw new Exception("未找到FROM子句");
18   - }
19   - }
20   -
21   - private static int calcFromIndex(String coreSql) {
22   - Stack<String> operStack = new Stack<String>();
23   - String coreSqlUpperCase = coreSql.toUpperCase();
24   - int sqlLen = coreSqlUpperCase.length();
25   - int currIndex = 0;
26   - while(currIndex < sqlLen) {
27   - String originContainBlank = subFirstStrEndWithBlank(coreSqlUpperCase, currIndex);
28   - String itemWithoutBlank = originContainBlank.trim();
29   - if("".equals(itemWithoutBlank)) {
30   - currIndex += originContainBlank.length();
31   - continue;
32   - }
33   - if(operStack.isEmpty() && "FROM".equals(itemWithoutBlank)) {
34   - return currIndex;
35   - }
36   - dealCoupleMark(itemWithoutBlank, operStack);
37   - currIndex += originContainBlank.length();
38   - }
39   - return -1;
40   - }
41   - private static void dealCoupleMark(String itemWithoutBlank, Stack<String> operStack) {
42   - char preChar = ' ';
43   - for(int i=0; i<itemWithoutBlank.length(); ++i) {
44   - char currChar = itemWithoutBlank.charAt(i);
45   - if(preChar != '\\' && currChar == '\'') {
46   - if(operStack.isEmpty() || !operStack.peek().equals("'")) {
47   - operStack.push("'");
48   - }else if(operStack.peek().equals("'")) {
49   - operStack.pop();
50   - }
51   - }else if(currChar == '('){
52   - if(operStack.isEmpty() || !operStack.peek().equals("'")) {
53   - operStack.push("(");
54   - }
55   - }else if(currChar == ')') {
56   - if(!operStack.isEmpty() && operStack.peek().equals("(")) {
57   - operStack.pop();
58   - }
59   - }
60   - preChar = currChar;
61   - }
62   - }
63   -
64   - private static String subFirstStrEndWithBlank(String coreSqlUpperCase, int startIndex) {
65   - boolean startWithBlank = coreSqlUpperCase.charAt(startIndex)==' ';
66   - int endIndex = startIndex;
67   - int sqlLen = coreSqlUpperCase.length();
68   - char preChar = '0';
69   - for(int i=startIndex; i<sqlLen; ++i) {
70   - char currChar = coreSqlUpperCase.charAt(i);
71   - if(startWithBlank && currChar!=' ') {
72   - endIndex = i;
73   - break;
74   - }
75   - if(!startWithBlank && currChar!=' ' && preChar==' ') {
76   - endIndex = i;
77   - break;
78   - }
79   - preChar = currChar;
80   - if(i == sqlLen-1) {
81   - endIndex = sqlLen;
82   - }
83   - }
84   - return coreSqlUpperCase.substring(startIndex, endIndex);
85   - }
86   -
87   - /**
88   - * 获取排序字符串
89   - * @param sort
90   - * @param order
91   - * @param columnPreffix
92   - * @return
93   - */
94   - public static String getSortCondition(String sort, String order, String columnPreffix){
95   - String underScoreSort = UtilsString.underscoreName(sort).toLowerCase();
96   - if(StringUtils.isEmpty(columnPreffix)){
97   - columnPreffix = "";
98   - }
99   - String sortCondition = " ";
100   - if(!StringUtils.isEmpty(underScoreSort)){
101   - sortCondition = " order by ";
102   - String[] sortArr = underScoreSort.split(",");
103   - if(StringUtils.isEmpty(order)){
104   - sortCondition += columnPreffix+sortArr[0]+" DESC ";
105   - for(int i=1; i<sortArr.length; ++i){
106   - sortCondition += ","+columnPreffix+sortArr[i]+" DESC ";
107   - }
108   - }else{
109   - String[] orderArr = order.split(",");
110   - sortCondition += sortArr[0]+" "+orderArr[0]+" ";
111   - for(int i=1; i<sortArr.length; ++i){
112   - if(i < orderArr.length){
113   - sortCondition = ","+columnPreffix+sortArr[i]+" "+orderArr[i]+" ";
114   - }else{
115   - sortCondition = ","+columnPreffix+sortArr[i]+" DESC ";
116   - }
117   - }
118   - }
119   - }
120   - return sortCondition;
121   - }
122   -
123   - /**
124   - * 获取分页
125   - * @param sort
126   - * @param order
127   - * @param columnPreffix
128   - * @return
129   - */
130   - public static String getLimitCondition(int page, int pageSize){
131   - String sql = "";
132   - if(page < -1){
133   - page = 0;
134   - if(pageSize < 1){
135   - pageSize = 0;
136   - }
137   - sql += " limit "+pageSize*(page-1)+","+pageSize;
138   - }else if(page == -1){
139   - sql = "";
140   - }else{
141   - if(pageSize < 1){
142   - pageSize = 0;
143   - }
144   - sql += " limit "+pageSize*(page-1)+","+pageSize;
145   - }
146   - return sql;
147   - }
148   -
149   - /**
150   - * 创建分页返回
151   - * @param page
152   - * @param rows
153   - * @param data
154   - * @return
155   - */
156   - public static Map<String, Object> createPage(int page, int size, int total, Object data){
157   - Map<String, Object> pageData = new HashMap<String, Object>();
158   - pageData.put("page", page);
159   - pageData.put("rows", data);
160   - pageData.put("size", size);
161   - pageData.put("total", total);
162   - return pageData;
163   - }
164   -
165   - public static void main(String[] args) {
166   - String[] testSql = new String[] {
167   - "\\",
168   - "select actionFrom as 'seelctsele\\'ctd',(select a as 'fromCActio' from t) from www where 223=1 ",
169   - "SELECT wxorder_order.refund_way refundWay,wxorder_order.refund_delivery_sn refundDeliverySn, (SELECT sum(wxorder_compensate.`ware_refund_money`) from `wxorder_compensate` where wxorder_compensate.`order_id` = wxorder_order.id) as wareRefundMoney,(SELECT sum(wxorder_compensate.`refund_money`) from `wxorder_compensate` where wxorder_compensate.`order_id` = wxorder_order.id) as refundMoney, wxorder_order.operate_refund_time applyCompensateTime,wxorder_order.refund_instructions refundInstructions, wxorder_order.channel_id channelId, wxorder_channel.name channelName, wxorder_channel.platform_code platformCode, wxorder_order.pre_control_status as refundPreStatus, wxorder_order.ware_id wareId, wxorder_ware.name wareName, wxorder_order.id, wxorder_order.order_sn orderSn, wxorder_order.upload_sn uploadSn, wxorder_order.money_paid moneyPaid, wxorder_order.consignee, wxorder_order.mobile, wxorder_order.province_name provinceName, wxorder_order.city_name cityName, wxorder_order.district_name districtName, wxorder_order.address, wxorder_order.channel_remark channelRemark, wxorder_order.customer_remark customerRemark, wxorder_order.platform_customer_remark platformCustomerRemark, wxorder_order.sender_name senderName, wxorder_order.sender_mobile senderMobile, date_format(wxorder_order.create_time, '%Y-%m-%d %H:%i:%s') createTime, date_format(wxorder_order.real_delivery_time, '%Y-%m-%d %H:%i:%s') realDeliveryTime, wxorder_order.progress_distribute progressDistribute, wxorder_order.progress_delivery progressDelivery, wxorder_order.control_status controlStatus, wxorder_order.express_name expressName, wxorder_order.express_number expressNumber,wxorder_order.shipping_price shippingPrice, wxorder_order.customer_network_name ,(select count(*) from wxorder_compensate WHERE wxorder_compensate.order_id = wxorder_order.id) as compensateCountAll,(select count(*) from wxorder_compensate WHERE wxorder_compensate.order_id = wxorder_order.id and wxorder_compensate.progress_status = 1) as compensateCountDealed ,(select count(*) from wxorder_channel_refund_payment where wxorder_channel_refund_payment.order_id = wxorder_order.id) as channelRefundPaymentStatus,(select count(*) from wxorder_ware_refund_payment where wxorder_ware_refund_payment.order_id = wxorder_order.id) as wareRefundPaymentStatus FROM wxorder_order wxorder_order INNER JOIN wxorder_channel wxorder_channel ON wxorder_order.channel_id=wxorder_channel.id and wxorder_channel.tenant_id=54 INNER JOIN wxorder_ware wxorder_ware ON wxorder_order.ware_id=wxorder_ware.id and wxorder_ware.tenant_id=54 INNER JOIN wxorder_order_goods wxorder_order_goods ON wxorder_order.id=wxorder_order_goods.order_id and wxorder_order_goods.tenant_id=54 WHERE 1=1 AND wxorder_order.tenant_id='54' AND wxorder_order.control_status='4' GROUP BY wxorder_order.id",
170   - "select wdd, fromType from www where 223",
171   - "SELECT excel_data.already_deal_line alreadyDealLine, excel_data.channel_id channelId, excel_data.channel_name channelName, excel_data.contain_express_status containExpressStatus, excel_data.create_time createTime, excel_data.deal_control dealControl, excel_data.deal_status dealStatus, excel_data.excel_path excelPath, excel_data.excel_title_index excelTitleIndex, excel_data.exists_error existsError, excel_data.file_id fileId, excel_data.file_name fileName, excel_data.group_name groupName, excel_data.id, excel_data.key_mapping keyMapping, excel_data.message_ssid messageSsid, excel_data.order_line orderLine, excel_data.payload payload, excel_data.progress_step progressStep, excel_data.select_sheet_name selectSheetName, excel_data.step_deal_time stepDealTime, excel_data.tenant_id tenantId, excel_data.update_time updateTime, excel_data.xls_batch_no xlsBatchNo FROM wxorder_excel_data excel_data WHERE excel_data.tenant_id=16",
172   - "SELECT excel_data.xls_batch_no as 'xlsBatchNo', (select now()) as 'temp' FROM wxorder_excel_data excel_data WHERE excel_data.tenant_id=16"
173   - };
174   -
175   - for(int i=0; i<testSql.length; ++i) {
176   - String item = testSql[i];
177   - System.out.println("================testSql["+i+"]===============");
178   - try {
179   - String[] data = splitCoreSql(item);
180   - System.out.println(data[0]);
181   - System.out.println(data[1]);
182   - } catch (Exception e) {
183   - System.out.println(e.getMessage());
184   - }
185   - }
186   -
187   -// String testSub = " asdf asdf asdfaf";
188   -// System.out.println(subFirstStrEndWithBlank(testSub, 5));
189   -// System.out.println(subFirstStrEndWithBlank(testSub, 6));
190   -// System.out.println(subFirstStrEndWithBlank(testSub, 13));
191   - }
192   -}
src/main/java/com/taover/repository/UtilsString.java
... ... @@ -1,237 +0,0 @@
1   -package com.taover.repository;
2   -
3   -import java.net.URL;
4   -import java.text.SimpleDateFormat;
5   -import java.util.Date;
6   -
7   -public class UtilsString {
8   - /**
9   - * 格式化日期区间字符串
10   - * @param source
11   - * @param splitStr
12   - * @param dateFormat
13   - * @return
14   - * @throws Exception
15   - */
16   - public static Date[] getDateFromString(String source, String splitStr, String dateFormat) throws Exception{
17   - Date[] resultObj = new Date[2];
18   - Date createdAtStart = null;
19   - Date createdAtEnd = null;
20   - if(source != null && !"".equals(source)){
21   - String[] createdAtArr = source.split(splitStr);
22   - SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
23   - if(createdAtArr.length > 0){
24   - createdAtStart = sdf.parse(createdAtArr[0]);
25   - }
26   - if(createdAtArr.length > 1){
27   - createdAtEnd = sdf.parse(createdAtArr[1]);
28   - }
29   - }
30   - resultObj[0] = createdAtStart;
31   - resultObj[1] = createdAtEnd;
32   - return resultObj;
33   - }
34   -
35   - /**
36   - * 获取URL path部分
37   - * @param url
38   - * @return
39   - */
40   - public static String getUrlPath(String url){
41   - if(url == null){
42   - return null;
43   - }
44   - if(url.startsWith("http")){
45   - try{
46   - URL dataUrl = new URL(url);
47   - return dataUrl.getPath();
48   - }catch(Exception e){
49   - e.printStackTrace();
50   - }
51   - }
52   - return url;
53   - }
54   -
55   - /**
56   - * 在compares字符数组查找pattern字符串,找到则返回字串在数组中的索引,未找到返回-1
57   - * @param pattern
58   - * @param compares
59   - * @return
60   - */
61   - public static int getStringIndex(String pattern, String compares[]){
62   - //参数检验
63   - if(pattern==null || compares==null){
64   - return -1;
65   - }
66   -
67   - //循环遍历compares
68   - for(int i=0; i<compares.length; ++i){
69   - if(compares[i].equals(pattern)){
70   - return i;
71   - }
72   - }
73   - return -1;
74   - }
75   -
76   - /**
77   - * 生成发货单的发货单内部序号, 格式:'D'.date('Ymd') +8位数字
78   - * @return
79   - */
80   - public static String getDeliverySn(){
81   - String result = "D";
82   - String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
83   - long temp = System.currentTimeMillis()%100000000;
84   - result = result + date + temp;
85   - return result;
86   - }
87   -
88   - /**
89   - * 通过表名获取BEAN类名
90   - * @param tableName
91   - * @return
92   - */
93   - public static String getBeanNameFormTableName(String tableName){
94   - if (tableName == null) return null;
95   - if (tableName.length() == 0) return "";
96   - byte[] ss = tableName.toLowerCase().getBytes();
97   - int len = ss.length;
98   - byte[] ss1 = new byte[len];
99   - ss1[0] = new String(ss, 0).toUpperCase().getBytes()[0];
100   - int k = 1;
101   - for (int i = 1; i < ss.length; i++) {
102   - if (ss[i] == '_') {
103   - if (i < ss.length - 1) {
104   - ss1[k] = (byte)Character.toUpperCase(ss[(i + 1)]);
105   - i++;
106   - }
107   - len--;
108   - } else {
109   - ss1[k] = ss[i];
110   - }
111   - k++;
112   - }
113   - return new String(ss1, 0, len);
114   - }
115   -
116   - /**
117   - * 获取前缀
118   - * @param value
119   - * @param digitNumber
120   - * @param preffixChar
121   - * @return
122   - */
123   - public static String getCodeWithPreffix(long value, int digitNumber, char preffixChar){
124   - String result = "";
125   - if(value>Long.MAX_VALUE || value<Long.MIN_VALUE){
126   - return null;
127   - }
128   - for(int i=digitNumber; i>0; --i){
129   - long baseDiv = (long) Math.pow(10, i-1);
130   - long baseRand = (long) Math.pow(10, i);
131   - long currentDigit = value % baseRand / baseDiv;
132   - if(currentDigit == 0){
133   - result = result + preffixChar;
134   - }else{
135   - result = result + currentDigit;
136   - }
137   - }
138   - return result;
139   - }
140   -
141   - /**
142   - * 将驼峰式命名的字符串转换为下划线大写方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。</br>
143   - * 例如:HelloWorld->HELLO_WORLD
144   - * @param name 转换前的驼峰式命名的字符串
145   - * @return 转换后下划线大写方式命名的字符串
146   - */
147   - public static String underscoreName(String name) {
148   - StringBuilder result = new StringBuilder();
149   - if (name != null && name.length() > 0) {
150   - // 将第一个字符处理成大写
151   - result.append(name.substring(0, 1).toUpperCase());
152   - // 循环处理其余字符
153   - for (int i = 1; i < name.length(); i++) {
154   - String s = name.substring(i, i + 1);
155   - // 在大写字母前添加下划线
156   - if (Character.isUpperCase(s.charAt(0)) && Character.isLetter(s.charAt(0))) {
157   - result.append("_");
158   - }
159   - // 其他字符直接转成大写
160   - result.append(s.toUpperCase());
161   - }
162   - }
163   - return result.toString();
164   - }
165   -
166   - /**
167   - * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
168   - * 例如:HELLO_WORLD->HelloWorld
169   - * @param name 转换前的下划线大写方式命名的字符串
170   - * @return 转换后的驼峰式命名的字符串
171   - */
172   - public static String camelName(String name) {
173   - StringBuilder result = new StringBuilder();
174   - // 快速检查
175   - if (name == null || name.isEmpty()) {
176   - // 没必要转换
177   - return "";
178   - } else if (!name.contains("_")) {
179   - // 不含下划线,仅将首字母小写
180   - return name.substring(0, 1).toLowerCase() + name.substring(1);
181   - }
182   - // 用下划线将原始字符串分割
183   - String camels[] = name.split("_");
184   - for (String camel : camels) {
185   - // 跳过原始字符串中开头、结尾的下换线或双重下划线
186   - if (camel.isEmpty()) {
187   - continue;
188   - }
189   - // 处理真正的驼峰片段
190   - if (result.length() == 0) {
191   - // 第一个驼峰片段,全部字母都小写
192   - result.append(camel.toLowerCase());
193   - } else {
194   - // 其他的驼峰片段,首字母大写
195   - result.append(camel.substring(0, 1).toUpperCase());
196   - result.append(camel.substring(1).toLowerCase());
197   - }
198   - }
199   - return result.toString();
200   - }
201   -
202   - public static String getRandomStr(int digitNum){
203   - int numStartZero = 48;
204   - int charStartUpperA = 65;
205   - int charStartLowerA = 97;
206   - int numSelectCount = 10;
207   - int charSelectCount = 26;
208   - int numCount = numSelectCount+2*charSelectCount;
209   - String randomResult = "";
210   - for(int i=0; i<digitNum; ++i){
211   - int currIndex = (int)(Math.random()*numCount);
212   - if(currIndex < numSelectCount){
213   - currIndex = numStartZero+currIndex;
214   - }else if(currIndex < numSelectCount+charSelectCount){
215   - currIndex = charStartUpperA+(currIndex-numSelectCount);
216   - }else{
217   - currIndex = charStartLowerA+(currIndex-numSelectCount-charSelectCount);
218   - }
219   - randomResult += (char)(currIndex)+"";
220   - }
221   - return randomResult;
222   - }
223   -
224   - public static void main(String args[]){
225   -// System.out.println(getBeanNameFormTableName("asdf_asdf"));
226   -// System.out.println(System.currentTimeMillis());
227   -// System.out.println(getCodeWithPreffix(1231212, 10, '-'));
228   - /*String dd = "\"{\"success\":true,\"code\":1,\"printedorder_id\":\"1654\",\"error_message\":\"\"}\"";
229   - dd = dd.substring(1, dd.length()-1);
230   - System.out.println(dd);
231   - JSONObject temp = JSONObject.fromObject(dd);
232   - System.out.println(temp.getInt("code"));*/
233   -
234   - //System.out.println(UtilsString.getUrlPath("https://ss0.umsapi.com/files/de/c1/13/dec11397254b06e1fd8750311ec2bb02ccd8d3dc.jpeg"));
235   - System.out.println(getRandomStr(12));
236   - }
237   -}
238 0 \ No newline at end of file
src/main/java/com/taover/repository/autoconfigure/ShardingSphereKeyGeneratorConfiguration.java 0 → 100644
... ... @@ -0,0 +1,31 @@
  1 +package com.taover.repository.autoconfigure;
  2 +
  3 +import org.springframework.boot.context.properties.ConfigurationProperties;
  4 +import org.springframework.context.annotation.Configuration;
  5 +
  6 +@Configuration
  7 +@ConfigurationProperties(prefix = "taover.sharding")
  8 +public class ShardingSphereKeyGeneratorConfiguration {
  9 + private String workerId;
  10 + private String maxTolerateTimeDifferenceMilliseconds;
  11 + private String maxVibrationOffset;
  12 +
  13 + public String getWorkerId() {
  14 + return workerId;
  15 + }
  16 + public void setWorkerId(String workerId) {
  17 + this.workerId = workerId;
  18 + }
  19 + public String getMaxTolerateTimeDifferenceMilliseconds() {
  20 + return maxTolerateTimeDifferenceMilliseconds;
  21 + }
  22 + public void setMaxTolerateTimeDifferenceMilliseconds(String maxTolerateTimeDifferenceMilliseconds) {
  23 + this.maxTolerateTimeDifferenceMilliseconds = maxTolerateTimeDifferenceMilliseconds;
  24 + }
  25 + public String getMaxVibrationOffset() {
  26 + return maxVibrationOffset;
  27 + }
  28 + public void setMaxVibrationOffset(String maxVibrationOffset) {
  29 + this.maxVibrationOffset = maxVibrationOffset;
  30 + }
  31 +}
... ...
src/main/java/com/taover/repository/autoconfigure/TaoverRepositoryAutoConfiguration.java 0 → 100644
... ... @@ -0,0 +1,44 @@
  1 +package com.taover.repository.autoconfigure;
  2 +
  3 +import javax.annotation.Resource;
  4 +
  5 +import org.springframework.boot.autoconfigure.AutoConfigureAfter;
  6 +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
  7 +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
  8 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  9 +import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
  10 +import org.springframework.boot.context.properties.EnableConfigurationProperties;
  11 +import org.springframework.context.annotation.Bean;
  12 +import org.springframework.context.annotation.Configuration;
  13 +
  14 +import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenant;
  15 +import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenantImpl;
  16 +import com.taover.repository.shardingsphere.ShardingInfoRepository;
  17 +import com.taover.repository.shardingsphere.ShardingSphereService;
  18 +
  19 +@Configuration
  20 +@EnableConfigurationProperties({ShardingSphereKeyGeneratorConfiguration.class})
  21 +@AutoConfigureAfter(JdbcTemplateAutoConfiguration.class)
  22 +@ConditionalOnProperty(prefix = "spring.shardingsphere", name = "enabled", havingValue = "true", matchIfMissing = true)
  23 +@ConditionalOnClass({ShardingSphereService.class})
  24 +@ConditionalOnMissingBean(ShardingSphereService.class)
  25 +public class TaoverRepositoryAutoConfiguration {
  26 +
  27 + @Resource
  28 + private ShardingSphereKeyGeneratorConfiguration config;
  29 +
  30 + @Bean
  31 + public ShardingSphereService shardingSphereService() {
  32 + return new ShardingSphereService(config);
  33 + }
  34 +
  35 + @Bean
  36 + public ShardingInfoRepository shardingInfoRepository() throws Exception {
  37 + return new ShardingInfoRepository();
  38 + }
  39 +
  40 + @Bean
  41 + public JdbcTemplateWrapperTenant jdbcTemplateWrapperTenant() {
  42 + return new JdbcTemplateWrapperTenantImpl();
  43 + }
  44 +}
... ...
src/main/java/com/taover/repository/bean/TenantIdentity.java 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +package com.taover.repository.bean;
  2 +
  3 +public abstract class TenantIdentity {
  4 + public abstract Long getTenantId();
  5 +}
  6 +
... ...
src/main/java/com/taover/repository/exception/MultiRowException.java
1 1 package com.taover.repository.exception;
2 2  
3 3 public class MultiRowException extends Exception {
  4 +
4 5 }
... ...
src/main/java/com/taover/repository/exception/NotFoundException.java
1 1 package com.taover.repository.exception;
2 2  
3 3 public class NotFoundException extends Exception {
4   -
  4 + private Exception originError;
  5 +
  6 + public NotFoundException() {}
  7 +
  8 + public NotFoundException(Exception e) {
  9 + this.originError = e;
  10 + }
5 11 }
... ...
src/main/java/com/taover/repository/exception/SqlParsePagerException.java 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +package com.taover.repository.exception;
  2 +
  3 +public class SqlParsePagerException extends RuntimeException{
  4 + private String msg = null;
  5 +
  6 + public SqlParsePagerException(String msg) {
  7 + this.msg = msg;
  8 + }
  9 +
  10 +}
... ...
src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateWrapperTenant.java 0 → 100644
... ... @@ -0,0 +1,966 @@
  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 JdbcTemplateWrapperTenant {
  32 +
  33 + //-------------------------------------------------------------------------
  34 + // Methods dealing with a plain java.sql.Connection
  35 + //-------------------------------------------------------------------------
  36 +
  37 + /**
  38 + * Execute a JDBC data access operation, implemented as callback action
  39 + * working on a JDBC Connection. This allows for implementing arbitrary
  40 + * data access operations, within Spring's managed JDBC environment:
  41 + * that is, participating in Spring-managed transactions and converting
  42 + * JDBC SQLExceptions into Spring's DataAccessException hierarchy.
  43 + * <p>The callback action can return a result object, for example a domain
  44 + * object or a collection of domain objects.
  45 + * @param action a callback object that specifies the action
  46 + * @return a result object returned by the action, or {@code null} if none
  47 + * @throws DataAccessException if there is any problem
  48 + */
  49 + @Nullable
  50 + <T> T execute(ConnectionCallback<T> action, Long tenantId) throws DataAccessException;
  51 +
  52 +
  53 + //-------------------------------------------------------------------------
  54 + // Methods dealing with static SQL (java.sql.Statement)
  55 + //-------------------------------------------------------------------------
  56 +
  57 + /**
  58 + * Execute a JDBC data access operation, implemented as callback action
  59 + * working on a JDBC Statement. This allows for implementing arbitrary data
  60 + * access operations on a single Statement, within Spring's managed JDBC
  61 + * environment: that is, participating in Spring-managed transactions and
  62 + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy.
  63 + * <p>The callback action can return a result object, for example a domain
  64 + * object or a collection of domain objects.
  65 + * @param action a callback that specifies the action
  66 + * @return a result object returned by the action, or {@code null} if none
  67 + * @throws DataAccessException if there is any problem
  68 + */
  69 + @Nullable
  70 + <T> T execute(StatementCallback<T> action, Long tenantId) throws DataAccessException;
  71 +
  72 + /**
  73 + * Issue a single SQL execute, typically a DDL statement.
  74 + * @param sql static SQL to execute
  75 + * @throws DataAccessException if there is any problem
  76 + */
  77 + void execute(String sql, Long tenantId) throws DataAccessException;
  78 +
  79 + /**
  80 + * Execute a query given static SQL, reading the ResultSet with a
  81 + * ResultSetExtractor.
  82 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  83 + * execute a static query with a PreparedStatement, use the overloaded
  84 + * {@code query} method with {@code null} as argument array.
  85 + * @param sql the SQL query to execute
  86 + * @param rse a callback that will extract all rows of results
  87 + * @return an arbitrary result object, as returned by the ResultSetExtractor
  88 + * @throws DataAccessException if there is any problem executing the query
  89 + * @see #query(String, Object[], ResultSetExtractor)
  90 + */
  91 + @Nullable
  92 + <T> T query(String sql, ResultSetExtractor<T> rse, Long tenantId) throws DataAccessException;
  93 +
  94 + /**
  95 + * Execute a query given static SQL, reading the ResultSet on a per-row
  96 + * basis with a RowCallbackHandler.
  97 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  98 + * execute a static query with a PreparedStatement, use the overloaded
  99 + * {@code query} method with {@code null} as argument array.
  100 + * @param sql the SQL query to execute
  101 + * @param rch a callback that will extract results, one row at a time
  102 + * @throws DataAccessException if there is any problem executing the query
  103 + * @see #query(String, Object[], RowCallbackHandler)
  104 + */
  105 + void query(String sql, RowCallbackHandler rch, Long tenantId) throws DataAccessException;
  106 +
  107 + /**
  108 + * Execute a query given static SQL, mapping each row to a result object
  109 + * via a RowMapper.
  110 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  111 + * execute a static query with a PreparedStatement, use the overloaded
  112 + * {@code query} method with {@code null} as argument array.
  113 + * @param sql the SQL query to execute
  114 + * @param rowMapper a callback that will map one object per row
  115 + * @return the result List, containing mapped objects
  116 + * @throws DataAccessException if there is any problem executing the query
  117 + * @see #query(String, Object[], RowMapper)
  118 + */
  119 + <T> List<T> query(String sql, RowMapper<T> rowMapper, Long tenantId) throws DataAccessException;
  120 +
  121 + /**
  122 + * Execute a query given static SQL, mapping a single result row to a
  123 + * result object via a RowMapper.
  124 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  125 + * execute a static query with a PreparedStatement, use the overloaded
  126 + * {@link #queryForObject(String, RowMapper, Object...)} method with
  127 + * {@code null} as argument array.
  128 + * @param sql the SQL query to execute
  129 + * @param rowMapper a callback that will map one object per row
  130 + * @return the single mapped object (may be {@code null} if the given
  131 + * {@link RowMapper} returned {@code} null)
  132 + * @throws IncorrectResultSizeDataAccessException if the query does not
  133 + * return exactly one row
  134 + * @throws DataAccessException if there is any problem executing the query
  135 + * @see #queryForObject(String, Object[], RowMapper)
  136 + */
  137 + @Nullable
  138 + <T> T queryForObject(String sql, RowMapper<T> rowMapper, Long tenantId) throws DataAccessException;
  139 +
  140 + /**
  141 + * Execute a query for a result object, given static SQL.
  142 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  143 + * execute a static query with a PreparedStatement, use the overloaded
  144 + * {@link #queryForObject(String, Class, Object...)} method with
  145 + * {@code null} as argument array.
  146 + * <p>This method is useful for running static SQL with a known outcome.
  147 + * The query is expected to be a single row/single column query; the returned
  148 + * result will be directly mapped to the corresponding object type.
  149 + * @param sql the SQL query to execute
  150 + * @param requiredType the type that the result object is expected to match
  151 + * @return the result object of the required type, or {@code null} in case of SQL NULL
  152 + * @throws IncorrectResultSizeDataAccessException if the query does not return
  153 + * exactly one row, or does not return exactly one column in that row
  154 + * @throws DataAccessException if there is any problem executing the query
  155 + * @see #queryForObject(String, Object[], Class)
  156 + */
  157 + @Nullable
  158 + <T> T queryForObject(String sql, Class<T> requiredType, Long tenantId) throws DataAccessException;
  159 +
  160 + /**
  161 + * Execute a query for a result map, given static SQL.
  162 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  163 + * execute a static query with a PreparedStatement, use the overloaded
  164 + * {@link #queryForMap(String, Object...)} method with {@code null}
  165 + * as argument array.
  166 + * <p>The query is expected to be a single row query; the result row will be
  167 + * mapped to a Map (one entry for each column, using the column name as the key).
  168 + * @param sql the SQL query to execute
  169 + * @return the result Map (one entry per column, with column name as key)
  170 + * @throws IncorrectResultSizeDataAccessException if the query does not
  171 + * return exactly one row
  172 + * @throws DataAccessException if there is any problem executing the query
  173 + * @see #queryForMap(String, Object[])
  174 + * @see ColumnMapRowMapper
  175 + */
  176 + Map<String, Object> queryForMap(String sql, Long tenantId) throws DataAccessException;
  177 +
  178 + /**
  179 + * Execute a query for a result list, given static SQL.
  180 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  181 + * execute a static query with a PreparedStatement, use the overloaded
  182 + * {@code queryForList} method with {@code null} as argument array.
  183 + * <p>The results will be mapped to a List (one entry for each row) of
  184 + * result objects, each of them matching the specified element type.
  185 + * @param sql the SQL query to execute
  186 + * @param elementType the required type of element in the result list
  187 + * (for example, {@code Integer.class})
  188 + * @return a List of objects that match the specified element type
  189 + * @throws DataAccessException if there is any problem executing the query
  190 + * @see #queryForList(String, Object[], Class)
  191 + * @see SingleColumnRowMapper
  192 + */
  193 + <T> List<T> queryForList(String sql, Class<T> elementType, Long tenantId) throws DataAccessException;
  194 +
  195 + /**
  196 + * Execute a query for a result list, given static SQL.
  197 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  198 + * execute a static query with a PreparedStatement, use the overloaded
  199 + * {@code queryForList} method with {@code null} as argument array.
  200 + * <p>The results will be mapped to a List (one entry for each row) of
  201 + * Maps (one entry for each column using the column name as the key).
  202 + * Each element in the list will be of the form returned by this interface's
  203 + * {@code queryForMap} methods.
  204 + * @param sql the SQL query to execute
  205 + * @return an List that contains a Map per row
  206 + * @throws DataAccessException if there is any problem executing the query
  207 + * @see #queryForList(String, Object[])
  208 + */
  209 + List<Map<String, Object>> queryForList(String sql, Long tenantId) throws DataAccessException;
  210 +
  211 + /**
  212 + * Execute a query for a SqlRowSet, given static SQL.
  213 + * <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
  214 + * execute a static query with a PreparedStatement, use the overloaded
  215 + * {@code queryForRowSet} method with {@code null} as argument array.
  216 + * <p>The results will be mapped to an SqlRowSet which holds the data in a
  217 + * disconnected fashion. This wrapper will translate any SQLExceptions thrown.
  218 + * <p>Note that, for the default implementation, JDBC RowSet support needs to
  219 + * be available at runtime: by default, Sun's {@code com.sun.rowset.CachedRowSetImpl}
  220 + * class is used, which is part of JDK 1.5+ and also available separately as part of
  221 + * Sun's JDBC RowSet Implementations download (rowset.jar).
  222 + * @param sql the SQL query to execute
  223 + * @return a SqlRowSet representation (possibly a wrapper around a
  224 + * {@code javax.sql.rowset.CachedRowSet})
  225 + * @throws DataAccessException if there is any problem executing the query
  226 + * @see #queryForRowSet(String, Object[])
  227 + * @see SqlRowSetResultSetExtractor
  228 + * @see javax.sql.rowset.CachedRowSet
  229 + */
  230 + SqlRowSet queryForRowSet(String sql, Long tenantId) throws DataAccessException;
  231 +
  232 + /**
  233 + * Issue a single SQL update operation (such as an insert, update or delete statement).
  234 + * @param sql static SQL to execute
  235 + * @return the number of rows affected
  236 + * @throws DataAccessException if there is any problem.
  237 + */
  238 + int update(String sql, Long tenantId) throws DataAccessException;
  239 +
  240 + /**
  241 + * Issue multiple SQL updates on a single JDBC Statement using batching.
  242 + * <p>Will fall back to separate updates on a single Statement if the JDBC
  243 + * driver does not support batch updates.
  244 + * @param sql defining an array of SQL statements that will be executed.
  245 + * @return an array of the number of rows affected by each statement
  246 + * @throws DataAccessException if there is any problem executing the batch
  247 + */
  248 + int[] batchUpdate(Long tenantId, String... sql) throws DataAccessException;
  249 +
  250 +
  251 + //-------------------------------------------------------------------------
  252 + // Methods dealing with prepared statements
  253 + //-------------------------------------------------------------------------
  254 +
  255 + /**
  256 + * Execute a JDBC data access operation, implemented as callback action
  257 + * working on a JDBC PreparedStatement. This allows for implementing arbitrary
  258 + * data access operations on a single Statement, within Spring's managed JDBC
  259 + * environment: that is, participating in Spring-managed transactions and
  260 + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy.
  261 + * <p>The callback action can return a result object, for example a domain
  262 + * object or a collection of domain objects.
  263 + * @param psc a callback that creates a PreparedStatement given a Connection
  264 + * @param action a callback that specifies the action
  265 + * @return a result object returned by the action, or {@code null} if none
  266 + * @throws DataAccessException if there is any problem
  267 + */
  268 + @Nullable
  269 + <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action, Long tenantId) throws DataAccessException;
  270 +
  271 + /**
  272 + * Execute a JDBC data access operation, implemented as callback action
  273 + * working on a JDBC PreparedStatement. This allows for implementing arbitrary
  274 + * data access operations on a single Statement, within Spring's managed JDBC
  275 + * environment: that is, participating in Spring-managed transactions and
  276 + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy.
  277 + * <p>The callback action can return a result object, for example a domain
  278 + * object or a collection of domain objects.
  279 + * @param sql the SQL to execute
  280 + * @param action a callback that specifies the action
  281 + * @return a result object returned by the action, or {@code null} if none
  282 + * @throws DataAccessException if there is any problem
  283 + */
  284 + @Nullable
  285 + <T> T execute(String sql, PreparedStatementCallback<T> action, Long tenantId) throws DataAccessException;
  286 +
  287 + /**
  288 + * Query using a prepared statement, reading the ResultSet with a ResultSetExtractor.
  289 + * <p>A PreparedStatementCreator can either be implemented directly or
  290 + * configured through a PreparedStatementCreatorFactory.
  291 + * @param psc a callback that creates a PreparedStatement given a Connection
  292 + * @param rse a callback that will extract results
  293 + * @return an arbitrary result object, as returned by the ResultSetExtractor
  294 + * @throws DataAccessException if there is any problem
  295 + * @see PreparedStatementCreatorFactory
  296 + */
  297 + @Nullable
  298 + <T> T query(PreparedStatementCreator psc, ResultSetExtractor<T> rse, Long tenantId) throws DataAccessException;
  299 +
  300 + /**
  301 + * Query using a prepared statement, reading the ResultSet with a ResultSetExtractor.
  302 + * @param sql the SQL query to execute
  303 + * @param pss a callback that knows how to set values on the prepared statement.
  304 + * If this is {@code null}, the SQL will be assumed to contain no bind parameters.
  305 + * Even if there are no bind parameters, this callback may be used to set the
  306 + * fetch size and other performance options.
  307 + * @param rse a callback that will extract results
  308 + * @return an arbitrary result object, as returned by the ResultSetExtractor
  309 + * @throws DataAccessException if there is any problem
  310 + */
  311 + @Nullable
  312 + <T> T query(String sql, @Nullable PreparedStatementSetter pss, ResultSetExtractor<T> rse, Long tenantId) throws DataAccessException;
  313 +
  314 + /**
  315 + * Query given SQL to create a prepared statement from SQL and a list of arguments
  316 + * to bind to the query, reading the ResultSet with a ResultSetExtractor.
  317 + * @param sql the SQL query to execute
  318 + * @param args arguments to bind to the query
  319 + * @param argTypes the SQL types of the arguments
  320 + * (constants from {@code java.sql.Types})
  321 + * @param rse a callback that will extract results
  322 + * @return an arbitrary result object, as returned by the ResultSetExtractor
  323 + * @throws DataAccessException if the query fails
  324 + * @see java.sql.Types
  325 + */
  326 + @Nullable
  327 + <T> T query(String sql, Object[] args, int[] argTypes, ResultSetExtractor<T> rse, Long tenantId) throws DataAccessException;
  328 +
  329 + /**
  330 + * Query given SQL to create a prepared statement from SQL and a list of arguments
  331 + * to bind to the query, reading the ResultSet with a ResultSetExtractor.
  332 + * @param sql the SQL query to execute
  333 + * @param args arguments to bind to the query
  334 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  335 + * may also contain {@link SqlParameterValue} objects which indicate not
  336 + * only the argument value but also the SQL type and optionally the scale
  337 + * @param rse a callback that will extract results
  338 + * @return an arbitrary result object, as returned by the ResultSetExtractor
  339 + * @throws DataAccessException if the query fails
  340 + */
  341 + @Nullable
  342 + <T> T query(String sql, Object[] args, ResultSetExtractor<T> rse, Long tenantId) throws DataAccessException;
  343 +
  344 + /**
  345 + * Query given SQL to create a prepared statement from SQL and a list of arguments
  346 + * to bind to the query, reading the ResultSet with a ResultSetExtractor.
  347 + * @param sql the SQL query to execute
  348 + * @param rse a callback that will extract results
  349 + * @param args arguments to bind to the query
  350 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  351 + * may also contain {@link SqlParameterValue} objects which indicate not
  352 + * only the argument value but also the SQL type and optionally the scale
  353 + * @return an arbitrary result object, as returned by the ResultSetExtractor
  354 + * @throws DataAccessException if the query fails
  355 + * @since 3.0.1
  356 + */
  357 + @Nullable
  358 + <T> T query(String sql, ResultSetExtractor<T> rse, Long tenantId, @Nullable Object... args) throws DataAccessException;
  359 +
  360 + /**
  361 + * Query using a prepared statement, reading the ResultSet on a per-row basis
  362 + * with a RowCallbackHandler.
  363 + * <p>A PreparedStatementCreator can either be implemented directly or
  364 + * configured through a PreparedStatementCreatorFactory.
  365 + * @param psc a callback that creates a PreparedStatement given a Connection
  366 + * @param rch a callback that will extract results, one row at a time
  367 + * @throws DataAccessException if there is any problem
  368 + * @see PreparedStatementCreatorFactory
  369 + */
  370 + void query(PreparedStatementCreator psc, RowCallbackHandler rch, Long tenantId) throws DataAccessException;
  371 +
  372 + /**
  373 + * Query given SQL to create a prepared statement from SQL and a
  374 + * PreparedStatementSetter implementation that knows how to bind values to the
  375 + * query, reading the ResultSet on a per-row basis with a RowCallbackHandler.
  376 + * @param sql the SQL query to execute
  377 + * @param pss a callback that knows how to set values on the prepared statement.
  378 + * If this is {@code null}, the SQL will be assumed to contain no bind parameters.
  379 + * Even if there are no bind parameters, this callback may be used to set the
  380 + * fetch size and other performance options.
  381 + * @param rch a callback that will extract results, one row at a time
  382 + * @throws DataAccessException if the query fails
  383 + */
  384 + void query(String sql, @Nullable PreparedStatementSetter pss, RowCallbackHandler rch, Long tenantId) throws DataAccessException;
  385 +
  386 + /**
  387 + * Query given SQL to create a prepared statement from SQL and a list of
  388 + * arguments to bind to the query, reading the ResultSet on a per-row basis
  389 + * with a RowCallbackHandler.
  390 + * @param sql the SQL query to execute
  391 + * @param args arguments to bind to the query
  392 + * @param argTypes the SQL types of the arguments
  393 + * (constants from {@code java.sql.Types})
  394 + * @param rch a callback that will extract results, one row at a time
  395 + * @throws DataAccessException if the query fails
  396 + * @see java.sql.Types
  397 + */
  398 + void query(String sql, Object[] args, int[] argTypes, RowCallbackHandler rch, Long tenantId) throws DataAccessException;
  399 +
  400 + /**
  401 + * Query given SQL to create a prepared statement from SQL and a list of
  402 + * arguments to bind to the query, reading the ResultSet on a per-row basis
  403 + * with a RowCallbackHandler.
  404 + * @param sql the SQL query to execute
  405 + * @param args arguments to bind to the query
  406 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  407 + * may also contain {@link SqlParameterValue} objects which indicate not
  408 + * only the argument value but also the SQL type and optionally the scale
  409 + * @param rch a callback that will extract results, one row at a time
  410 + * @throws DataAccessException if the query fails
  411 + */
  412 + void query(String sql, Object[] args, RowCallbackHandler rch, Long tenantId) throws DataAccessException;
  413 +
  414 + /**
  415 + * Query given SQL to create a prepared statement from SQL and a list of
  416 + * arguments to bind to the query, reading the ResultSet on a per-row basis
  417 + * with a RowCallbackHandler.
  418 + * @param sql the SQL query to execute
  419 + * @param rch a callback that will extract results, one row at a time
  420 + * @param args arguments to bind to the query
  421 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  422 + * may also contain {@link SqlParameterValue} objects which indicate not
  423 + * only the argument value but also the SQL type and optionally the scale
  424 + * @throws DataAccessException if the query fails
  425 + * @since 3.0.1
  426 + */
  427 + void query(String sql, RowCallbackHandler rch, Long tenantId, @Nullable Object... args) throws DataAccessException;
  428 +
  429 + /**
  430 + * Query using a prepared statement, mapping each row to a result object
  431 + * via a RowMapper.
  432 + * <p>A PreparedStatementCreator can either be implemented directly or
  433 + * configured through a PreparedStatementCreatorFactory.
  434 + * @param psc a callback that creates a PreparedStatement given a Connection
  435 + * @param rowMapper a callback that will map one object per row
  436 + * @return the result List, containing mapped objects
  437 + * @throws DataAccessException if there is any problem
  438 + * @see PreparedStatementCreatorFactory
  439 + */
  440 + <T> List<T> query(PreparedStatementCreator psc, RowMapper<T> rowMapper, Long tenantId) throws DataAccessException;
  441 +
  442 + /**
  443 + * Query given SQL to create a prepared statement from SQL and a
  444 + * PreparedStatementSetter implementation that knows how to bind values
  445 + * to the query, mapping each row to a result object via a RowMapper.
  446 + * @param sql the SQL query to execute
  447 + * @param pss a callback that knows how to set values on the prepared statement.
  448 + * If this is {@code null}, the SQL will be assumed to contain no bind parameters.
  449 + * Even if there are no bind parameters, this callback may be used to set the
  450 + * fetch size and other performance options.
  451 + * @param rowMapper a callback that will map one object per row
  452 + * @return the result List, containing mapped objects
  453 + * @throws DataAccessException if the query fails
  454 + */
  455 + <T> List<T> query(String sql, @Nullable PreparedStatementSetter pss, RowMapper<T> rowMapper, Long tenantId) throws DataAccessException;
  456 +
  457 + /**
  458 + * Query given SQL to create a prepared statement from SQL and a list of
  459 + * arguments to bind to the query, mapping each row to a result object
  460 + * via a RowMapper.
  461 + * @param sql the SQL query to execute
  462 + * @param args arguments to bind to the query
  463 + * @param argTypes the SQL types of the arguments
  464 + * (constants from {@code java.sql.Types})
  465 + * @param rowMapper a callback that will map one object per row
  466 + * @return the result List, containing mapped objects
  467 + * @throws DataAccessException if the query fails
  468 + * @see java.sql.Types
  469 + */
  470 + <T> List<T> query(String sql, Object[] args, int[] argTypes, RowMapper<T> rowMapper, Long tenantId) throws DataAccessException;
  471 +
  472 + /**
  473 + * Query given SQL to create a prepared statement from SQL and a list of
  474 + * arguments to bind to the query, mapping each row to a result object
  475 + * via a RowMapper.
  476 + * @param sql the SQL query to execute
  477 + * @param args arguments to bind to the query
  478 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  479 + * may also contain {@link SqlParameterValue} objects which indicate not
  480 + * only the argument value but also the SQL type and optionally the scale
  481 + * @param rowMapper a callback that will map one object per row
  482 + * @return the result List, containing mapped objects
  483 + * @throws DataAccessException if the query fails
  484 + */
  485 + <T> List<T> query(String sql, Object[] args, RowMapper<T> rowMapper, Long tenantId) throws DataAccessException;
  486 +
  487 + /**
  488 + * Query given SQL to create a prepared statement from SQL and a list of
  489 + * arguments to bind to the query, mapping each row to a result object
  490 + * via a RowMapper.
  491 + * @param sql the SQL query to execute
  492 + * @param rowMapper a callback that will map one object per row
  493 + * @param args arguments to bind to the query
  494 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  495 + * may also contain {@link SqlParameterValue} objects which indicate not
  496 + * only the argument value but also the SQL type and optionally the scale
  497 + * @return the result List, containing mapped objects
  498 + * @throws DataAccessException if the query fails
  499 + * @since 3.0.1
  500 + */
  501 + <T> List<T> query(String sql, RowMapper<T> rowMapper, Long tenantId, @Nullable Object... args) throws DataAccessException;
  502 +
  503 + /**
  504 + * Query given SQL to create a prepared statement from SQL and a list
  505 + * of arguments to bind to the query, mapping a single result row to a
  506 + * result object via a RowMapper.
  507 + * @param sql the SQL query to execute
  508 + * @param args arguments to bind to the query
  509 + * (leaving it to the PreparedStatement to guess the corresponding SQL type)
  510 + * @param argTypes the SQL types of the arguments
  511 + * (constants from {@code java.sql.Types})
  512 + * @param rowMapper a callback that will map one object per row
  513 + * @return the single mapped object (may be {@code null} if the given
  514 + * {@link RowMapper} returned {@code} null)
  515 + * @throws IncorrectResultSizeDataAccessException if the query does not
  516 + * return exactly one row
  517 + * @throws DataAccessException if the query fails
  518 + */
  519 + @Nullable
  520 + <T> T queryForObject(String sql, Object[] args, int[] argTypes, RowMapper<T> rowMapper, Long tenantId)
  521 + throws DataAccessException;
  522 +
  523 + /**
  524 + * Query given SQL to create a prepared statement from SQL and a list
  525 + * of arguments to bind to the query, mapping a single result row to a
  526 + * result object via a RowMapper.
  527 + * @param sql the SQL query to execute
  528 + * @param args arguments to bind to the query
  529 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  530 + * may also contain {@link SqlParameterValue} objects which indicate not
  531 + * only the argument value but also the SQL type and optionally the scale
  532 + * @param rowMapper a callback that will map one object per row
  533 + * @return the single mapped object (may be {@code null} if the given
  534 + * {@link RowMapper} returned {@code} null)
  535 + * @throws IncorrectResultSizeDataAccessException if the query does not
  536 + * return exactly one row
  537 + * @throws DataAccessException if the query fails
  538 + */
  539 + @Nullable
  540 + <T> T queryForObject(String sql, Object[] args, RowMapper<T> rowMapper, Long tenantId) throws DataAccessException;
  541 +
  542 + /**
  543 + * Query given SQL to create a prepared statement from SQL and a list
  544 + * of arguments to bind to the query, mapping a single result row to a
  545 + * result object via a RowMapper.
  546 + * @param sql the SQL query to execute
  547 + * @param rowMapper a callback that will map one object per row
  548 + * @param args arguments to bind to the query
  549 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  550 + * may also contain {@link SqlParameterValue} objects which indicate not
  551 + * only the argument value but also the SQL type and optionally the scale
  552 + * @return the single mapped object (may be {@code null} if the given
  553 + * {@link RowMapper} returned {@code} null)
  554 + * @throws IncorrectResultSizeDataAccessException if the query does not
  555 + * return exactly one row
  556 + * @throws DataAccessException if the query fails
  557 + * @since 3.0.1
  558 + */
  559 + @Nullable
  560 + <T> T queryForObject(String sql, RowMapper<T> rowMapper, Long tenantId, @Nullable Object... args) throws DataAccessException;
  561 +
  562 + /**
  563 + * Query given SQL to create a prepared statement from SQL and a list of
  564 + * arguments to bind to the query, expecting a result object.
  565 + * <p>The query is expected to be a single row/single column query; the returned
  566 + * result will be directly mapped to the corresponding object type.
  567 + * @param sql the SQL query to execute
  568 + * @param args arguments to bind to the query
  569 + * @param argTypes the SQL types of the arguments
  570 + * (constants from {@code java.sql.Types})
  571 + * @param requiredType the type that the result object is expected to match
  572 + * @return the result object of the required type, or {@code null} in case of SQL NULL
  573 + * @throws IncorrectResultSizeDataAccessException if the query does not return
  574 + * exactly one row, or does not return exactly one column in that row
  575 + * @throws DataAccessException if the query fails
  576 + * @see #queryForObject(String, Class)
  577 + * @see java.sql.Types
  578 + */
  579 + @Nullable
  580 + <T> T queryForObject(String sql, Object[] args, int[] argTypes, Class<T> requiredType, Long tenantId)
  581 + throws DataAccessException;
  582 +
  583 + /**
  584 + * Query given SQL to create a prepared statement from SQL and a list of
  585 + * arguments to bind to the query, expecting a result object.
  586 + * <p>The query is expected to be a single row/single column query; the returned
  587 + * result will be directly mapped to the corresponding object type.
  588 + * @param sql the SQL query to execute
  589 + * @param args arguments to bind to the query
  590 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  591 + * may also contain {@link SqlParameterValue} objects which indicate not
  592 + * only the argument value but also the SQL type and optionally the scale
  593 + * @param requiredType the type that the result object is expected to match
  594 + * @return the result object of the required type, or {@code null} in case of SQL NULL
  595 + * @throws IncorrectResultSizeDataAccessException if the query does not return
  596 + * exactly one row, or does not return exactly one column in that row
  597 + * @throws DataAccessException if the query fails
  598 + * @see #queryForObject(String, Class)
  599 + */
  600 + @Nullable
  601 + <T> T queryForObject(String sql, Object[] args, Class<T> requiredType, Long tenantId) throws DataAccessException;
  602 +
  603 + /**
  604 + * Query given SQL to create a prepared statement from SQL and a list of
  605 + * arguments to bind to the query, expecting a result object.
  606 + * <p>The query is expected to be a single row/single column query; the returned
  607 + * result will be directly mapped to the corresponding object type.
  608 + * @param sql the SQL query to execute
  609 + * @param requiredType the type that the result object is expected to match
  610 + * @param args arguments to bind to the query
  611 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  612 + * may also contain {@link SqlParameterValue} objects which indicate not
  613 + * only the argument value but also the SQL type and optionally the scale
  614 + * @return the result object of the required type, or {@code null} in case of SQL NULL
  615 + * @throws IncorrectResultSizeDataAccessException if the query does not return
  616 + * exactly one row, or does not return exactly one column in that row
  617 + * @throws DataAccessException if the query fails
  618 + * @since 3.0.1
  619 + * @see #queryForObject(String, Class)
  620 + */
  621 + @Nullable
  622 + <T> T queryForObject(String sql, Class<T> requiredType, Long tenantId, @Nullable Object... args) throws DataAccessException;
  623 +
  624 + /**
  625 + * Query given SQL to create a prepared statement from SQL and a list of
  626 + * arguments to bind to the query, expecting a result map.
  627 + * <p>The query is expected to be a single row query; the result row will be
  628 + * mapped to a Map (one entry for each column, using the column name as the key).
  629 + * @param sql the SQL query to execute
  630 + * @param args arguments to bind to the query
  631 + * @param argTypes the SQL types of the arguments
  632 + * (constants from {@code java.sql.Types})
  633 + * @return the result Map (one entry per column, with column name as key)
  634 + * @throws IncorrectResultSizeDataAccessException if the query does not
  635 + * return exactly one row
  636 + * @throws DataAccessException if the query fails
  637 + * @see #queryForMap(String)
  638 + * @see ColumnMapRowMapper
  639 + * @see java.sql.Types
  640 + */
  641 + Map<String, Object> queryForMap(String sql, Object[] args, int[] argTypes, Long tenantId) throws DataAccessException;
  642 +
  643 + /**
  644 + * Query given SQL to create a prepared statement from SQL and a list of
  645 + * arguments to bind to the query, expecting a result map.
  646 + * <p>The {@code queryForMap} methods defined by this interface are appropriate
  647 + * when you don't have a domain model. Otherwise, consider using one of the
  648 + * {@code queryForObject} methods.
  649 + * <p>The query is expected to be a single row query; the result row will be
  650 + * mapped to a Map (one entry for each column, using the column name as the key).
  651 + * @param sql the SQL query to execute
  652 + * @param args arguments to bind to the query
  653 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  654 + * may also contain {@link SqlParameterValue} objects which indicate not
  655 + * only the argument value but also the SQL type and optionally the scale
  656 + * @return the result Map (one entry for each column, using the
  657 + * column name as the key)
  658 + * @throws IncorrectResultSizeDataAccessException if the query does not
  659 + * return exactly one row
  660 + * @throws DataAccessException if the query fails
  661 + * @see #queryForMap(String)
  662 + * @see ColumnMapRowMapper
  663 + */
  664 + Map<String, Object> queryForMap(String sql, Long tenantId, @Nullable Object... args) throws DataAccessException;
  665 +
  666 + /**
  667 + * Query given SQL to create a prepared statement from SQL and a list of
  668 + * arguments to bind to the query, expecting a result list.
  669 + * <p>The results will be mapped to a List (one entry for each row) of
  670 + * result objects, each of them matching the specified element type.
  671 + * @param sql the SQL query to execute
  672 + * @param args arguments to bind to the query
  673 + * @param argTypes the SQL types of the arguments
  674 + * (constants from {@code java.sql.Types})
  675 + * @param elementType the required type of element in the result list
  676 + * (for example, {@code Integer.class})
  677 + * @return a List of objects that match the specified element type
  678 + * @throws DataAccessException if the query fails
  679 + * @see #queryForList(String, Class)
  680 + * @see SingleColumnRowMapper
  681 + */
  682 + <T> List<T> queryForList(String sql, Object[] args, int[] argTypes, Class<T> elementType, Long tenantId)
  683 + throws DataAccessException;
  684 +
  685 + /**
  686 + * Query given SQL to create a prepared statement from SQL and a list of
  687 + * arguments to bind to the query, expecting a result list.
  688 + * <p>The results will be mapped to a List (one entry for each row) of
  689 + * result objects, each of them matching the specified element type.
  690 + * @param sql the SQL query to execute
  691 + * @param args arguments to bind to the query
  692 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  693 + * may also contain {@link SqlParameterValue} objects which indicate not
  694 + * only the argument value but also the SQL type and optionally the scale
  695 + * @param elementType the required type of element in the result list
  696 + * (for example, {@code Integer.class})
  697 + * @return a List of objects that match the specified element type
  698 + * @throws DataAccessException if the query fails
  699 + * @see #queryForList(String, Class)
  700 + * @see SingleColumnRowMapper
  701 + */
  702 + <T> List<T> queryForList(String sql, Object[] args, Class<T> elementType, Long tenantId) throws DataAccessException;
  703 +
  704 + /**
  705 + * Query given SQL to create a prepared statement from SQL and a list of
  706 + * arguments to bind to the query, expecting a result list.
  707 + * <p>The results will be mapped to a List (one entry for each row) of
  708 + * result objects, each of them matching the specified element type.
  709 + * @param sql the SQL query to execute
  710 + * @param elementType the required type of element in the result list
  711 + * (for example, {@code Integer.class})
  712 + * @param args arguments to bind to the query
  713 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  714 + * may also contain {@link SqlParameterValue} objects which indicate not
  715 + * only the argument value but also the SQL type and optionally the scale
  716 + * @return a List of objects that match the specified element type
  717 + * @throws DataAccessException if the query fails
  718 + * @since 3.0.1
  719 + * @see #queryForList(String, Class)
  720 + * @see SingleColumnRowMapper
  721 + */
  722 + <T> List<T> queryForList(String sql, Class<T> elementType, Long tenantId, @Nullable Object... args) throws DataAccessException;
  723 +
  724 + /**
  725 + * Query given SQL to create a prepared statement from SQL and a list of
  726 + * arguments to bind to the query, expecting a result list.
  727 + * <p>The results will be mapped to a List (one entry for each row) of
  728 + * Maps (one entry for each column, using the column name as the key).
  729 + * Each element in the list will be of the form returned by this interface's
  730 + * {@code queryForMap} methods.
  731 + * @param sql the SQL query to execute
  732 + * @param args arguments to bind to the query
  733 + * @param argTypes the SQL types of the arguments
  734 + * (constants from {@code java.sql.Types})
  735 + * @return a List that contains a Map per row
  736 + * @throws DataAccessException if the query fails
  737 + * @see #queryForList(String)
  738 + * @see java.sql.Types
  739 + */
  740 + List<Map<String, Object>> queryForList(String sql, Object[] args, int[] argTypes, Long tenantId) throws DataAccessException;
  741 +
  742 + /**
  743 + * Query given SQL to create a prepared statement from SQL and a list of
  744 + * arguments to bind to the query, expecting a result list.
  745 + * <p>The results will be mapped to a List (one entry for each row) of
  746 + * Maps (one entry for each column, using the column name as the key).
  747 + * Each element in the list will be of the form returned by this interface's
  748 + * {@code queryForMap} methods.
  749 + * @param sql the SQL query to execute
  750 + * @param args arguments to bind to the query
  751 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  752 + * may also contain {@link SqlParameterValue} objects which indicate not
  753 + * only the argument value but also the SQL type and optionally the scale
  754 + * @return a List that contains a Map per row
  755 + * @throws DataAccessException if the query fails
  756 + * @see #queryForList(String)
  757 + */
  758 + List<Map<String, Object>> queryForList(String sql, Long tenantId, @Nullable Object... args) throws DataAccessException;
  759 +
  760 + /**
  761 + * Query given SQL to create a prepared statement from SQL and a list of
  762 + * arguments to bind to the query, expecting a SqlRowSet.
  763 + * <p>The results will be mapped to an SqlRowSet which holds the data in a
  764 + * disconnected fashion. This wrapper will translate any SQLExceptions thrown.
  765 + * <p>Note that, for the default implementation, JDBC RowSet support needs to
  766 + * be available at runtime: by default, Sun's {@code com.sun.rowset.CachedRowSetImpl}
  767 + * class is used, which is part of JDK 1.5+ and also available separately as part of
  768 + * Sun's JDBC RowSet Implementations download (rowset.jar).
  769 + * @param sql the SQL query to execute
  770 + * @param args arguments to bind to the query
  771 + * @param argTypes the SQL types of the arguments
  772 + * (constants from {@code java.sql.Types})
  773 + * @return a SqlRowSet representation (possibly a wrapper around a
  774 + * {@code javax.sql.rowset.CachedRowSet})
  775 + * @throws DataAccessException if there is any problem executing the query
  776 + * @see #queryForRowSet(String)
  777 + * @see SqlRowSetResultSetExtractor
  778 + * @see javax.sql.rowset.CachedRowSet
  779 + * @see java.sql.Types
  780 + */
  781 + SqlRowSet queryForRowSet(String sql, Object[] args, int[] argTypes, Long tenantId) throws DataAccessException;
  782 +
  783 + /**
  784 + * Query given SQL to create a prepared statement from SQL and a list of
  785 + * arguments to bind to the query, expecting a SqlRowSet.
  786 + * <p>The results will be mapped to an SqlRowSet which holds the data in a
  787 + * disconnected fashion. This wrapper will translate any SQLExceptions thrown.
  788 + * <p>Note that, for the default implementation, JDBC RowSet support needs to
  789 + * be available at runtime: by default, Sun's {@code com.sun.rowset.CachedRowSetImpl}
  790 + * class is used, which is part of JDK 1.5+ and also available separately as part of
  791 + * Sun's JDBC RowSet Implementations download (rowset.jar).
  792 + * @param sql the SQL query to execute
  793 + * @param args arguments to bind to the query
  794 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  795 + * may also contain {@link SqlParameterValue} objects which indicate not
  796 + * only the argument value but also the SQL type and optionally the scale
  797 + * @return a SqlRowSet representation (possibly a wrapper around a
  798 + * {@code javax.sql.rowset.CachedRowSet})
  799 + * @throws DataAccessException if there is any problem executing the query
  800 + * @see #queryForRowSet(String)
  801 + * @see SqlRowSetResultSetExtractor
  802 + * @see javax.sql.rowset.CachedRowSet
  803 + */
  804 + SqlRowSet queryForRowSet(String sql, Long tenantId, @Nullable Object... args) throws DataAccessException;
  805 +
  806 + /**
  807 + * Issue a single SQL update operation (such as an insert, update or delete
  808 + * statement) using a PreparedStatementCreator to provide SQL and any
  809 + * required parameters.
  810 + * <p>A PreparedStatementCreator can either be implemented directly or
  811 + * configured through a PreparedStatementCreatorFactory.
  812 + * @param psc a callback that provides SQL and any necessary parameters
  813 + * @return the number of rows affected
  814 + * @throws DataAccessException if there is any problem issuing the update
  815 + * @see PreparedStatementCreatorFactory
  816 + */
  817 + int update(PreparedStatementCreator psc, Long tenantId) throws DataAccessException;
  818 +
  819 + /**
  820 + * Issue an update statement using a PreparedStatementCreator to provide SQL and
  821 + * any required parameters. Generated keys will be put into the given KeyHolder.
  822 + * <p>Note that the given PreparedStatementCreator has to create a statement
  823 + * with activated extraction of generated keys (a JDBC 3.0 feature). This can
  824 + * either be done directly or through using a PreparedStatementCreatorFactory.
  825 + * @param psc a callback that provides SQL and any necessary parameters
  826 + * @param generatedKeyHolder a KeyHolder that will hold the generated keys
  827 + * @return the number of rows affected
  828 + * @throws DataAccessException if there is any problem issuing the update
  829 + * @see PreparedStatementCreatorFactory
  830 + * @see org.springframework.jdbc.support.GeneratedKeyHolder
  831 + */
  832 + int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder, Long tenantId) throws DataAccessException;
  833 +
  834 + /**
  835 + * Issue an update statement using a PreparedStatementSetter to set bind parameters,
  836 + * with given SQL. Simpler than using a PreparedStatementCreator as this method
  837 + * will create the PreparedStatement: The PreparedStatementSetter just needs to
  838 + * set parameters.
  839 + * @param sql the SQL containing bind parameters
  840 + * @param pss helper that sets bind parameters. If this is {@code null}
  841 + * we run an update with static SQL.
  842 + * @return the number of rows affected
  843 + * @throws DataAccessException if there is any problem issuing the update
  844 + */
  845 + int update(String sql, @Nullable PreparedStatementSetter pss, Long tenantId) throws DataAccessException;
  846 +
  847 + /**
  848 + * Issue a single SQL update operation (such as an insert, update or delete statement)
  849 + * via a prepared statement, binding the given arguments.
  850 + * @param sql the SQL containing bind parameters
  851 + * @param args arguments to bind to the query
  852 + * @param argTypes the SQL types of the arguments
  853 + * (constants from {@code java.sql.Types})
  854 + * @return the number of rows affected
  855 + * @throws DataAccessException if there is any problem issuing the update
  856 + * @see java.sql.Types
  857 + */
  858 + int update(String sql, Object[] args, int[] argTypes, Long tenantId) throws DataAccessException;
  859 +
  860 + /**
  861 + * Issue a single SQL update operation (such as an insert, update or delete statement)
  862 + * via a prepared statement, binding the given arguments.
  863 + * @param sql the SQL containing bind parameters
  864 + * @param args arguments to bind to the query
  865 + * (leaving it to the PreparedStatement to guess the corresponding SQL type);
  866 + * may also contain {@link SqlParameterValue} objects which indicate not
  867 + * only the argument value but also the SQL type and optionally the scale
  868 + * @return the number of rows affected
  869 + * @throws DataAccessException if there is any problem issuing the update
  870 + */
  871 + int update(String sql, Long tenantId, @Nullable Object... args) throws DataAccessException;
  872 +
  873 + /**
  874 + * Issue multiple update statements on a single PreparedStatement,
  875 + * using batch updates and a BatchPreparedStatementSetter to set values.
  876 + * <p>Will fall back to separate updates on a single PreparedStatement
  877 + * if the JDBC driver does not support batch updates.
  878 + * @param sql defining PreparedStatement that will be reused.
  879 + * All statements in the batch will use the same SQL.
  880 + * @param pss object to set parameters on the PreparedStatement
  881 + * created by this method
  882 + * @return an array of the number of rows affected by each statement
  883 + * @throws DataAccessException if there is any problem issuing the update
  884 + */
  885 + int[] batchUpdate(String sql, BatchPreparedStatementSetter pss, Long tenantId) throws DataAccessException;
  886 +
  887 + /**
  888 + * Execute a batch using the supplied SQL statement with the batch of supplied arguments.
  889 + * @param sql the SQL statement to execute
  890 + * @param batchArgs the List of Object arrays containing the batch of arguments for the query
  891 + * @return an array containing the numbers of rows affected by each update in the batch
  892 + */
  893 + int[] batchUpdate(String sql, List<Object[]> batchArgs, Long tenantId) throws DataAccessException;
  894 +
  895 + /**
  896 + * Execute a batch using the supplied SQL statement with the batch of supplied arguments.
  897 + * @param sql the SQL statement to execute.
  898 + * @param batchArgs the List of Object arrays containing the batch of arguments for the query
  899 + * @param argTypes the SQL types of the arguments
  900 + * (constants from {@code java.sql.Types})
  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, int[] argTypes, Long tenantId) throws DataAccessException;
  904 +
  905 + /**
  906 + * Execute multiple batches using the supplied SQL statement with the collect of supplied arguments.
  907 + * The arguments' values will be set using the ParameterizedPreparedStatementSetter.
  908 + * Each batch should be of size indicated in 'batchSize'.
  909 + * @param sql the SQL statement to execute.
  910 + * @param batchArgs the List of Object arrays containing the batch of arguments for the query
  911 + * @param batchSize batch size
  912 + * @param pss the ParameterizedPreparedStatementSetter to use
  913 + * @return an array containing for each batch another array containing the numbers of rows affected
  914 + * by each update in the batch
  915 + * @since 3.1
  916 + */
  917 + <T> int[][] batchUpdate(String sql, Collection<T> batchArgs, int batchSize,
  918 + ParameterizedPreparedStatementSetter<T> pss, Long tenantId) throws DataAccessException;
  919 +
  920 +
  921 + //-------------------------------------------------------------------------
  922 + // Methods dealing with callable statements
  923 + //-------------------------------------------------------------------------
  924 +
  925 + /**
  926 + * Execute a JDBC data access operation, implemented as callback action
  927 + * working on a JDBC CallableStatement. This allows for implementing arbitrary
  928 + * data access operations on a single Statement, within Spring's managed JDBC
  929 + * environment: that is, participating in Spring-managed transactions and
  930 + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy.
  931 + * <p>The callback action can return a result object, for example a domain
  932 + * object or a collection of domain objects.
  933 + * @param csc a callback that creates a CallableStatement given a Connection
  934 + * @param action a callback that specifies the action
  935 + * @return a result object returned by the action, or {@code null} if none
  936 + * @throws DataAccessException if there is any problem
  937 + */
  938 + @Nullable
  939 + <T> T execute(CallableStatementCreator csc, CallableStatementCallback<T> action, Long tenantId) throws DataAccessException;
  940 +
  941 + /**
  942 + * Execute a JDBC data access operation, implemented as callback action
  943 + * working on a JDBC CallableStatement. This allows for implementing arbitrary
  944 + * data access operations on a single Statement, within Spring's managed JDBC
  945 + * environment: that is, participating in Spring-managed transactions and
  946 + * converting JDBC SQLExceptions into Spring's DataAccessException hierarchy.
  947 + * <p>The callback action can return a result object, for example a domain
  948 + * object or a collection of domain objects.
  949 + * @param callString the SQL call string to execute
  950 + * @param action a callback that specifies the action
  951 + * @return a result object returned by the action, or {@code null} if none
  952 + * @throws DataAccessException if there is any problem
  953 + */
  954 + @Nullable
  955 + <T> T execute(String callString, CallableStatementCallback<T> action, Long tenantId) throws DataAccessException;
  956 +
  957 + /**
  958 + * Execute a SQL call using a CallableStatementCreator to provide SQL and
  959 + * any required parameters.
  960 + * @param csc a callback that provides SQL and any necessary parameters
  961 + * @param declaredParameters list of declared SqlParameter objects
  962 + * @return a Map of extracted out parameters
  963 + * @throws DataAccessException if there is any problem issuing the update
  964 + */
  965 + Map<String, Object> call(CallableStatementCreator csc, List<SqlParameter> declaredParameters, Long tenantId) throws DataAccessException;
  966 +}
... ...
src/main/java/com/taover/repository/jdbctemplate/JdbcTemplateWrapperTenantImpl.java 0 → 100644
... ... @@ -0,0 +1,662 @@
  1 +package com.taover.repository.jdbctemplate;
  2 +
  3 +import java.util.Collection;
  4 +import java.util.List;
  5 +import java.util.Map;
  6 +import java.util.Map.Entry;
  7 +
  8 +import javax.annotation.Resource;
  9 +
  10 +import org.apache.shardingsphere.api.hint.HintManager;
  11 +import org.springframework.dao.DataAccessException;
  12 +import org.springframework.jdbc.core.BatchPreparedStatementSetter;
  13 +import org.springframework.jdbc.core.CallableStatementCallback;
  14 +import org.springframework.jdbc.core.CallableStatementCreator;
  15 +import org.springframework.jdbc.core.ConnectionCallback;
  16 +import org.springframework.jdbc.core.JdbcTemplate;
  17 +import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter;
  18 +import org.springframework.jdbc.core.PreparedStatementCallback;
  19 +import org.springframework.jdbc.core.PreparedStatementCreator;
  20 +import org.springframework.jdbc.core.PreparedStatementSetter;
  21 +import org.springframework.jdbc.core.ResultSetExtractor;
  22 +import org.springframework.jdbc.core.RowCallbackHandler;
  23 +import org.springframework.jdbc.core.RowMapper;
  24 +import org.springframework.jdbc.core.SqlParameter;
  25 +import org.springframework.jdbc.core.StatementCallback;
  26 +import org.springframework.jdbc.support.KeyHolder;
  27 +import org.springframework.jdbc.support.rowset.SqlRowSet;
  28 +
  29 +import com.taover.repository.shardingsphere.ShardingSphereService;
  30 +
  31 +public class JdbcTemplateWrapperTenantImpl implements JdbcTemplateWrapperTenant {
  32 + @Resource
  33 + private JdbcTemplate jdbcTemplate;
  34 + @Resource
  35 + private ShardingSphereService shardingSphereService;
  36 +
  37 + private void loadShardingInfo(Long tenantId) {
  38 + Map<String, String> shardingInfo = this.shardingSphereService.getShardingInfoMapByTenantId(tenantId);
  39 + if(shardingInfo == null || shardingInfo.isEmpty()) {
  40 + return;
  41 + }
  42 + HintManager.clear();
  43 + for(Entry<String, String> item: shardingInfo.entrySet()) {
  44 + HintManager.getInstance().addTableShardingValue(item.getKey(), item.getValue());
  45 + }
  46 + }
  47 +
  48 + private void clearShardingInfo() {
  49 + HintManager.clear();
  50 + }
  51 +
  52 + @Override
  53 + public <E> E execute(ConnectionCallback<E> action, Long tenantId) throws DataAccessException {
  54 + try {
  55 + this.loadShardingInfo(tenantId);
  56 + return this.jdbcTemplate.execute(action);
  57 + }finally {
  58 + this.clearShardingInfo();
  59 + }
  60 + }
  61 +
  62 + @Override
  63 + public <E> E execute(StatementCallback<E> action, Long tenantId) throws DataAccessException {
  64 + try {
  65 + this.loadShardingInfo(tenantId);
  66 + return this.jdbcTemplate.execute(action);
  67 + }finally {
  68 + this.clearShardingInfo();
  69 + }
  70 + }
  71 +
  72 + @Override
  73 + public void execute(String sql, Long tenantId) throws DataAccessException {
  74 + try {
  75 + this.loadShardingInfo(tenantId);
  76 + this.jdbcTemplate.execute(sql);
  77 + }finally {
  78 + this.clearShardingInfo();
  79 + }
  80 + }
  81 +
  82 + @Override
  83 + public <E> E query(String sql, ResultSetExtractor<E> rse, Long tenantId) throws DataAccessException {
  84 + try {
  85 + this.loadShardingInfo(tenantId);
  86 + return this.jdbcTemplate.query(sql, rse);
  87 + }finally {
  88 + this.clearShardingInfo();
  89 + }
  90 + }
  91 +
  92 + @Override
  93 + public void query(String sql, RowCallbackHandler rch, Long tenantId) throws DataAccessException {
  94 + try {
  95 + this.loadShardingInfo(tenantId);
  96 + this.jdbcTemplate.query(sql, rch);
  97 + }finally {
  98 + this.clearShardingInfo();
  99 + }
  100 + }
  101 +
  102 + @Override
  103 + public <E> List<E> query(String sql, RowMapper<E> rowMapper, Long tenantId) throws DataAccessException {
  104 + try {
  105 + this.loadShardingInfo(tenantId);
  106 + return this.jdbcTemplate.query(sql, rowMapper);
  107 + }finally {
  108 + this.clearShardingInfo();
  109 + }
  110 + }
  111 +
  112 + @Override
  113 + public <E> E queryForObject(String sql, RowMapper<E> rowMapper, Long tenantId) throws DataAccessException {
  114 + try {
  115 + this.loadShardingInfo(tenantId);
  116 + return this.jdbcTemplate.queryForObject(sql, rowMapper);
  117 + }finally {
  118 + this.clearShardingInfo();
  119 + }
  120 + }
  121 +
  122 + @Override
  123 + public <E> E queryForObject(String sql, Class<E> requiredType, Long tenantId) throws DataAccessException {
  124 + try {
  125 + this.loadShardingInfo(tenantId);
  126 + return this.jdbcTemplate.queryForObject(sql, requiredType);
  127 + }finally {
  128 + this.clearShardingInfo();
  129 + }
  130 + }
  131 +
  132 + @Override
  133 + public Map<String, Object> queryForMap(String sql, Long tenantId) throws DataAccessException {
  134 + try {
  135 + this.loadShardingInfo(tenantId);
  136 + return this.jdbcTemplate.queryForMap(sql);
  137 + }finally {
  138 + this.clearShardingInfo();
  139 + }
  140 + }
  141 +
  142 + @Override
  143 + public <E> List<E> queryForList(String sql, Class<E> elementType, Long tenantId) throws DataAccessException {
  144 + try {
  145 + this.loadShardingInfo(tenantId);
  146 + return this.jdbcTemplate.queryForList(sql, elementType);
  147 + }finally {
  148 + this.clearShardingInfo();
  149 + }
  150 + }
  151 +
  152 + @Override
  153 + public List<Map<String, Object>> queryForList(String sql, Long tenantId) throws DataAccessException {
  154 + try {
  155 + this.loadShardingInfo(tenantId);
  156 + return this.jdbcTemplate.queryForList(sql);
  157 + }finally {
  158 + this.clearShardingInfo();
  159 + }
  160 + }
  161 +
  162 + @Override
  163 + public SqlRowSet queryForRowSet(String sql, Long tenantId) throws DataAccessException {
  164 + try {
  165 + this.loadShardingInfo(tenantId);
  166 + return this.jdbcTemplate.queryForRowSet(sql);
  167 + }finally {
  168 + this.clearShardingInfo();
  169 + }
  170 + }
  171 +
  172 + @Override
  173 + public int update(String sql, Long tenantId) throws DataAccessException {
  174 + try {
  175 + this.loadShardingInfo(tenantId);
  176 + return this.jdbcTemplate.update(sql);
  177 + }finally {
  178 + this.clearShardingInfo();
  179 + }
  180 + }
  181 +
  182 + @Override
  183 + public int[] batchUpdate(Long tenantId, String... sql) throws DataAccessException {
  184 + try {
  185 + this.loadShardingInfo(tenantId);
  186 + return this.jdbcTemplate.batchUpdate(sql);
  187 + }finally {
  188 + this.clearShardingInfo();
  189 + }
  190 + }
  191 +
  192 + @Override
  193 + public <E> E execute(PreparedStatementCreator psc, PreparedStatementCallback<E> action, Long tenantId)
  194 + throws DataAccessException {
  195 + try {
  196 + this.loadShardingInfo(tenantId);
  197 + return this.jdbcTemplate.execute(psc, action);
  198 + }finally {
  199 + this.clearShardingInfo();
  200 + }
  201 + }
  202 +
  203 + @Override
  204 + public <E> E execute(String sql, PreparedStatementCallback<E> action, Long tenantId) throws DataAccessException {
  205 + try {
  206 + this.loadShardingInfo(tenantId);
  207 + return this.jdbcTemplate.execute(sql, action);
  208 + }finally {
  209 + this.clearShardingInfo();
  210 + }
  211 + }
  212 +
  213 + @Override
  214 + public <E> E query(PreparedStatementCreator psc, ResultSetExtractor<E> rse, Long tenantId)
  215 + throws DataAccessException {
  216 + try {
  217 + this.loadShardingInfo(tenantId);
  218 + return this.jdbcTemplate.query(psc, rse);
  219 + }finally {
  220 + this.clearShardingInfo();
  221 + }
  222 + }
  223 +
  224 + @Override
  225 + public <E> E query(String sql, PreparedStatementSetter pss, ResultSetExtractor<E> rse, Long tenantId)
  226 + throws DataAccessException {
  227 + try {
  228 + this.loadShardingInfo(tenantId);
  229 + return this.jdbcTemplate.query(sql, pss, rse);
  230 + }finally {
  231 + this.clearShardingInfo();
  232 + }
  233 + }
  234 +
  235 + @Override
  236 + public <E> E query(String sql, Object[] args, int[] argTypes, ResultSetExtractor<E> rse, Long tenantId)
  237 + throws DataAccessException {
  238 + try {
  239 + this.loadShardingInfo(tenantId);
  240 + return this.jdbcTemplate.query(sql, args, argTypes, rse);
  241 + }finally {
  242 + this.clearShardingInfo();
  243 + }
  244 + }
  245 +
  246 + @Override
  247 + public <E> E query(String sql, Object[] args, ResultSetExtractor<E> rse, Long tenantId) throws DataAccessException {
  248 + try {
  249 + this.loadShardingInfo(tenantId);
  250 + return this.jdbcTemplate.query(sql, args, rse);
  251 + }finally {
  252 + this.clearShardingInfo();
  253 + }
  254 + }
  255 +
  256 + @Override
  257 + public <E> E query(String sql, ResultSetExtractor<E> rse, Long tenantId, Object... args)
  258 + throws DataAccessException {
  259 + try {
  260 + this.loadShardingInfo(tenantId);
  261 + return this.jdbcTemplate.query(sql, rse, args);
  262 + }finally {
  263 + this.clearShardingInfo();
  264 + }
  265 + }
  266 +
  267 + @Override
  268 + public void query(PreparedStatementCreator psc, RowCallbackHandler rch, Long tenantId) throws DataAccessException {
  269 + try {
  270 + this.loadShardingInfo(tenantId);
  271 + this.jdbcTemplate.query(psc, rch);
  272 + }finally {
  273 + this.clearShardingInfo();
  274 + }
  275 + }
  276 +
  277 + @Override
  278 + public void query(String sql, PreparedStatementSetter pss, RowCallbackHandler rch, Long tenantId)
  279 + throws DataAccessException {
  280 + try {
  281 + this.loadShardingInfo(tenantId);
  282 + this.jdbcTemplate.query(sql, pss, rch);
  283 + }finally {
  284 + this.clearShardingInfo();
  285 + }
  286 + }
  287 +
  288 + @Override
  289 + public void query(String sql, Object[] args, int[] argTypes, RowCallbackHandler rch, Long tenantId)
  290 + throws DataAccessException {
  291 + try {
  292 + this.loadShardingInfo(tenantId);
  293 + this.jdbcTemplate.query(sql, args, argTypes, rch);
  294 + }finally {
  295 + this.clearShardingInfo();
  296 + }
  297 + }
  298 +
  299 + @Override
  300 + public void query(String sql, Object[] args, RowCallbackHandler rch, Long tenantId) throws DataAccessException {
  301 + try {
  302 + this.loadShardingInfo(tenantId);
  303 + this.jdbcTemplate.query(sql, args, rch);
  304 + }finally {
  305 + this.clearShardingInfo();
  306 + }
  307 + }
  308 +
  309 + @Override
  310 + public void query(String sql, RowCallbackHandler rch, Long tenantId, Object... args) throws DataAccessException {
  311 + try {
  312 + this.loadShardingInfo(tenantId);
  313 + this.jdbcTemplate.query(sql, rch, args);
  314 + }finally {
  315 + this.clearShardingInfo();
  316 + }
  317 + }
  318 +
  319 + @Override
  320 + public <E> List<E> query(PreparedStatementCreator psc, RowMapper<E> rowMapper, Long tenantId)
  321 + throws DataAccessException {
  322 + try {
  323 + this.loadShardingInfo(tenantId);
  324 + return this.jdbcTemplate.query(psc, rowMapper);
  325 + }finally {
  326 + this.clearShardingInfo();
  327 + }
  328 + }
  329 +
  330 + @Override
  331 + public <E> List<E> query(String sql, PreparedStatementSetter pss, RowMapper<E> rowMapper, Long tenantId)
  332 + throws DataAccessException {
  333 + try {
  334 + this.loadShardingInfo(tenantId);
  335 + return this.jdbcTemplate.query(sql, pss, rowMapper);
  336 + }finally {
  337 + this.clearShardingInfo();
  338 + }
  339 + }
  340 +
  341 + @Override
  342 + public <E> List<E> query(String sql, Object[] args, int[] argTypes, RowMapper<E> rowMapper, Long tenantId)
  343 + throws DataAccessException {
  344 + try {
  345 + this.loadShardingInfo(tenantId);
  346 + return this.jdbcTemplate.query(sql, args, argTypes, rowMapper);
  347 + }finally {
  348 + this.clearShardingInfo();
  349 + }
  350 + }
  351 +
  352 + @Override
  353 + public <E> List<E> query(String sql, Object[] args, RowMapper<E> rowMapper, Long tenantId)
  354 + throws DataAccessException {
  355 + try {
  356 + this.loadShardingInfo(tenantId);
  357 + return this.jdbcTemplate.query(sql, args, rowMapper);
  358 + }finally {
  359 + this.clearShardingInfo();
  360 + }
  361 + }
  362 +
  363 + @Override
  364 + public <E> List<E> query(String sql, RowMapper<E> rowMapper, Long tenantId, Object... args)
  365 + throws DataAccessException {
  366 + try {
  367 + this.loadShardingInfo(tenantId);
  368 + return this.jdbcTemplate.query(sql, rowMapper, args);
  369 + }finally {
  370 + this.clearShardingInfo();
  371 + }
  372 + }
  373 +
  374 + @Override
  375 + public <E> E queryForObject(String sql, Object[] args, int[] argTypes, RowMapper<E> rowMapper, Long tenantId)
  376 + throws DataAccessException {
  377 + try {
  378 + this.loadShardingInfo(tenantId);
  379 + return this.jdbcTemplate.queryForObject(sql, args, argTypes, rowMapper);
  380 + }finally {
  381 + this.clearShardingInfo();
  382 + }
  383 + }
  384 +
  385 + @Override
  386 + public <E> E queryForObject(String sql, Object[] args, RowMapper<E> rowMapper, Long tenantId)
  387 + throws DataAccessException {
  388 + try {
  389 + this.loadShardingInfo(tenantId);
  390 + return this.jdbcTemplate.queryForObject(sql, args, rowMapper);
  391 + }finally {
  392 + this.clearShardingInfo();
  393 + }
  394 + }
  395 +
  396 + @Override
  397 + public <E> E queryForObject(String sql, RowMapper<E> rowMapper, Long tenantId, Object... args)
  398 + throws DataAccessException {
  399 + try {
  400 + this.loadShardingInfo(tenantId);
  401 + return this.jdbcTemplate.queryForObject(sql, rowMapper, args);
  402 + }finally {
  403 + this.clearShardingInfo();
  404 + }
  405 + }
  406 +
  407 + @Override
  408 + public <E> E queryForObject(String sql, Object[] args, int[] argTypes, Class<E> requiredType, Long tenantId)
  409 + throws DataAccessException {
  410 + try {
  411 + this.loadShardingInfo(tenantId);
  412 + return this.jdbcTemplate.queryForObject(sql, args, argTypes, requiredType);
  413 + }finally {
  414 + this.clearShardingInfo();
  415 + }
  416 + }
  417 +
  418 + @Override
  419 + public <E> E queryForObject(String sql, Object[] args, Class<E> requiredType, Long tenantId)
  420 + throws DataAccessException {
  421 + try {
  422 + this.loadShardingInfo(tenantId);
  423 + return this.jdbcTemplate.queryForObject(sql, args, requiredType);
  424 + }finally {
  425 + this.clearShardingInfo();
  426 + }
  427 + }
  428 +
  429 + @Override
  430 + public <E> E queryForObject(String sql, Class<E> requiredType, Long tenantId, Object... args)
  431 + throws DataAccessException {
  432 + try {
  433 + this.loadShardingInfo(tenantId);
  434 + return this.jdbcTemplate.queryForObject(sql, requiredType, args);
  435 + }finally {
  436 + this.clearShardingInfo();
  437 + }
  438 + }
  439 +
  440 + @Override
  441 + public Map<String, Object> queryForMap(String sql, Object[] args, int[] argTypes, Long tenantId)
  442 + throws DataAccessException {
  443 + try {
  444 + this.loadShardingInfo(tenantId);
  445 + return this.jdbcTemplate.queryForMap(sql, args, argTypes);
  446 + }finally {
  447 + this.clearShardingInfo();
  448 + }
  449 + }
  450 +
  451 + @Override
  452 + public Map<String, Object> queryForMap(String sql, Long tenantId, Object... args) throws DataAccessException {
  453 + try {
  454 + this.loadShardingInfo(tenantId);
  455 + return this.jdbcTemplate.queryForMap(sql, args);
  456 + }finally {
  457 + this.clearShardingInfo();
  458 + }
  459 + }
  460 +
  461 + @Override
  462 + public <E> List<E> queryForList(String sql, Object[] args, int[] argTypes, Class<E> elementType, Long tenantId)
  463 + throws DataAccessException {
  464 + try {
  465 + this.loadShardingInfo(tenantId);
  466 + return this.jdbcTemplate.queryForList(sql, args, argTypes, elementType);
  467 + }finally {
  468 + this.clearShardingInfo();
  469 + }
  470 + }
  471 +
  472 + @Override
  473 + public <E> List<E> queryForList(String sql, Object[] args, Class<E> elementType, Long tenantId)
  474 + throws DataAccessException {
  475 + try {
  476 + this.loadShardingInfo(tenantId);
  477 + return this.jdbcTemplate.queryForList(sql, args, elementType);
  478 + }finally {
  479 + this.clearShardingInfo();
  480 + }
  481 + }
  482 +
  483 + @Override
  484 + public <E> List<E> queryForList(String sql, Class<E> elementType, Long tenantId, Object... args)
  485 + throws DataAccessException {
  486 + try {
  487 + this.loadShardingInfo(tenantId);
  488 + return this.jdbcTemplate.queryForList(sql, elementType, args);
  489 + }finally {
  490 + this.clearShardingInfo();
  491 + }
  492 + }
  493 +
  494 + @Override
  495 + public List<Map<String, Object>> queryForList(String sql, Object[] args, int[] argTypes, Long tenantId)
  496 + throws DataAccessException {
  497 + try {
  498 + this.loadShardingInfo(tenantId);
  499 + return this.jdbcTemplate.queryForList(sql, args, argTypes);
  500 + }finally {
  501 + this.clearShardingInfo();
  502 + }
  503 + }
  504 +
  505 + @Override
  506 + public List<Map<String, Object>> queryForList(String sql, Long tenantId, Object... args)
  507 + throws DataAccessException {
  508 + try {
  509 + this.loadShardingInfo(tenantId);
  510 + return this.jdbcTemplate.queryForList(sql, args);
  511 + }finally {
  512 + this.clearShardingInfo();
  513 + }
  514 + }
  515 +
  516 + @Override
  517 + public SqlRowSet queryForRowSet(String sql, Object[] args, int[] argTypes, Long tenantId)
  518 + throws DataAccessException {
  519 + try {
  520 + this.loadShardingInfo(tenantId);
  521 + return this.jdbcTemplate.queryForRowSet(sql, args, argTypes);
  522 + }finally {
  523 + this.clearShardingInfo();
  524 + }
  525 + }
  526 +
  527 + @Override
  528 + public SqlRowSet queryForRowSet(String sql, Long tenantId, Object... args) throws DataAccessException {
  529 + try {
  530 + this.loadShardingInfo(tenantId);
  531 + return this.jdbcTemplate.queryForRowSet(sql, args);
  532 + }finally {
  533 + this.clearShardingInfo();
  534 + }
  535 + }
  536 +
  537 + @Override
  538 + public int update(PreparedStatementCreator psc, Long tenantId) throws DataAccessException {
  539 + try {
  540 + this.loadShardingInfo(tenantId);
  541 + return this.jdbcTemplate.update(psc);
  542 + }finally {
  543 + this.clearShardingInfo();
  544 + }
  545 + }
  546 +
  547 + @Override
  548 + public int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder, Long tenantId)
  549 + throws DataAccessException {
  550 + try {
  551 + this.loadShardingInfo(tenantId);
  552 + return this.jdbcTemplate.update(psc, generatedKeyHolder);
  553 + }finally {
  554 + this.clearShardingInfo();
  555 + }
  556 + }
  557 +
  558 + @Override
  559 + public int update(String sql, PreparedStatementSetter pss, Long tenantId) throws DataAccessException {
  560 + try {
  561 + this.loadShardingInfo(tenantId);
  562 + return this.jdbcTemplate.update(sql, pss);
  563 + }finally {
  564 + this.clearShardingInfo();
  565 + }
  566 + }
  567 +
  568 + @Override
  569 + public int update(String sql, Object[] args, int[] argTypes, Long tenantId) throws DataAccessException {
  570 + try {
  571 + this.loadShardingInfo(tenantId);
  572 + return this.jdbcTemplate.update(sql, args, argTypes);
  573 + }finally {
  574 + this.clearShardingInfo();
  575 + }
  576 + }
  577 +
  578 + @Override
  579 + public int update(String sql, Long tenantId, Object... args) throws DataAccessException {
  580 + try {
  581 + this.loadShardingInfo(tenantId);
  582 + return this.jdbcTemplate.update(sql, args);
  583 + }finally {
  584 + this.clearShardingInfo();
  585 + }
  586 + }
  587 +
  588 + @Override
  589 + public int[] batchUpdate(String sql, BatchPreparedStatementSetter pss, Long tenantId) throws DataAccessException {
  590 + try {
  591 + this.loadShardingInfo(tenantId);
  592 + return this.jdbcTemplate.batchUpdate(sql, pss);
  593 + }finally {
  594 + this.clearShardingInfo();
  595 + }
  596 + }
  597 +
  598 + @Override
  599 + public int[] batchUpdate(String sql, List<Object[]> batchArgs, Long tenantId) throws DataAccessException {
  600 + try {
  601 + this.loadShardingInfo(tenantId);
  602 + return this.jdbcTemplate.batchUpdate(sql, batchArgs);
  603 + }finally {
  604 + this.clearShardingInfo();
  605 + }
  606 + }
  607 +
  608 + @Override
  609 + public int[] batchUpdate(String sql, List<Object[]> batchArgs, int[] argTypes, Long tenantId)
  610 + throws DataAccessException {
  611 + try {
  612 + this.loadShardingInfo(tenantId);
  613 + return this.jdbcTemplate.batchUpdate(sql, batchArgs);
  614 + }finally {
  615 + this.clearShardingInfo();
  616 + }
  617 + }
  618 +
  619 + @Override
  620 + public <E> int[][] batchUpdate(String sql, Collection<E> batchArgs, int batchSize,
  621 + ParameterizedPreparedStatementSetter<E> pss, Long tenantId) throws DataAccessException {
  622 + try {
  623 + this.loadShardingInfo(tenantId);
  624 + return this.jdbcTemplate.batchUpdate(sql, batchArgs, batchSize, pss);
  625 + }finally {
  626 + this.clearShardingInfo();
  627 + }
  628 + }
  629 +
  630 + @Override
  631 + public <E> E execute(CallableStatementCreator csc, CallableStatementCallback<E> action, Long tenantId)
  632 + throws DataAccessException {
  633 + try {
  634 + this.loadShardingInfo(tenantId);
  635 + return this.jdbcTemplate.execute(csc, action);
  636 + }finally {
  637 + this.clearShardingInfo();
  638 + }
  639 + }
  640 +
  641 + @Override
  642 + public <E> E execute(String callString, CallableStatementCallback<E> action, Long tenantId)
  643 + throws DataAccessException {
  644 + try {
  645 + this.loadShardingInfo(tenantId);
  646 + return this.jdbcTemplate.execute(callString, action);
  647 + }finally {
  648 + this.clearShardingInfo();
  649 + }
  650 + }
  651 +
  652 + @Override
  653 + public Map<String, Object> call(CallableStatementCreator csc, List<SqlParameter> declaredParameters, Long tenantId)
  654 + throws DataAccessException {
  655 + try {
  656 + this.loadShardingInfo(tenantId);
  657 + return this.jdbcTemplate.call(csc, declaredParameters);
  658 + }finally {
  659 + this.clearShardingInfo();
  660 + }
  661 + }
  662 +}
... ...
src/main/java/com/taover/repository/shardingsphere/ShardingAlgorithmHint.java 0 → 100644
... ... @@ -0,0 +1,33 @@
  1 +package com.taover.repository.shardingsphere;
  2 +
  3 +import java.util.Collection;
  4 +import java.util.HashSet;
  5 +import java.util.Set;
  6 +
  7 +import org.apache.commons.logging.Log;
  8 +import org.apache.commons.logging.LogFactory;
  9 +import org.apache.shardingsphere.api.sharding.hint.HintShardingAlgorithm;
  10 +import org.apache.shardingsphere.api.sharding.hint.HintShardingValue;
  11 +
  12 +public class ShardingAlgorithmHint implements HintShardingAlgorithm<String> {
  13 + Log log = LogFactory.getLog(ShardingAlgorithmHint.class);
  14 +
  15 + public ShardingAlgorithmHint() {
  16 + System.out.println("ShardingAlgorithmHint()");
  17 + }
  18 +
  19 + @Override
  20 + public Collection<String> doSharding(Collection<String> availableTargetNames, HintShardingValue<String> shardingValue) {
  21 + Collection<String> values = shardingValue.getValues();
  22 + if(values == null || values.isEmpty()) {
  23 + String message = shardingValue.getLogicTableName()+"已启用分库分表,SQL语句请指定tenant_id 或 使用封装好的DAO层方法";
  24 + log.error(message);
  25 + throw new RuntimeException(message);
  26 + }
  27 + Set<String> result = new HashSet<String>(availableTargetNames);
  28 + for(String item: values) {
  29 + result.add(shardingValue.getLogicTableName()+item);
  30 + }
  31 + return result;
  32 + }
  33 +}
... ...
src/main/java/com/taover/repository/shardingsphere/ShardingInfoEntity.java 0 → 100644
... ... @@ -0,0 +1,106 @@
  1 +package com.taover.repository.shardingsphere;
  2 +
  3 +import java.io.Serializable;
  4 +import java.math.BigDecimal;
  5 +import java.sql.Timestamp;
  6 +import java.util.Date;
  7 +
  8 +import javax.persistence.Entity;
  9 +import javax.persistence.Table;
  10 +import javax.persistence.Id;
  11 +import javax.persistence.Column;
  12 +
  13 +/**
  14 + * @version 1.0.0
  15 + */
  16 +@Entity
  17 +@Table(name="sharding_info", catalog="")
  18 +public class ShardingInfoEntity implements Serializable {
  19 +
  20 + private static final long serialVersionUID = 1L;
  21 +
  22 +
  23 + /**
  24 + *
  25 + */
  26 + @Id
  27 + @Column(name="id")
  28 + private java.lang.Long id;
  29 +
  30 + public java.lang.Long getId(){
  31 + return id;
  32 + }
  33 + public void setId(java.lang.Long id){
  34 + this.id = id;
  35 + }
  36 +
  37 + /**
  38 + * 表名
  39 + */
  40 + @Column(name="table_name")
  41 + private java.lang.String tableName;
  42 +
  43 + public java.lang.String getTableName(){
  44 + return tableName;
  45 + }
  46 + public void setTableName(java.lang.String tableName){
  47 + this.tableName = tableName;
  48 + }
  49 +
  50 + /**
  51 + * 租户ID
  52 + */
  53 + @Column(name="tenant_id")
  54 + private java.lang.Long tenantId;
  55 +
  56 + public java.lang.Long getTenantId(){
  57 + return tenantId;
  58 + }
  59 + public void setTenantId(java.lang.Long tenantId){
  60 + this.tenantId = tenantId;
  61 + }
  62 +
  63 + /**
  64 + * 后缀
  65 + */
  66 + @Column(name="sharding_suffix")
  67 + private java.lang.String shardingSuffix;
  68 +
  69 + public java.lang.String getShardingSuffix(){
  70 + return shardingSuffix;
  71 + }
  72 + public void setShardingSuffix(java.lang.String shardingSuffix){
  73 + this.shardingSuffix = shardingSuffix;
  74 + }
  75 +
  76 + /**
  77 + *
  78 + */
  79 + @Column(name="create_time")
  80 + private java.sql.Timestamp createTime;
  81 +
  82 + public java.sql.Timestamp getCreateTime(){
  83 + return createTime;
  84 + }
  85 + public void setCreateTime(java.sql.Timestamp createTime){
  86 + this.createTime = createTime;
  87 + }
  88 +
  89 + /**
  90 + *
  91 + */
  92 + @Column(name="update_time")
  93 + private java.sql.Timestamp updateTime;
  94 +
  95 + public java.sql.Timestamp getUpdateTime(){
  96 + return updateTime;
  97 + }
  98 + public void setUpdateTime(java.sql.Timestamp updateTime){
  99 + this.updateTime = updateTime;
  100 + }
  101 +
  102 + @Override
  103 + public String toString() {
  104 + return "ShardingInfoEntity: [id="+id+",tableName="+tableName+",tenantId="+tenantId+",shardingSuffix="+shardingSuffix+",createTime="+createTime+",updateTime="+updateTime+"]";
  105 + }
  106 + }
... ...
src/main/java/com/taover/repository/shardingsphere/ShardingInfoRepository.java 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +package com.taover.repository.shardingsphere;
  2 +
  3 +import com.taover.repository.CustomJdbcTemplate;
  4 +
  5 +public class ShardingInfoRepository extends CustomJdbcTemplate<ShardingInfoEntity, Long>{
  6 +
  7 + public ShardingInfoRepository() throws Exception {
  8 + super();
  9 + }
  10 +
  11 +}
... ...
src/main/java/com/taover/repository/shardingsphere/ShardingKeyGeneratorExt.java 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +package com.taover.repository.shardingsphere;
  2 +
  3 +import java.util.List;
  4 +
  5 +import com.taover.repository.autoconfigure.ShardingSphereKeyGeneratorConfiguration;
  6 +
  7 +public interface ShardingKeyGeneratorExt {
  8 + /**
  9 + * 生成ID List
  10 + * @param shardingOffset 分片索引
  11 + * @param genNum 生成数量
  12 + * @return
  13 + */
  14 + List<Long> generateKeyList(int genNum);
  15 +
  16 + /**
  17 + * 设置属性值
  18 + * @param config
  19 + */
  20 + void loalConfig(ShardingSphereKeyGeneratorConfiguration config);
  21 +}
... ...
src/main/java/com/taover/repository/shardingsphere/ShardingKeyGeneratorImpl.java 0 → 100644
... ... @@ -0,0 +1,212 @@
  1 +package com.taover.repository.shardingsphere;
  2 +/*
  3 + * Licensed to the Apache Software Foundation (ASF) under one or more
  4 + * contributor license agreements. See the NOTICE file distributed with
  5 + * this work for additional information regarding copyright ownership.
  6 + * The ASF licenses this file to You under the Apache License, Version 2.0
  7 + * (the "License"); you may not use this file except in compliance with
  8 + * the License. You may obtain a copy of the License at
  9 + *
  10 + * http://www.apache.org/licenses/LICENSE-2.0
  11 + *
  12 + * Unless required by applicable law or agreed to in writing, software
  13 + * distributed under the License is distributed on an "AS IS" BASIS,
  14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15 + * See the License for the specific language governing permissions and
  16 + * limitations under the License.
  17 + */
  18 +
  19 +import java.util.ArrayList;
  20 +import java.util.Calendar;
  21 +import java.util.List;
  22 +import java.util.Properties;
  23 +
  24 +import org.apache.shardingsphere.core.strategy.keygen.TimeService;
  25 +import org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator;
  26 +
  27 +import com.google.common.base.Preconditions;
  28 +import com.taover.repository.autoconfigure.ShardingSphereKeyGeneratorConfiguration;
  29 +
  30 +/**
  31 + * Snowflake distributed primary key generator.
  32 + *
  33 + * <p>
  34 + * Use snowflake algorithm. Length is 64 bit.
  35 + * </p>
  36 + *
  37 + * <pre>
  38 + * 1bit sign bit.
  39 + * 41bits timestamp offset from 2016.11.01(ShardingSphere distributed primary key published data) to now.
  40 + * 10bits worker process id.
  41 + * 12bits auto increment offset in one mills
  42 + * </pre>
  43 + *
  44 + * <p>
  45 + * Call @{@code SnowflakeShardingKeyGenerator.setWorkerId} to set worker id, default value is 0.
  46 + * </p>
  47 + *
  48 + * <p>
  49 + * Call @{@code SnowflakeShardingKeyGenerator.setMaxTolerateTimeDifferenceMilliseconds} to set max tolerate time difference milliseconds, default value is 0.
  50 + * </p>
  51 + */
  52 +public final class ShardingKeyGeneratorImpl implements ShardingKeyGenerator, ShardingKeyGeneratorExt {
  53 +
  54 + public static final long EPOCH;
  55 +
  56 + private static final long SEQUENCE_BITS = 11L;
  57 +
  58 + private static final long BATCH_FLAG_BITS = 1L;
  59 +
  60 + private static final long WORKER_ID_BITS = 10L;
  61 +
  62 + private static final long SEQUENCE_MASK = (1 << SEQUENCE_BITS) - 1;
  63 +
  64 + private static final long BATCH_FLAG_LEFT_SHIFT_BITS = SEQUENCE_BITS;
  65 +
  66 + private static final long WORKER_ID_LEFT_SHIFT_BITS = BATCH_FLAG_LEFT_SHIFT_BITS + BATCH_FLAG_BITS;
  67 +
  68 + private static final long TIMESTAMP_LEFT_SHIFT_BITS = WORKER_ID_LEFT_SHIFT_BITS + WORKER_ID_BITS;
  69 +
  70 + private static final long WORKER_ID_MAX_VALUE = 1L << WORKER_ID_BITS;
  71 +
  72 + private static final long WORKER_ID = 0;
  73 +
  74 + private static final int DEFAULT_VIBRATION_VALUE = 1;
  75 +
  76 + private static final int MAX_TOLERATE_TIME_DIFFERENCE_MILLISECONDS = 10;
  77 +
  78 + private static TimeService timeService = new TimeService();
  79 +
  80 + private Properties properties = new Properties();
  81 +
  82 + private int sequenceOffset = -1;
  83 +
  84 + private long sequence;
  85 +
  86 + private long lastMilliseconds;
  87 +
  88 + static {
  89 + Calendar calendar = Calendar.getInstance();
  90 + calendar.set(2016, Calendar.NOVEMBER, 1);
  91 + calendar.set(Calendar.HOUR_OF_DAY, 0);
  92 + calendar.set(Calendar.MINUTE, 0);
  93 + calendar.set(Calendar.SECOND, 0);
  94 + calendar.set(Calendar.MILLISECOND, 0);
  95 + EPOCH = calendar.getTimeInMillis();
  96 + }
  97 +
  98 + @Override
  99 + public String getType() {
  100 + return "SNOWFLAKE-SELF";
  101 + }
  102 +
  103 + @Override
  104 + public synchronized Comparable<?> generateKey() {
  105 + long currentMilliseconds = timeService.getCurrentMillis();
  106 + if (waitTolerateTimeDifferenceIfNeed(currentMilliseconds)) {
  107 + currentMilliseconds = timeService.getCurrentMillis();
  108 + }
  109 + if (lastMilliseconds == currentMilliseconds) {
  110 + if (0L == (sequence = (sequence + 1) & SEQUENCE_MASK)) {
  111 + currentMilliseconds = waitUntilNextTime(currentMilliseconds);
  112 + }
  113 + } else {
  114 + vibrateSequenceOffset();
  115 + sequence = sequenceOffset;
  116 + }
  117 + lastMilliseconds = currentMilliseconds;
  118 + return ((currentMilliseconds - EPOCH) << TIMESTAMP_LEFT_SHIFT_BITS) | (getWorkerId() << WORKER_ID_LEFT_SHIFT_BITS) | (0 << BATCH_FLAG_LEFT_SHIFT_BITS) | sequence;
  119 + }
  120 +
  121 + private boolean waitTolerateTimeDifferenceIfNeed(final long currentMilliseconds) {
  122 + if (lastMilliseconds <= currentMilliseconds) {
  123 + return false;
  124 + }
  125 + long timeDifferenceMilliseconds = lastMilliseconds - currentMilliseconds;
  126 + Preconditions.checkState(timeDifferenceMilliseconds < getMaxTolerateTimeDifferenceMilliseconds(),
  127 + "Clock is moving backwards, last time is %d milliseconds, current time is %d milliseconds", lastMilliseconds, currentMilliseconds);
  128 + try {
  129 + Thread.sleep(timeDifferenceMilliseconds);
  130 + } catch (InterruptedException e) {
  131 + e.printStackTrace();
  132 + }
  133 + return true;
  134 + }
  135 +
  136 + private long getWorkerId() {
  137 + long result = Long.valueOf(properties.getProperty("worker.id", String.valueOf(WORKER_ID)));
  138 + Preconditions.checkArgument(result >= 0L && result < WORKER_ID_MAX_VALUE);
  139 + return result;
  140 + }
  141 +
  142 + private int getMaxVibrationOffset() {
  143 + int result = Integer.parseInt(properties.getProperty("max.vibration.offset", String.valueOf(DEFAULT_VIBRATION_VALUE)));
  144 + Preconditions.checkArgument(result >= 0 && result <= SEQUENCE_MASK, "Illegal max vibration offset");
  145 + return result;
  146 + }
  147 +
  148 + private int getMaxTolerateTimeDifferenceMilliseconds() {
  149 + return Integer.valueOf(properties.getProperty("max.tolerate.time.difference.milliseconds", String.valueOf(MAX_TOLERATE_TIME_DIFFERENCE_MILLISECONDS)));
  150 + }
  151 +
  152 + private long waitUntilNextTime(final long lastTime) {
  153 + long result = timeService.getCurrentMillis();
  154 + while (result <= lastTime) {
  155 + result = timeService.getCurrentMillis();
  156 + }
  157 + return result;
  158 + }
  159 +
  160 + private void vibrateSequenceOffset() {
  161 + sequenceOffset = sequenceOffset >= getMaxVibrationOffset() ? 0 : sequenceOffset + 1;
  162 + }
  163 +
  164 + @Override
  165 + public List<Long> generateKeyList(int genNum) {
  166 + long currentMilliseconds = timeService.getCurrentMillis();
  167 + if (waitTolerateTimeDifferenceIfNeed(currentMilliseconds)) {
  168 + currentMilliseconds = timeService.getCurrentMillis();
  169 + }
  170 + List<Long> data = new ArrayList<Long>(genNum);
  171 + for(int i=0; i<genNum; ++i) {
  172 + if (lastMilliseconds == currentMilliseconds) {
  173 + if (0L == (sequence = (sequence + 1) & SEQUENCE_MASK)) {
  174 + currentMilliseconds = waitUntilNextTime(currentMilliseconds);
  175 + }
  176 + } else {
  177 + vibrateSequenceOffset();
  178 + sequence = sequenceOffset;
  179 + }
  180 + data.add(((currentMilliseconds - EPOCH) << TIMESTAMP_LEFT_SHIFT_BITS) | (getWorkerId() << WORKER_ID_LEFT_SHIFT_BITS) | (1 << BATCH_FLAG_LEFT_SHIFT_BITS) | sequence);
  181 + }
  182 + lastMilliseconds = currentMilliseconds;
  183 + return data;
  184 + }
  185 +
  186 + @Override
  187 + public Properties getProperties() {
  188 + return this.properties;
  189 + }
  190 +
  191 + @Override
  192 + public void setProperties(Properties properties) {
  193 + this.properties = properties;
  194 + }
  195 +
  196 + public static void setTimeService(TimeService timeService) {
  197 + ShardingKeyGeneratorImpl.timeService = timeService;
  198 + }
  199 +
  200 + @Override
  201 + public void loalConfig(ShardingSphereKeyGeneratorConfiguration config) {
  202 + if(config.getMaxTolerateTimeDifferenceMilliseconds() != null) {
  203 + properties.setProperty("max.tolerate.time.difference.milliseconds", config.getMaxTolerateTimeDifferenceMilliseconds());
  204 + }
  205 + if(config.getWorkerId() != null) {
  206 + properties.setProperty("worker.id", config.getWorkerId());
  207 + }
  208 + if(config.getMaxVibrationOffset() != null) {
  209 + properties.setProperty("max.vibration.offset", config.getMaxVibrationOffset());
  210 + }
  211 + }
  212 +}
... ...
src/main/java/com/taover/repository/shardingsphere/ShardingSphereService.java 0 → 100644
... ... @@ -0,0 +1,62 @@
  1 +package com.taover.repository.shardingsphere;
  2 +
  3 +import java.util.HashMap;
  4 +import java.util.List;
  5 +import java.util.Map;
  6 +
  7 +import javax.annotation.Resource;
  8 +
  9 +import org.springframework.stereotype.Service;
  10 +
  11 +import com.taover.repository.autoconfigure.ShardingSphereKeyGeneratorConfiguration;
  12 +
  13 +@Service
  14 +public class ShardingSphereService {
  15 + private Map<Long, Map<String, String>> CACHED_TABLE_SUFFIX_BY_TENANT = null;
  16 + private Map<String, ShardingKeyGeneratorExt> GENERATOR_HOLDER = new HashMap<String, ShardingKeyGeneratorExt>();
  17 +
  18 + @Resource
  19 + private ShardingInfoRepository shardingInfoRepository;
  20 + private ShardingSphereKeyGeneratorConfiguration config;
  21 +
  22 + public ShardingSphereService(ShardingSphereKeyGeneratorConfiguration config) {
  23 + this.config = config;
  24 + }
  25 +
  26 + public List<Long> generateKeyList(String tableName, int number){
  27 + if(!GENERATOR_HOLDER.containsKey(tableName)) {
  28 + loadShardingKeyGenerator(tableName);
  29 + }
  30 + return GENERATOR_HOLDER.get(tableName).generateKeyList(number);
  31 + }
  32 +
  33 + public Map<String, String> getShardingInfoMapByTenantId(Long tenantId) {
  34 + if(CACHED_TABLE_SUFFIX_BY_TENANT == null) {
  35 + loadCacheTableShardingInfoByTenantId();
  36 + }
  37 + return CACHED_TABLE_SUFFIX_BY_TENANT.get(tenantId);
  38 + }
  39 +
  40 + private synchronized void loadCacheTableShardingInfoByTenantId() {
  41 + if(CACHED_TABLE_SUFFIX_BY_TENANT != null) {
  42 + return;
  43 + }
  44 + List<ShardingInfoEntity> dataList = this.shardingInfoRepository.findListBySql("1=1");
  45 + Map<Long, Map<String, String>> tempData = new HashMap<Long, Map<String, String>>();
  46 + for(ShardingInfoEntity item: dataList) {
  47 + Map<String, String> tempItem = tempData.getOrDefault(item.getTenantId(), new HashMap<String, String>());
  48 + tempItem.put(item.getTableName(), item.getShardingSuffix());
  49 + tempData.put(item.getTenantId(), tempItem);
  50 + }
  51 + CACHED_TABLE_SUFFIX_BY_TENANT = tempData;
  52 + }
  53 +
  54 + private synchronized void loadShardingKeyGenerator(String tableName) {
  55 + if(GENERATOR_HOLDER.containsKey(tableName)) {
  56 + return;
  57 + }
  58 + ShardingKeyGeneratorExt generator = new ShardingKeyGeneratorImpl();
  59 + generator.loalConfig(config);
  60 + GENERATOR_HOLDER.put(tableName, generator);
  61 + }
  62 +}
... ...
src/main/java/com/taover/repository/util/UtilsSql.java 0 → 100644
... ... @@ -0,0 +1,194 @@
  1 +package com.taover.repository.util;
  2 +
  3 +import java.util.HashMap;
  4 +import java.util.Map;
  5 +import java.util.Stack;
  6 +
  7 +import org.springframework.util.StringUtils;
  8 +
  9 +import com.taover.repository.exception.SqlParsePagerException;
  10 +
  11 +public class UtilsSql {
  12 +
  13 + public static String[] splitCoreSql(String coreSql) throws SqlParsePagerException {
  14 + //去除''内的信息
  15 + int fromIndex = calcFromIndex(coreSql);
  16 + if(fromIndex > -1) {
  17 + return new String[] {coreSql.substring(0, fromIndex), coreSql.substring(fromIndex, coreSql.length())};
  18 + }else {
  19 + throw new SqlParsePagerException("未找到FROM子句");
  20 + }
  21 + }
  22 +
  23 + private static int calcFromIndex(String coreSql) {
  24 + Stack<String> operStack = new Stack<String>();
  25 + String coreSqlUpperCase = coreSql.toUpperCase();
  26 + int sqlLen = coreSqlUpperCase.length();
  27 + int currIndex = 0;
  28 + while(currIndex < sqlLen) {
  29 + String originContainBlank = subFirstStrEndWithBlank(coreSqlUpperCase, currIndex);
  30 + String itemWithoutBlank = originContainBlank.trim();
  31 + if("".equals(itemWithoutBlank)) {
  32 + currIndex += originContainBlank.length();
  33 + continue;
  34 + }
  35 + if(operStack.isEmpty() && "FROM".equals(itemWithoutBlank)) {
  36 + return currIndex;
  37 + }
  38 + dealCoupleMark(itemWithoutBlank, operStack);
  39 + currIndex += originContainBlank.length();
  40 + }
  41 + return -1;
  42 + }
  43 + private static void dealCoupleMark(String itemWithoutBlank, Stack<String> operStack) {
  44 + char preChar = ' ';
  45 + for(int i=0; i<itemWithoutBlank.length(); ++i) {
  46 + char currChar = itemWithoutBlank.charAt(i);
  47 + if(preChar != '\\' && currChar == '\'') {
  48 + if(operStack.isEmpty() || !operStack.peek().equals("'")) {
  49 + operStack.push("'");
  50 + }else if(operStack.peek().equals("'")) {
  51 + operStack.pop();
  52 + }
  53 + }else if(currChar == '('){
  54 + if(operStack.isEmpty() || !operStack.peek().equals("'")) {
  55 + operStack.push("(");
  56 + }
  57 + }else if(currChar == ')') {
  58 + if(!operStack.isEmpty() && operStack.peek().equals("(")) {
  59 + operStack.pop();
  60 + }
  61 + }
  62 + preChar = currChar;
  63 + }
  64 + }
  65 +
  66 + private static String subFirstStrEndWithBlank(String coreSqlUpperCase, int startIndex) {
  67 + boolean startWithBlank = coreSqlUpperCase.charAt(startIndex)==' ';
  68 + int endIndex = startIndex;
  69 + int sqlLen = coreSqlUpperCase.length();
  70 + char preChar = '0';
  71 + for(int i=startIndex; i<sqlLen; ++i) {
  72 + char currChar = coreSqlUpperCase.charAt(i);
  73 + if(startWithBlank && currChar!=' ') {
  74 + endIndex = i;
  75 + break;
  76 + }
  77 + if(!startWithBlank && currChar!=' ' && preChar==' ') {
  78 + endIndex = i;
  79 + break;
  80 + }
  81 + preChar = currChar;
  82 + if(i == sqlLen-1) {
  83 + endIndex = sqlLen;
  84 + }
  85 + }
  86 + return coreSqlUpperCase.substring(startIndex, endIndex);
  87 + }
  88 +
  89 + /**
  90 + * 获取排序字符串
  91 + * @param sort
  92 + * @param order
  93 + * @param columnPreffix
  94 + * @return
  95 + */
  96 + public static String getSortCondition(String sort, String order, String columnPreffix){
  97 + String underScoreSort = UtilsString.underscoreName(sort).toLowerCase();
  98 + if(StringUtils.isEmpty(columnPreffix)){
  99 + columnPreffix = "";
  100 + }
  101 + String sortCondition = " ";
  102 + if(!StringUtils.isEmpty(underScoreSort)){
  103 + sortCondition = " order by ";
  104 + String[] sortArr = underScoreSort.split(",");
  105 + if(StringUtils.isEmpty(order)){
  106 + sortCondition += columnPreffix+sortArr[0]+" DESC ";
  107 + for(int i=1; i<sortArr.length; ++i){
  108 + sortCondition += ","+columnPreffix+sortArr[i]+" DESC ";
  109 + }
  110 + }else{
  111 + String[] orderArr = order.split(",");
  112 + sortCondition += sortArr[0]+" "+orderArr[0]+" ";
  113 + for(int i=1; i<sortArr.length; ++i){
  114 + if(i < orderArr.length){
  115 + sortCondition = ","+columnPreffix+sortArr[i]+" "+orderArr[i]+" ";
  116 + }else{
  117 + sortCondition = ","+columnPreffix+sortArr[i]+" DESC ";
  118 + }
  119 + }
  120 + }
  121 + }
  122 + return sortCondition;
  123 + }
  124 +
  125 + /**
  126 + * 获取分页
  127 + * @param sort
  128 + * @param order
  129 + * @param columnPreffix
  130 + * @return
  131 + */
  132 + public static String getLimitCondition(int page, int pageSize){
  133 + String sql = "";
  134 + if(page < -1){
  135 + page = 0;
  136 + if(pageSize < 1){
  137 + pageSize = 0;
  138 + }
  139 + sql += " limit "+pageSize*(page-1)+","+pageSize;
  140 + }else if(page == -1){
  141 + sql = "";
  142 + }else{
  143 + if(pageSize < 1){
  144 + pageSize = 0;
  145 + }
  146 + sql += " limit "+pageSize*(page-1)+","+pageSize;
  147 + }
  148 + return sql;
  149 + }
  150 +
  151 + /**
  152 + * 创建分页返回
  153 + * @param page
  154 + * @param rows
  155 + * @param data
  156 + * @return
  157 + */
  158 + public static Map<String, Object> createPage(int page, int size, int total, Object data){
  159 + Map<String, Object> pageData = new HashMap<String, Object>();
  160 + pageData.put("page", page);
  161 + pageData.put("rows", data);
  162 + pageData.put("size", size);
  163 + pageData.put("total", total);
  164 + return pageData;
  165 + }
  166 +
  167 + public static void main(String[] args) {
  168 + String[] testSql = new String[] {
  169 + "\\",
  170 + "select actionFrom as 'seelctsele\\'ctd',(select a as 'fromCActio' from t) from www where 223=1 ",
  171 + "SELECT wxorder_order.refund_way refundWay,wxorder_order.refund_delivery_sn refundDeliverySn, (SELECT sum(wxorder_compensate.`ware_refund_money`) from `wxorder_compensate` where wxorder_compensate.`order_id` = wxorder_order.id) as wareRefundMoney,(SELECT sum(wxorder_compensate.`refund_money`) from `wxorder_compensate` where wxorder_compensate.`order_id` = wxorder_order.id) as refundMoney, wxorder_order.operate_refund_time applyCompensateTime,wxorder_order.refund_instructions refundInstructions, wxorder_order.channel_id channelId, wxorder_channel.name channelName, wxorder_channel.platform_code platformCode, wxorder_order.pre_control_status as refundPreStatus, wxorder_order.ware_id wareId, wxorder_ware.name wareName, wxorder_order.id, wxorder_order.order_sn orderSn, wxorder_order.upload_sn uploadSn, wxorder_order.money_paid moneyPaid, wxorder_order.consignee, wxorder_order.mobile, wxorder_order.province_name provinceName, wxorder_order.city_name cityName, wxorder_order.district_name districtName, wxorder_order.address, wxorder_order.channel_remark channelRemark, wxorder_order.customer_remark customerRemark, wxorder_order.platform_customer_remark platformCustomerRemark, wxorder_order.sender_name senderName, wxorder_order.sender_mobile senderMobile, date_format(wxorder_order.create_time, '%Y-%m-%d %H:%i:%s') createTime, date_format(wxorder_order.real_delivery_time, '%Y-%m-%d %H:%i:%s') realDeliveryTime, wxorder_order.progress_distribute progressDistribute, wxorder_order.progress_delivery progressDelivery, wxorder_order.control_status controlStatus, wxorder_order.express_name expressName, wxorder_order.express_number expressNumber,wxorder_order.shipping_price shippingPrice, wxorder_order.customer_network_name ,(select count(*) from wxorder_compensate WHERE wxorder_compensate.order_id = wxorder_order.id) as compensateCountAll,(select count(*) from wxorder_compensate WHERE wxorder_compensate.order_id = wxorder_order.id and wxorder_compensate.progress_status = 1) as compensateCountDealed ,(select count(*) from wxorder_channel_refund_payment where wxorder_channel_refund_payment.order_id = wxorder_order.id) as channelRefundPaymentStatus,(select count(*) from wxorder_ware_refund_payment where wxorder_ware_refund_payment.order_id = wxorder_order.id) as wareRefundPaymentStatus FROM wxorder_order wxorder_order INNER JOIN wxorder_channel wxorder_channel ON wxorder_order.channel_id=wxorder_channel.id and wxorder_channel.tenant_id=54 INNER JOIN wxorder_ware wxorder_ware ON wxorder_order.ware_id=wxorder_ware.id and wxorder_ware.tenant_id=54 INNER JOIN wxorder_order_goods wxorder_order_goods ON wxorder_order.id=wxorder_order_goods.order_id and wxorder_order_goods.tenant_id=54 WHERE 1=1 AND wxorder_order.tenant_id='54' AND wxorder_order.control_status='4' GROUP BY wxorder_order.id",
  172 + "select wdd, fromType from www where 223",
  173 + "SELECT excel_data.already_deal_line alreadyDealLine, excel_data.channel_id channelId, excel_data.channel_name channelName, excel_data.contain_express_status containExpressStatus, excel_data.create_time createTime, excel_data.deal_control dealControl, excel_data.deal_status dealStatus, excel_data.excel_path excelPath, excel_data.excel_title_index excelTitleIndex, excel_data.exists_error existsError, excel_data.file_id fileId, excel_data.file_name fileName, excel_data.group_name groupName, excel_data.id, excel_data.key_mapping keyMapping, excel_data.message_ssid messageSsid, excel_data.order_line orderLine, excel_data.payload payload, excel_data.progress_step progressStep, excel_data.select_sheet_name selectSheetName, excel_data.step_deal_time stepDealTime, excel_data.tenant_id tenantId, excel_data.update_time updateTime, excel_data.xls_batch_no xlsBatchNo FROM wxorder_excel_data excel_data WHERE excel_data.tenant_id=16",
  174 + "SELECT excel_data.xls_batch_no as 'xlsBatchNo', (select now()) as 'temp' FROM wxorder_excel_data excel_data WHERE excel_data.tenant_id=16"
  175 + };
  176 +
  177 + for(int i=0; i<testSql.length; ++i) {
  178 + String item = testSql[i];
  179 + System.out.println("================testSql["+i+"]===============");
  180 + try {
  181 + String[] data = splitCoreSql(item);
  182 + System.out.println(data[0]);
  183 + System.out.println(data[1]);
  184 + } catch (Exception e) {
  185 + System.out.println(e.getMessage());
  186 + }
  187 + }
  188 +
  189 +// String testSub = " asdf asdf asdfaf";
  190 +// System.out.println(subFirstStrEndWithBlank(testSub, 5));
  191 +// System.out.println(subFirstStrEndWithBlank(testSub, 6));
  192 +// System.out.println(subFirstStrEndWithBlank(testSub, 13));
  193 + }
  194 +}
... ...
src/main/java/com/taover/repository/util/UtilsString.java 0 → 100644
... ... @@ -0,0 +1,237 @@
  1 +package com.taover.repository.util;
  2 +
  3 +import java.net.URL;
  4 +import java.text.SimpleDateFormat;
  5 +import java.util.Date;
  6 +
  7 +public class UtilsString {
  8 + /**
  9 + * 格式化日期区间字符串
  10 + * @param source
  11 + * @param splitStr
  12 + * @param dateFormat
  13 + * @return
  14 + * @throws Exception
  15 + */
  16 + public static Date[] getDateFromString(String source, String splitStr, String dateFormat) throws Exception{
  17 + Date[] resultObj = new Date[2];
  18 + Date createdAtStart = null;
  19 + Date createdAtEnd = null;
  20 + if(source != null && !"".equals(source)){
  21 + String[] createdAtArr = source.split(splitStr);
  22 + SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
  23 + if(createdAtArr.length > 0){
  24 + createdAtStart = sdf.parse(createdAtArr[0]);
  25 + }
  26 + if(createdAtArr.length > 1){
  27 + createdAtEnd = sdf.parse(createdAtArr[1]);
  28 + }
  29 + }
  30 + resultObj[0] = createdAtStart;
  31 + resultObj[1] = createdAtEnd;
  32 + return resultObj;
  33 + }
  34 +
  35 + /**
  36 + * 获取URL path部分
  37 + * @param url
  38 + * @return
  39 + */
  40 + public static String getUrlPath(String url){
  41 + if(url == null){
  42 + return null;
  43 + }
  44 + if(url.startsWith("http")){
  45 + try{
  46 + URL dataUrl = new URL(url);
  47 + return dataUrl.getPath();
  48 + }catch(Exception e){
  49 + e.printStackTrace();
  50 + }
  51 + }
  52 + return url;
  53 + }
  54 +
  55 + /**
  56 + * 在compares字符数组查找pattern字符串,找到则返回字串在数组中的索引,未找到返回-1
  57 + * @param pattern
  58 + * @param compares
  59 + * @return
  60 + */
  61 + public static int getStringIndex(String pattern, String compares[]){
  62 + //参数检验
  63 + if(pattern==null || compares==null){
  64 + return -1;
  65 + }
  66 +
  67 + //循环遍历compares
  68 + for(int i=0; i<compares.length; ++i){
  69 + if(compares[i].equals(pattern)){
  70 + return i;
  71 + }
  72 + }
  73 + return -1;
  74 + }
  75 +
  76 + /**
  77 + * 生成发货单的发货单内部序号, 格式:'D'.date('Ymd') +8位数字
  78 + * @return
  79 + */
  80 + public static String getDeliverySn(){
  81 + String result = "D";
  82 + String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
  83 + long temp = System.currentTimeMillis()%100000000;
  84 + result = result + date + temp;
  85 + return result;
  86 + }
  87 +
  88 + /**
  89 + * 通过表名获取BEAN类名
  90 + * @param tableName
  91 + * @return
  92 + */
  93 + public static String getBeanNameFormTableName(String tableName){
  94 + if (tableName == null) return null;
  95 + if (tableName.length() == 0) return "";
  96 + byte[] ss = tableName.toLowerCase().getBytes();
  97 + int len = ss.length;
  98 + byte[] ss1 = new byte[len];
  99 + ss1[0] = new String(ss, 0).toUpperCase().getBytes()[0];
  100 + int k = 1;
  101 + for (int i = 1; i < ss.length; i++) {
  102 + if (ss[i] == '_') {
  103 + if (i < ss.length - 1) {
  104 + ss1[k] = (byte)Character.toUpperCase(ss[(i + 1)]);
  105 + i++;
  106 + }
  107 + len--;
  108 + } else {
  109 + ss1[k] = ss[i];
  110 + }
  111 + k++;
  112 + }
  113 + return new String(ss1, 0, len);
  114 + }
  115 +
  116 + /**
  117 + * 获取前缀
  118 + * @param value
  119 + * @param digitNumber
  120 + * @param preffixChar
  121 + * @return
  122 + */
  123 + public static String getCodeWithPreffix(long value, int digitNumber, char preffixChar){
  124 + String result = "";
  125 + if(value>Long.MAX_VALUE || value<Long.MIN_VALUE){
  126 + return null;
  127 + }
  128 + for(int i=digitNumber; i>0; --i){
  129 + long baseDiv = (long) Math.pow(10, i-1);
  130 + long baseRand = (long) Math.pow(10, i);
  131 + long currentDigit = value % baseRand / baseDiv;
  132 + if(currentDigit == 0){
  133 + result = result + preffixChar;
  134 + }else{
  135 + result = result + currentDigit;
  136 + }
  137 + }
  138 + return result;
  139 + }
  140 +
  141 + /**
  142 + * 将驼峰式命名的字符串转换为下划线大写方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。</br>
  143 + * 例如:HelloWorld->HELLO_WORLD
  144 + * @param name 转换前的驼峰式命名的字符串
  145 + * @return 转换后下划线大写方式命名的字符串
  146 + */
  147 + public static String underscoreName(String name) {
  148 + StringBuilder result = new StringBuilder();
  149 + if (name != null && name.length() > 0) {
  150 + // 将第一个字符处理成大写
  151 + result.append(name.substring(0, 1).toUpperCase());
  152 + // 循环处理其余字符
  153 + for (int i = 1; i < name.length(); i++) {
  154 + String s = name.substring(i, i + 1);
  155 + // 在大写字母前添加下划线
  156 + if (Character.isUpperCase(s.charAt(0)) && Character.isLetter(s.charAt(0))) {
  157 + result.append("_");
  158 + }
  159 + // 其他字符直接转成大写
  160 + result.append(s.toUpperCase());
  161 + }
  162 + }
  163 + return result.toString();
  164 + }
  165 +
  166 + /**
  167 + * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
  168 + * 例如:HELLO_WORLD->HelloWorld
  169 + * @param name 转换前的下划线大写方式命名的字符串
  170 + * @return 转换后的驼峰式命名的字符串
  171 + */
  172 + public static String camelName(String name) {
  173 + StringBuilder result = new StringBuilder();
  174 + // 快速检查
  175 + if (name == null || name.isEmpty()) {
  176 + // 没必要转换
  177 + return "";
  178 + } else if (!name.contains("_")) {
  179 + // 不含下划线,仅将首字母小写
  180 + return name.substring(0, 1).toLowerCase() + name.substring(1);
  181 + }
  182 + // 用下划线将原始字符串分割
  183 + String camels[] = name.split("_");
  184 + for (String camel : camels) {
  185 + // 跳过原始字符串中开头、结尾的下换线或双重下划线
  186 + if (camel.isEmpty()) {
  187 + continue;
  188 + }
  189 + // 处理真正的驼峰片段
  190 + if (result.length() == 0) {
  191 + // 第一个驼峰片段,全部字母都小写
  192 + result.append(camel.toLowerCase());
  193 + } else {
  194 + // 其他的驼峰片段,首字母大写
  195 + result.append(camel.substring(0, 1).toUpperCase());
  196 + result.append(camel.substring(1).toLowerCase());
  197 + }
  198 + }
  199 + return result.toString();
  200 + }
  201 +
  202 + public static String getRandomStr(int digitNum){
  203 + int numStartZero = 48;
  204 + int charStartUpperA = 65;
  205 + int charStartLowerA = 97;
  206 + int numSelectCount = 10;
  207 + int charSelectCount = 26;
  208 + int numCount = numSelectCount+2*charSelectCount;
  209 + String randomResult = "";
  210 + for(int i=0; i<digitNum; ++i){
  211 + int currIndex = (int)(Math.random()*numCount);
  212 + if(currIndex < numSelectCount){
  213 + currIndex = numStartZero+currIndex;
  214 + }else if(currIndex < numSelectCount+charSelectCount){
  215 + currIndex = charStartUpperA+(currIndex-numSelectCount);
  216 + }else{
  217 + currIndex = charStartLowerA+(currIndex-numSelectCount-charSelectCount);
  218 + }
  219 + randomResult += (char)(currIndex)+"";
  220 + }
  221 + return randomResult;
  222 + }
  223 +
  224 + public static void main(String args[]){
  225 +// System.out.println(getBeanNameFormTableName("asdf_asdf"));
  226 +// System.out.println(System.currentTimeMillis());
  227 +// System.out.println(getCodeWithPreffix(1231212, 10, '-'));
  228 + /*String dd = "\"{\"success\":true,\"code\":1,\"printedorder_id\":\"1654\",\"error_message\":\"\"}\"";
  229 + dd = dd.substring(1, dd.length()-1);
  230 + System.out.println(dd);
  231 + JSONObject temp = JSONObject.fromObject(dd);
  232 + System.out.println(temp.getInt("code"));*/
  233 +
  234 + //System.out.println(UtilsString.getUrlPath("https://ss0.umsapi.com/files/de/c1/13/dec11397254b06e1fd8750311ec2bb02ccd8d3dc.jpeg"));
  235 + System.out.println(getRandomStr(12));
  236 + }
  237 +}
0 238 \ No newline at end of file
... ...
src/main/resources/META-INF/services/org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator 0 → 100644
... ... @@ -0,0 +1 @@
  1 +com.taover.repository.shardingsphere.ShardingKeyGeneratorImpl
0 2 \ No newline at end of file
... ...
src/main/resources/META-INF/spring.factories 0 → 100644
... ... @@ -0,0 +1 @@
  1 +org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.taover.repository.autoconfigure.TaoverRepositoryAutoConfiguration
0 2 \ No newline at end of file
... ...
src/test/java/com/taover/repository/test/TestAutoconfigure.java 0 → 100644
... ... @@ -0,0 +1,20 @@
  1 +package com.taover.repository.test;
  2 +
  3 +import org.springframework.boot.SpringApplication;
  4 +import org.springframework.boot.autoconfigure.SpringBootApplication;
  5 +import org.springframework.context.ConfigurableApplicationContext;
  6 +import org.springframework.scheduling.annotation.EnableScheduling;
  7 +
  8 +import com.taover.repository.jdbctemplate.JdbcTemplateWrapperTenant;
  9 +
  10 +@SpringBootApplication
  11 +@EnableScheduling
  12 +public class TestAutoconfigure {
  13 + public static void main(String args[]) {
  14 + ConfigurableApplicationContext context = SpringApplication.run(TestAutoconfigure.class, args);
  15 + JdbcTemplateWrapperTenant jdbcTemplate = context.getBean(JdbcTemplateWrapperTenant.class);
  16 + System.out.println(jdbcTemplate.queryForList("select * from wxorder_order limit 1", 1L));
  17 + System.out.println(jdbcTemplate.queryForList("select * from wxorder_order limit 1", 2L));
  18 + System.out.println(jdbcTemplate.queryForList("select * from wxorder_order_express limit 1", 1L));
  19 + }
  20 +}
... ...
src/test/resources/META-INF/services/org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator 0 → 100644
... ... @@ -0,0 +1 @@
  1 +com.taover.repository.shardingsphere.ShardingKeyGeneratorImpl
0 2 \ No newline at end of file
... ...
src/test/resources/META-INF/spring.factories 0 → 100644
... ... @@ -0,0 +1 @@
  1 +org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.taover.repository.autoconfigure.RepositoryAutoConfiguration
0 2 \ No newline at end of file
... ...
src/test/resources/application.properties 0 → 100644
... ... @@ -0,0 +1,52 @@
  1 +
  2 +server.port=80
  3 +server.session.timeout=3600
  4 +
  5 +spring.servlet.multipart.max-file-size=10MB
  6 +spring.servlet.multipart.max-request-size=20MB
  7 +
  8 +spring.jackson.time-zone=GMT+8
  9 +spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
  10 +spring.mvc.dateFormat = yyyy-MM-dd HH:mm:ss
  11 +spring.gson.serialize-nulls=true
  12 +
  13 +spring.mvc.dispatch-options-request=true
  14 +
  15 +# shardingspere
  16 +spring.shardingsphere.datasource.names=ds0
  17 +spring.shardingsphere.datasource.ds0.type=com.alibaba.druid.pool.DruidDataSource
  18 +spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
  19 +#spring.shardingsphere.datasource.ds0.url=jdbc:mysql://121.42.142.102:3306/bzyun_wxorder?characterEncoding=UTF-8&zeroDateTimeBehavior=CONVERT_TO_NULL
  20 +#spring.shardingsphere.datasource.ds0.username=dev
  21 +#spring.shardingsphere.datasource.ds0.password=taover02
  22 +spring.shardingsphere.datasource.ds0.url=jdbc:mysql://rdsifmezqifmezqo.mysql.rds.aliyuncs.com:3306/bzyun_wxorder?characterEncoding=UTF-8
  23 +spring.shardingsphere.datasource.ds0.username=tylife
  24 +spring.shardingsphere.datasource.ds0.password=lexi365
  25 +spring.shardingsphere.datasource.ds0.initial-size=10
  26 +spring.shardingsphere.datasource.ds0.max-active=20
  27 +spring.shardingsphere.datasource.ds0.min-idle=5
  28 +spring.shardingsphere.datasource.ds0.max-wait=60000
  29 +
  30 +spring.shardingsphere.sharding.tables.wxorder_order.actual-data-nodes=ds0.wxorder_order
  31 +spring.shardingsphere.sharding.tables.wxorder_order.database-strategy.inline.sharding-column=id
  32 +spring.shardingsphere.sharding.tables.wxorder_order.database-strategy.inline.algorithm-expression=ds0
  33 +spring.shardingsphere.sharding.tables.wxorder_order.table-strategy.hint.algorithm-class-name=com.taover.repository.shardingsphere.ShardingAlgorithmHint
  34 +spring.shardingsphere.sharding.tables.wxorder_order.key-generator.column=id
  35 +spring.shardingsphere.sharding.tables.wxorder_order.key-generator.type=SNOWFLAKE-SELF
  36 +
  37 +spring.shardingsphere.sharding.tables.wxorder_order_goods.actual-data-nodes=ds0.wxorder_order_goods
  38 +spring.shardingsphere.sharding.tables.wxorder_order_goods.database-strategy.inline.sharding-column=id
  39 +spring.shardingsphere.sharding.tables.wxorder_order_goods.database-strategy.inline.algorithm-expression=ds0
  40 +spring.shardingsphere.sharding.tables.wxorder_order.table-strategy.hint.algorithm-class-name=com.taover.repository.shardingsphere.ShardingAlgorithmHint
  41 +spring.shardingsphere.sharding.tables.wxorder_order_goods.key-generator.column=id
  42 +spring.shardingsphere.sharding.tables.wxorder_order_goods.key-generator.type=SNOWFLAKE-SELF
  43 +
  44 +taover.sharding.workerId=1
  45 +taover.sharding.maxVibrationOffset=3
  46 +taover.sharding.maxTolerateTimeDifferenceMilliseconds=1000
  47 +
  48 +#spring.shardingsphere.sharding.default-key-generator.key-generator.column=id
  49 +#spring.shardingsphere.sharding.default-key-generator.type=SNOWFLAKE-SELF
  50 +#spring.shardingsphere.sharding.default-key-generator.props.worker.id=1
  51 +#spring.shardingsphere.sharding.default-key-generator.props.max.vibration.offset=3
  52 +#spring.shardingsphere.sharding.default-key-generator.props.max.tolerate.time.difference.milliseconds=1000
... ...