Commit f0611848f6313a6020b3d6b02ef2929585c1d6fa

Authored by 王彬
1 parent 7a32a07a

extend to sharding sphere

Showing 30 changed files with 2924 additions and 718 deletions   Show diff stats
@@ -5,7 +5,6 @@ @@ -5,7 +5,6 @@
5 * For more details take a look at the Java Libraries chapter in the Gradle 5 * For more details take a look at the Java Libraries chapter in the Gradle
6 * user guide available at https://docs.gradle.org/4.5.1/userguide/java_library_plugin.html 6 * user guide available at https://docs.gradle.org/4.5.1/userguide/java_library_plugin.html
7 */ 7 */
8 -  
9 plugins { 8 plugins {
10 // Apply the java-library plugin to add support for Java Library 9 // Apply the java-library plugin to add support for Java Library
11 id 'java' 10 id 'java'
@@ -19,10 +18,12 @@ group = 'com.taover.repository' @@ -19,10 +18,12 @@ group = 'com.taover.repository'
19 mainClassName = 'com.taover.repository.UtilsString' 18 mainClassName = 'com.taover.repository.UtilsString'
20 19
21 dependencies { 20 dependencies {
  21 + compile("org.springframework.boot:spring-boot-starter:2.0.5.RELEASE")
22 compile("org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final") 22 compile("org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final")
23 compile('org.springframework:spring-jdbc:5.1.9.RELEASE') 23 compile('org.springframework:spring-jdbc:5.1.9.RELEASE')
24 compile('mysql:mysql-connector-java:5.1.47') 24 compile('mysql:mysql-connector-java:5.1.47')
25 compile('com.alibaba:druid:1.2.4') 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 repositories { 29 repositories {
@@ -56,7 +57,7 @@ uploadArchives { @@ -56,7 +57,7 @@ uploadArchives {
56 authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD) 57 authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD)
57 } 58 }
58 pom.project { 59 pom.project {
59 - version '2.1.38' 60 + version '2.1.44'
60 artifactId ARTIFACT_Id 61 artifactId ARTIFACT_Id
61 groupId GROUP_ID 62 groupId GROUP_ID
62 packaging TYPE 63 packaging TYPE
gradle.properties
@@ -12,7 +12,7 @@ NEXUS_PASSWORD=Nexus@dev @@ -12,7 +12,7 @@ NEXUS_PASSWORD=Nexus@dev
12 # groupid 12 # groupid
13 GROUP_ID=com.taover 13 GROUP_ID=com.taover
14 14
15 -ARTIFACT_Id=com-taover-repository 15 +ARTIFACT_Id=com-taover-repository-starter
16 16
17 # type 17 # type
18 TYPE=jar 18 TYPE=jar
src/main/java/com/taover/repository/CustomJdbcTemplate.java
@@ -18,6 +18,8 @@ import javax.persistence.Table; @@ -18,6 +18,8 @@ import javax.persistence.Table;
18 18
19 import org.springframework.jdbc.core.JdbcTemplate; 19 import org.springframework.jdbc.core.JdbcTemplate;
20 20
  21 +import com.taover.repository.util.UtilsSql;
  22 +
21 /** 23 /**
22 * 24 *
23 * @author root 25 * @author root
src/main/java/com/taover/repository/CustomJdbcTemplateWrapperTenant.java
@@ -16,12 +16,13 @@ import javax.persistence.Id; @@ -16,12 +16,13 @@ import javax.persistence.Id;
16 import javax.persistence.Table; 16 import javax.persistence.Table;
17 17
18 import org.springframework.dao.DataAccessException; 18 import org.springframework.dao.DataAccessException;
19 -import org.springframework.jdbc.core.JdbcTemplate;  
20 19
21 import com.taover.repository.exception.MultiRowException; 20 import com.taover.repository.exception.MultiRowException;
22 import com.taover.repository.exception.NoContainTenantException; 21 import com.taover.repository.exception.NoContainTenantException;
23 import com.taover.repository.exception.NotFoundException; 22 import com.taover.repository.exception.NotFoundException;
24 import com.taover.repository.exception.ObjectReflectException; 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,52 +31,47 @@ import com.taover.repository.exception.ObjectReflectException;
30 * @param <T> 31 * @param <T>
31 * @param <ID> 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 @Resource 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 public CustomJdbcTemplateWrapperTenant() throws Exception{ 52 public CustomJdbcTemplateWrapperTenant() throws Exception{
57 //获取泛型类Class 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 if(annoTable == null){ 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 String schema = annoTable.schema(); 62 String schema = annoTable.schema();
67 String catalog = annoTable.catalog(); 63 String catalog = annoTable.catalog();
68 if(schema != null && !"".equals(schema)){ 64 if(schema != null && !"".equals(schema)){
69 - this.dbName = schema; 65 + this._dbName = schema;
70 }else if(catalog != null && !"".equals(catalog)){ 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 for(int i=0; i<declaredFields.length; ++i){ 75 for(int i=0; i<declaredFields.length; ++i){
80 Field currField = declaredFields[i]; 76 Field currField = declaredFields[i];
81 String fieldName = currField.getName(); 77 String fieldName = currField.getName();
@@ -83,34 +79,33 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -83,34 +79,33 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
83 Column annoColumn = (Column)currField.getAnnotation(Column.class); 79 Column annoColumn = (Column)currField.getAnnotation(Column.class);
84 if(annoId != null){ 80 if(annoId != null){
85 if(annoColumn == null){ 81 if(annoColumn == null){
86 - idTableFieldName = this.camelToUnderline(fieldName); 82 + _idTableFieldName = this.camelToUnderline(fieldName);
87 }else{ 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 }else{ 89 }else{
95 if(annoColumn != null){ 90 if(annoColumn != null){
96 String tableFieldName = annoColumn.name(); 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 //创建rowmapper 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,42 +132,6 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
137 } 132 }
138 return result.toString(); 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 private void appendWhereCondition(StringBuffer sql, StringBuffer pql, List<Object> list, List<Object[]> condition) { 136 private void appendWhereCondition(StringBuffer sql, StringBuffer pql, List<Object> list, List<Object[]> condition) {
178 if (condition == null || condition.size() == 0) return; 137 if (condition == null || condition.size() == 0) return;
@@ -236,20 +195,20 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -236,20 +195,20 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
236 } 195 }
237 196
238 private String getTableSql(){ 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 private String constructUpdateSql(T entity, List<Field> beanFieldList) { 203 private String constructUpdateSql(T entity, List<Field> beanFieldList) {
245 StringBuffer sqlInsertPart = new StringBuffer("INSERT INTO "+this.getTableSql()+"("); 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 while(beanFieldIter.hasNext()){ 206 while(beanFieldIter.hasNext()){
248 String beanFieldName = beanFieldIter.next(); 207 String beanFieldName = beanFieldIter.next();
249 - String tableFieldName = this.beanToTableField.get(beanFieldName); 208 + String tableFieldName = this._beanToTableField.get(beanFieldName);
250 Field beanField = null; 209 Field beanField = null;
251 try { 210 try {
252 - beanField = this.tClassInfo.getDeclaredField(beanFieldName); 211 + beanField = this._tClassInfo.getDeclaredField(beanFieldName);
253 beanField.setAccessible(true); 212 beanField.setAccessible(true);
254 if(beanField.get(entity) == null) { 213 if(beanField.get(entity) == null) {
255 continue; 214 continue;
@@ -280,7 +239,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -280,7 +239,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
280 return 0; 239 return 0;
281 } 240 }
282 } 241 }
283 - 242 +
284 @Override 243 @Override
285 public T findEntityByID(ID id, Long tenantId) throws NotFoundException { 244 public T findEntityByID(ID id, Long tenantId) throws NotFoundException {
286 return findEntityByID(id, tenantId, false); 245 return findEntityByID(id, tenantId, false);
@@ -288,16 +247,16 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -288,16 +247,16 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
288 247
289 @Override 248 @Override
290 public T findEntityByID(ID id, Long tenantId, boolean isLock) throws NotFoundException { 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 if (isLock) { 252 if (isLock) {
294 sql.append(" FOR UPDATE"); 253 sql.append(" FOR UPDATE");
295 } 254 }
296 try { 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 @Override 262 @Override
@@ -333,20 +292,20 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -333,20 +292,20 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
333 292
334 @Override 293 @Override
335 public List<T> findListByCondition(List<Object[]> condition, String sortCondition, Long tenantId){ 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 List<Object> list = new ArrayList<Object>(); 296 List<Object> list = new ArrayList<Object>();
338 condition.add(new Object[] {"tenant_id", "=", tenantId}); 297 condition.add(new Object[] {"tenant_id", "=", tenantId});
339 this.appendWhereCondition(sql, new StringBuffer(), list, condition); 298 this.appendWhereCondition(sql, new StringBuffer(), list, condition);
340 if(sortCondition != null && !sortCondition.equals("")){ 299 if(sortCondition != null && !sortCondition.equals("")){
341 sql.append(" " + sortCondition + " "); 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 @Override 305 @Override
347 public List<T> findListBySql(String sqlCondition, Long tenantId){ 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 @Override 311 @Override
@@ -356,7 +315,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -356,7 +315,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
356 315
357 @Override 316 @Override
358 public Map<String, Object> findPageByCondition(List<Object[]> condition, String sortCondition, int page, int pageSize, Long tenantId){ 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 StringBuffer pql = new StringBuffer(sql.toString()); 319 StringBuffer pql = new StringBuffer(sql.toString());
361 StringBuffer sqlCount = new StringBuffer("SELECT COUNT(1) rowCount FROM "+this.getTableSql()); 320 StringBuffer sqlCount = new StringBuffer("SELECT COUNT(1) rowCount FROM "+this.getTableSql());
362 condition.add(new Object[] {"tenant_id", "=", tenantId}); 321 condition.add(new Object[] {"tenant_id", "=", tenantId});
@@ -376,40 +335,39 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -376,40 +335,39 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
376 } 335 }
377 336
378 String pageSql = sql.toString() + " limit ?, ?"; 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 return UtilsSql.createPage(page, pageSize, Integer.valueOf(totalRowsMap.get("rowCount").toString()), resultList); 340 return UtilsSql.createPage(page, pageSize, Integer.valueOf(totalRowsMap.get("rowCount").toString()), resultList);
383 } 341 }
384 342
385 @Override 343 @Override
386 public Map<String, Object> findPageBySql(String sqlCondition, int page, int pageSize, Long tenantId){ 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 StringBuffer sqlCount = new StringBuffer("SELECT count(1) rowCount FROM "+this.getTableSql()+" WHERE tenant_id=" + tenantId + " and " + sqlCondition); 346 StringBuffer sqlCount = new StringBuffer("SELECT count(1) rowCount FROM "+this.getTableSql()+" WHERE tenant_id=" + tenantId + " and " + sqlCondition);
389 sql.append(" limit ?, ?"); 347 sql.append(" limit ?, ?");
390 List<Object> page_list = new ArrayList<Object>(); 348 List<Object> page_list = new ArrayList<Object>();
391 page_list.add((page - 1) * pageSize); 349 page_list.add((page - 1) * pageSize);
392 page_list.add(page * pageSize); 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 return UtilsSql.createPage(page, pageSize, Integer.valueOf(totalRowsMap.get("rowCount").toString()), resultList); 354 return UtilsSql.createPage(page, pageSize, Integer.valueOf(totalRowsMap.get("rowCount").toString()), resultList);
397 } 355 }
398 356
399 @Override 357 @Override
400 - public void addEntity(T entity) { 358 + public void addEntity(T entity, Long tenantId) {
401 StringBuffer sqlInsertPart = new StringBuffer("INSERT INTO "+this.getTableSql()+"("); 359 StringBuffer sqlInsertPart = new StringBuffer("INSERT INTO "+this.getTableSql()+"(");
402 StringBuffer sqlColumnPart = new StringBuffer(") VALUES ("); 360 StringBuffer sqlColumnPart = new StringBuffer(") VALUES (");
403 List<Object> paramList = new ArrayList<Object>(); 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 while(beanFieldIter.hasNext()){ 364 while(beanFieldIter.hasNext()){
407 String beanFieldName = beanFieldIter.next(); 365 String beanFieldName = beanFieldIter.next();
408 - String tableFieldName = this.beanToTableField.get(beanFieldName); 366 + String tableFieldName = this._beanToTableField.get(beanFieldName);
409 Field beanField; 367 Field beanField;
410 Object beanFieldValue = null; 368 Object beanFieldValue = null;
411 try { 369 try {
412 - beanField = this.tClassInfo.getDeclaredField(beanFieldName); 370 + beanField = this._tClassInfo.getDeclaredField(beanFieldName);
413 beanField.setAccessible(true); 371 beanField.setAccessible(true);
414 beanFieldValue = beanField.get(entity); 372 beanFieldValue = beanField.get(entity);
415 } catch (Exception e) { 373 } catch (Exception e) {
@@ -423,19 +381,19 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -423,19 +381,19 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
423 sqlColumnPart.append(" ?,"); 381 sqlColumnPart.append(" ?,");
424 paramList.add(beanFieldValue); 382 paramList.add(beanFieldValue);
425 } 383 }
426 - 384 +
427 //执行SQL 385 //执行SQL
428 String exeSql = sqlInsertPart.substring(0, sqlInsertPart.length()-1)+sqlColumnPart.substring(0, sqlColumnPart.length()-1)+")"; 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 @Override 390 @Override
433 - public void addEntityList(List<T> entityList) { 391 + public void addEntityList(List<T> entityList, Long tenantId) {
434 if(entityList == null || entityList.isEmpty()) { 392 if(entityList == null || entityList.isEmpty()) {
435 return; 393 return;
436 } 394 }
437 //构造SQL语句及Entity Field列表 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 StringBuffer exeSql = new StringBuffer(this.constructUpdateSql(entityList.get(0), beanFieldList)); 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,15 +422,15 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
464 } 422 }
465 exeSql.setCharAt(exeSql.length()-1, ';'); 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 @Override 429 @Override
472 public int deleteEntityByID(ID id, Long tenantId) { 430 public int deleteEntityByID(ID id, Long tenantId) {
473 StringBuffer sql = new StringBuffer("DELETE FROM "+this.getTableSql()+" WHERE"); 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 @Override 436 @Override
@@ -486,7 +444,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -486,7 +444,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
486 StringBuffer pql = new StringBuffer(sql.toString()); 444 StringBuffer pql = new StringBuffer(sql.toString());
487 condition.add(new Object[] {"tenant_id", "=", tenantId}); 445 condition.add(new Object[] {"tenant_id", "=", tenantId});
488 this.appendWhereCondition(sql, pql, list, condition); 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 @Override 450 @Override
@@ -494,7 +452,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -494,7 +452,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
494 if("".equals(sqlCondition.trim())) { 452 if("".equals(sqlCondition.trim())) {
495 throw new RuntimeException("params[sqlCondition] is empty"); 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 @Override 458 @Override
@@ -503,7 +461,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -503,7 +461,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
503 for(ID id: idList) { 461 for(ID id: idList) {
504 idSb.append(id); 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 @Override 467 @Override
@@ -520,10 +478,10 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -520,10 +478,10 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
520 List<Object> list = new ArrayList<Object>(); 478 List<Object> list = new ArrayList<Object>();
521 this.appendSetSql(sql, pql, list, changeList); 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 String updateSql = sql.substring(0, sql.length()-1)+where; 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 @Override 487 @Override
@@ -546,7 +504,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -546,7 +504,7 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
546 this.appendWhereCondition(where, pwhere, list, condition); 504 this.appendWhereCondition(where, pwhere, list, condition);
547 505
548 String updateSql = sql.substring(0, sql.length()-1)+where.toString(); 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 @Override 510 @Override
@@ -564,17 +522,13 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -564,17 +522,13 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
564 this.appendSetSql(sql, pql, list, updateObj); 522 this.appendSetSql(sql, pql, list, updateObj);
565 523
566 String updateSql = sql.toString().substring(0, sql.length()-1) + " WHERE tenant_id="+tenantId+" and "+sqlCondition; 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 @Override 528 @Override
571 public Map<String, Object> getPageData(String coreSql, String orderByPartSql, Integer page, Integer pageSize, Long tenantId){ 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 @Override 534 @Override
@@ -589,10 +543,9 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme @@ -589,10 +543,9 @@ public class CustomJdbcTemplateWrapperTenant&lt;T, ID extends Serializable&gt; impleme
589 543
590 //执行查询 544 //执行查询
591 List<Map<String, Object>> queryData = new ArrayList<Map<String, Object>>(); 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 return UtilsSql.createPage(page, pageSize, Integer.valueOf(countData.get("rowsCount").toString()), queryData); 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 @@ @@ -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,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,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,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 \ No newline at end of file 0 \ No newline at end of file
src/main/java/com/taover/repository/autoconfigure/ShardingSphereKeyGeneratorConfiguration.java 0 → 100644
@@ -0,0 +1,31 @@ @@ -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 @@ @@ -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 @@ @@ -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 package com.taover.repository.exception; 1 package com.taover.repository.exception;
2 2
3 public class MultiRowException extends Exception { 3 public class MultiRowException extends Exception {
  4 +
4 } 5 }
src/main/java/com/taover/repository/exception/NotFoundException.java
1 package com.taover.repository.exception; 1 package com.taover.repository.exception;
2 2
3 public class NotFoundException extends Exception { 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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ @@ -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 \ No newline at end of file 238 \ No newline at end of file
src/main/resources/META-INF/services/org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +com.taover.repository.shardingsphere.ShardingKeyGeneratorImpl
0 \ No newline at end of file 2 \ No newline at end of file
src/main/resources/META-INF/spring.factories 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.taover.repository.autoconfigure.TaoverRepositoryAutoConfiguration
0 \ No newline at end of file 2 \ No newline at end of file
src/test/java/com/taover/repository/test/TestAutoconfigure.java 0 → 100644
@@ -0,0 +1,20 @@ @@ -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 @@ @@ -0,0 +1 @@
  1 +com.taover.repository.shardingsphere.ShardingKeyGeneratorImpl
0 \ No newline at end of file 2 \ No newline at end of file
src/test/resources/META-INF/spring.factories 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.taover.repository.autoconfigure.RepositoryAutoConfiguration
0 \ No newline at end of file 2 \ No newline at end of file
src/test/resources/application.properties 0 → 100644
@@ -0,0 +1,52 @@ @@ -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