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 lombok.extern.slf4j.Slf4j; import org.apache.commons.compress.utils.Sets; import org.apache.ibatis.javassist.Modifier; 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.apache.shardingsphere.underlying.common.rule.DataNode; import org.springframework.beans.factory.annotation.Autowired; 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.util.*; import java.util.concurrent.atomic.AtomicInteger; @Service @Slf4j public class JdbcServiceImpl { public boolean createTable() throws SQLException { String ip = "192.168.29.131"; String port = "3306"; String dbName = "sharding_user"; String username = "root"; String password = "123456"; String tableName = "t_order_2022"; return JdbcUtils.createTable(ip, port, dbName, username, password, tableName); } @Resource(name = "shardingDataSource") private DataSource dataSource; @Autowired private MyDataSourceConfig myDataSourceConfig; /** * 获取数据节点 */ private List getDataNodes(MyDataSourcePropertie myDaSoPro, String dataSourceName, String logicTableName) throws SQLException { List 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 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; } @Transactional public void checkDb() { Map dataSourceConfig = myDataSourceConfig.getDataSourceConfig(); try { ShardingDataSource shardingDataSource = (ShardingDataSource) dataSource; ShardingRule shardingRule = shardingDataSource.getRuntimeContext().getRule(); //tableRule = shardingRule.getTableRule(dynamicTableName); List tableRules = (List) shardingRule.getTableRules(); Map>> data = new HashMap<>(); for (TableRule tableRule : tableRules) { String logicTableName = tableRule.getLogicTable(); Collection actualDatasourceNames = tableRule.getActualDatasourceNames(); Map> dataSourceMap = new HashMap<>(); for (String dataSourceName : actualDatasourceNames) { List dataNodeList = new ArrayList<>(); dataSourceMap.put(dataSourceName, dataNodeList); data.put(logicTableName, dataSourceMap); MyDataSourcePropertie myDataSourcePropertie = dataSourceConfig.get(dataSourceName); if (!StringUtils.isEmpty(myDataSourcePropertie)) { String shardingDbName = myDataSourcePropertie.getShardingDbName(); //并且包含需要自动刷新的表 if (myDataSourcePropertie.getTables().contains(logicTableName)) { //获取最近节点 List newDataNodes = getDataNodes(myDataSourcePropertie, dataSourceName, logicTableName); dataNodeList.addAll(newDataNodes); } } } } for (TableRule tableRule : tableRules) { String logicTableName = tableRule.getLogicTable(); Map> dataListMap = data.get(logicTableName); //刷新数据库jdbc连接信息 dynamicRefreshDatasourceNew(tableRule, dataListMap); } } catch (NoSuchFieldException | IllegalAccessException | SQLException e) { log.error(String.format("逻辑表:%s 动态分表配置错误!")); } } /** * 动态刷新数据源 */ private void dynamicRefreshDatasourceNew(TableRule tableRule, Map> dataListMap) throws NoSuchFieldException, IllegalAccessException { // 动态刷新:datasourceToTablesMapField Map> datasourceToTablesMap = Maps.newHashMap(); // 获取最新的DataNodes List newDataNodesAll = new ArrayList<>(); // 获取最新的actualTablesAll Set actualTablesAll = Sets.newHashSet(); // 获取最新的dataNodeIndexMap Map dataNodeIndexMap = Maps.newHashMap(); for (String dataSourceName : dataListMap.keySet()) { List newDataNodes = dataListMap.get(dataSourceName); Set actualTables = Sets.newHashSet(); 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(); }); datasourceToTablesMap.put(dataSourceName, actualTables); actualTablesAll.addAll(actualTables); newDataNodesAll.addAll(newDataNodes); } // 动态刷新: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, newDataNodesAll); // 动态刷新:actualTablesField Field actualTablesField = TableRule.class.getDeclaredField("actualTables"); actualTablesField.setAccessible(true); actualTablesField.set(tableRule, actualTablesAll); // 动态刷新:dataNodeIndexMapField Field dataNodeIndexMapField = TableRule.class.getDeclaredField("dataNodeIndexMap"); dataNodeIndexMapField.setAccessible(true); dataNodeIndexMapField.set(tableRule, dataNodeIndexMap); // 动态刷新:datasourceToTablesMapField Field datasourceToTablesMapField = TableRule.class.getDeclaredField("datasourceToTablesMap"); datasourceToTablesMapField.setAccessible(true); datasourceToTablesMapField.set(tableRule, datasourceToTablesMap); } }