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