|
@@ -1,11 +1,31 @@
|
|
package com.xin.shardingspherejdbcdemo.service.impl;
|
|
package com.xin.shardingspherejdbcdemo.service.impl;
|
|
|
|
|
|
|
|
+import com.google.common.collect.Maps;
|
|
|
|
+import com.xin.shardingspherejdbcdemo.config.sharding.MyDataSourceConfig;
|
|
|
|
+import com.xin.shardingspherejdbcdemo.config.sharding.MyDataSourcePropertie;
|
|
import com.xin.shardingspherejdbcdemo.utils.JdbcUtils;
|
|
import com.xin.shardingspherejdbcdemo.utils.JdbcUtils;
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
+import org.apache.commons.compress.utils.Sets;
|
|
|
|
+import org.apache.ibatis.javassist.Modifier;
|
|
|
|
+import org.apache.shardingsphere.core.config.ShardingConfigurationException;
|
|
|
|
+import org.apache.shardingsphere.core.rule.DataNode;
|
|
|
|
+import org.apache.shardingsphere.core.rule.ShardingRule;
|
|
|
|
+import org.apache.shardingsphere.core.rule.TableRule;
|
|
|
|
+import org.apache.shardingsphere.shardingjdbc.jdbc.core.datasource.ShardingDataSource;
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
|
|
|
|
|
+import javax.annotation.Resource;
|
|
|
|
+import javax.sql.DataSource;
|
|
|
|
+import java.lang.reflect.Field;
|
|
import java.sql.SQLException;
|
|
import java.sql.SQLException;
|
|
|
|
+import java.util.*;
|
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
|
@Service
|
|
@Service
|
|
|
|
+@Slf4j
|
|
public class JdbcServiceImpl {
|
|
public class JdbcServiceImpl {
|
|
|
|
|
|
public boolean createTable() throws SQLException {
|
|
public boolean createTable() throws SQLException {
|
|
@@ -18,4 +38,100 @@ public class JdbcServiceImpl {
|
|
return JdbcUtils.createTable(ip, port, dbName, username, password, tableName);
|
|
return JdbcUtils.createTable(ip, port, dbName, username, password, tableName);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @Resource(name = "shardingDataSource")
|
|
|
|
+ private DataSource dataSource;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private MyDataSourceConfig myDataSourceConfig;
|
|
|
|
+
|
|
|
|
+ @Transactional
|
|
|
|
+ public void checkDb() {
|
|
|
|
+ Map<String, MyDataSourcePropertie> dataSourceConfig = myDataSourceConfig.getDataSourceConfig();
|
|
|
|
+ try {
|
|
|
|
+ ShardingDataSource shardingDataSource = (ShardingDataSource) dataSource;
|
|
|
|
+ ShardingRule shardingRule = shardingDataSource.getRuntimeContext().getRule();
|
|
|
|
+ //tableRule = shardingRule.getTableRule(dynamicTableName);
|
|
|
|
+ List<TableRule> tableRules = (List<TableRule>) shardingRule.getTableRules();
|
|
|
|
+
|
|
|
|
+ for (TableRule tableRule : tableRules) {
|
|
|
|
+ String logicTableName = tableRule.getLogicTable();
|
|
|
|
+ Collection<String> actualDatasourceNames = tableRule.getActualDatasourceNames();
|
|
|
|
+ for (String dataSourceName : actualDatasourceNames) {
|
|
|
|
+ MyDataSourcePropertie myDataSourcePropertie = dataSourceConfig.get(dataSourceName);
|
|
|
|
+ if (!StringUtils.isEmpty(myDataSourcePropertie)) {
|
|
|
|
+ //并且包含需要自动刷新的表
|
|
|
|
+ if (myDataSourcePropertie.getTables().contains(logicTableName)) {
|
|
|
|
+ //获取最近节点
|
|
|
|
+ List<DataNode> newDataNodes = getDataNodes(myDataSourcePropertie, dataSourceName, logicTableName);
|
|
|
|
+ //刷新数据库jdbc连接信息
|
|
|
|
+ dynamicRefreshDatasource(dataSourceName, tableRule, newDataNodes);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ } catch (ShardingConfigurationException | NoSuchFieldException | IllegalAccessException | SQLException e) {
|
|
|
|
+ log.error(String.format("逻辑表:%s 动态分表配置错误!"));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取数据节点
|
|
|
|
+ */
|
|
|
|
+ private List<DataNode> getDataNodes(MyDataSourcePropertie myDaSoPro, String dataSourceName, String logicTableName) throws SQLException {
|
|
|
|
+ List<DataNode> newDataNodes = new ArrayList<>();
|
|
|
|
+ Calendar date = Calendar.getInstance();
|
|
|
|
+ String year = String.valueOf(date.get(Calendar.YEAR));
|
|
|
|
+ String createTableName = logicTableName + year;
|
|
|
|
+ JdbcUtils.createTable(myDaSoPro.getIp(), myDaSoPro.getPort(), myDaSoPro.getDbname(), myDaSoPro.getUsername(), myDaSoPro.getPassword(), createTableName);
|
|
|
|
+ List<String> tables = JdbcUtils.queryTable(myDaSoPro.getIp(), myDaSoPro.getPort(), myDaSoPro.getDbname(), myDaSoPro.getUsername(), myDaSoPro.getPassword(), logicTableName);
|
|
|
|
+ for (String table : tables) {
|
|
|
|
+ DataNode dataNode = new DataNode(dataSourceName + "." + table);
|
|
|
|
+ newDataNodes.add(dataNode);
|
|
|
|
+ }
|
|
|
|
+ // 扩展点
|
|
|
|
+ return newDataNodes;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 动态刷新数据源
|
|
|
|
+ */
|
|
|
|
+ private void dynamicRefreshDatasource(String dataSourceName, TableRule tableRule, List<DataNode> newDataNodes)
|
|
|
|
+ throws NoSuchFieldException, IllegalAccessException {
|
|
|
|
+ Set<String> actualTables = Sets.newHashSet();
|
|
|
|
+ Map<DataNode, Integer> dataNodeIndexMap = Maps.newHashMap();
|
|
|
|
+ AtomicInteger index = new AtomicInteger(0);
|
|
|
|
+ newDataNodes.forEach(dataNode -> {
|
|
|
|
+ actualTables.add(dataNode.getTableName());
|
|
|
|
+ if (index.intValue() == 0) {
|
|
|
|
+ dataNodeIndexMap.put(dataNode, 0);
|
|
|
|
+ } else {
|
|
|
|
+ dataNodeIndexMap.put(dataNode, index.intValue());
|
|
|
|
+ }
|
|
|
|
+ index.incrementAndGet();
|
|
|
|
+ });
|
|
|
|
+ // 动态刷新:actualDataNodesField
|
|
|
|
+ Field actualDataNodesField = TableRule.class.getDeclaredField("actualDataNodes");
|
|
|
|
+ Field modifiersField = Field.class.getDeclaredField("modifiers");
|
|
|
|
+ modifiersField.setAccessible(true);
|
|
|
|
+ modifiersField.setInt(actualDataNodesField, actualDataNodesField.getModifiers() & ~Modifier.FINAL);
|
|
|
|
+ actualDataNodesField.setAccessible(true);
|
|
|
|
+ actualDataNodesField.set(tableRule, newDataNodes);
|
|
|
|
+ // 动态刷新:actualTablesField
|
|
|
|
+ Field actualTablesField = TableRule.class.getDeclaredField("actualTables");
|
|
|
|
+ actualTablesField.setAccessible(true);
|
|
|
|
+ actualTablesField.set(tableRule, actualTables);
|
|
|
|
+ // 动态刷新:dataNodeIndexMapField
|
|
|
|
+ Field dataNodeIndexMapField = TableRule.class.getDeclaredField("dataNodeIndexMap");
|
|
|
|
+ dataNodeIndexMapField.setAccessible(true);
|
|
|
|
+ dataNodeIndexMapField.set(tableRule, dataNodeIndexMap);
|
|
|
|
+ // 动态刷新:datasourceToTablesMapField
|
|
|
|
+ Map<String, Collection<String>> datasourceToTablesMap = Maps.newHashMap();
|
|
|
|
+ datasourceToTablesMap.put(dataSourceName, actualTables);
|
|
|
|
+ Field datasourceToTablesMapField = TableRule.class.getDeclaredField("datasourceToTablesMap");
|
|
|
|
+ datasourceToTablesMapField.setAccessible(true);
|
|
|
|
+ datasourceToTablesMapField.set(tableRule, datasourceToTablesMap);
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|