1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
| @Slf4j public class ShardingAlgorithmUtils {
private static final Map<String, Set<String>> DS_TABLE_NAME_CACHE = new ConcurrentHashMap<>();
private static final String TABLE_SPLIT_SYMBOL = "_";
private static final Environment ENV = SpringUtils.getApplicationContext().getEnvironment();
public static String getShardingTableAndCreate(String logicTableName, String actualTableName, String dsPrefix) { synchronized (logicTableName.intern()) { Set<String> set = DS_TABLE_NAME_CACHE.get(dsPrefix); if (CollectionUtils.isNotEmpty(set) && set.contains(actualTableName)) { return actualTableName; }
boolean result = false; try { result = createShardingTable(logicTableName, actualTableName, dsPrefix); if (result) { set.add(actualTableName); } } catch (Exception e) { if (e instanceof SQLSyntaxErrorException && e.getMessage().contains("already exists")) { set.add(actualTableName); } } } return actualTableName; }
public static Set<String> getShardingTablesAndCreate(String logicTableName, Collection<String> actualTableNames, String dsPrefix) { return actualTableNames.stream().map(o -> getShardingTableAndCreate(logicTableName, o, dsPrefix)).collect(Collectors.toSet()); }
public static void loadAllTableNameBySchema(List<String> dsPrefix, List<String> logicTableNames) { DS_TABLE_NAME_CACHE.clear();
for (String prefix : dsPrefix) {
String jdbcUrl = ENV.getProperty(prefix + ".jdbc-url"); String username = ENV.getProperty(prefix + ".username"); String password = ENV.getProperty(prefix + ".password");
if (StringUtils.isEmpty(jdbcUrl) || StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) { log.error("jdbc properties invalid,URL:{}, username:{}, password:{}", jdbcUrl, username, password); throw new IllegalArgumentException("jdbc properties invalid!"); } try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password); Statement st = conn.createStatement()) { Set<String> set = new HashSet<>(); for (String logicTableName : logicTableNames) { try (ResultSet rs = st.executeQuery("SHOW TABLES LIKE '" + logicTableName + TABLE_SPLIT_SYMBOL + "%'")) { while (rs.next()) { String tableName = rs.getString(1); if (tableName != null && tableName.matches(String.format("^(%s\\d{6})$", logicTableName + TABLE_SPLIT_SYMBOL))) { set.add(rs.getString(1)); } } DS_TABLE_NAME_CACHE.put(prefix, set); } }
} catch (SQLException e) { log.error("Database connection failure:", e); throw new IllegalArgumentException("Database connection failure!"); } }
}
public static boolean createShardingTable(String logicTableName, String actualTableName, String dsPrefix) throws SQLException { String month = actualTableName.replace(logicTableName + TABLE_SPLIT_SYMBOL,""); YearMonth shardingMonth = YearMonth.parse(month, DateTimeFormatter.ofPattern("yyyyMM")); if (shardingMonth.isAfter(YearMonth.now())) { return false; }
synchronized (logicTableName.intern()) { executeSql(Collections.singletonList("CREATE TABLE `" + actualTableName + "` LIKE `" + logicTableName + "`;"), dsPrefix); } return true; }
private static void executeSql(List<String> sqlList, String dsPrefix) throws SQLException { String jdbcUrl = ENV.getProperty(dsPrefix + ".jdbc-url"); String username = ENV.getProperty(dsPrefix + ".username"); String password = ENV.getProperty(dsPrefix + ".password");
if (StringUtils.isEmpty(jdbcUrl) || StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) { log.error("jdbc properties invalid,URL:{}, username:{}, password:{}", jdbcUrl, username, password); throw new IllegalArgumentException("jdbc properties invalid!"); } try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) { try (Statement st = conn.createStatement()) { conn.setAutoCommit(false); for (String sql : sqlList) { st.execute(sql); } } catch (Exception e) { conn.rollback(); log.error("table create failure:", e); throw e; } } catch (SQLException e) { log.error("database connection failure:", e); throw e; } } }
|