我正在做一个项目,其中我在不同的数据库中有两个具有不同模式的表。所以这意味着我有两个不同的连接参数让这两个表使用 JDBC-
让我们假设下面是config.property
文件 -
TABLES: table1 table2
#For Table1
table1.url: jdbc:mysql://localhost:3306/garden
table1.user: gardener
table1.password: shavel
table1.driver: jdbc-driver
table1.percentage: 80
#For Table2
table2.url: jdbc:mysql://otherhost:3306/forest
table2.user: forester
table2.password: axe
table2.driver: jdbc-driver
table2.percentage: 20
下面的方法将阅读上述内容config.property file
并ReadTableConnectionInfo object
为每个表格制作一个。
private static HashMap<String, ReadTableConnectionInfo> tableList = new HashMap<String, ReadTableConnectionInfo>();
private static void readPropertyFile() throws IOException {
prop.load(Read.class.getClassLoader().getResourceAsStream("config.properties"));
tableNames = Arrays.asList(prop.getProperty("TABLES").split(" "));
for (String arg : tableNames) {
ReadTableConnectionInfo ci = new ReadTableConnectionInfo();
String url = prop.getProperty(arg + ".url");
String user = prop.getProperty(arg + ".user");
String password = prop.getProperty(arg + ".password");
String driver = prop.getProperty(arg + ".driver");
double percentage = Double.parseDouble(prop.getProperty(arg + ".percentage"));
ci.setUrl(url);
ci.setUser(user);
ci.setPassword(password);
ci.setDriver(driver);
ci.setPercentage(percentage);
tableList.put(arg, ci);
}
}
下面的ReadTableConnectionInfo
类将保存特定表的所有表连接信息。
public class ReadTableConnectionInfo {
public String url;
public String user;
public String password;
public String driver;
public String percentage;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDriver() {
return driver;
}
public void setDriver(String driver) {
this.driver = driver;
}
public double getPercentage() {
return percentage;
}
public void setPercentage(double percentage) {
this.percentage = percentage;
}
}
现在我正在为指定数量的线程创建 ExecutorService 并将其传递给类tableList object
的构造函数-ReadTask
// create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
service.submit(new ReadTask(tableList));
}
下面是我ReadTask
的实现Runnable interface
,其中每个线程都应该为每个表建立连接。
class ReadTask implements Runnable {
private final HashMap<String, XMPReadTableConnectionInfo> tableLists;
public ReadTask(HashMap<String, ReadTableConnectionInfo> tableList) {
this.tableLists = tableList;
}
@Override
public void run() {
int j = 0;
dbConnection = new Connection[tableLists.size()];
statement = new Statement[tableLists.size()];
//loop around the map values and make the connection list
for (ReadTableConnectionInfo ci : tableLists.values()) {
dbConnection[j] = getDBConnection(ci.getUrl(), ci.getUser(), ci.getPassword(), ci.getDriver());
statement[j] = dbConnection[j].createStatement();
j++;
}
while (System.currentTimeMillis() <= 60 minutes) {
/* Generate random number and check to see whether that random number
* falls between 1 and 80, if yes, then choose table1
* and then use table1 connection and statement that I made above and do a SELECT * on that table.
* If that random numbers falls between 81 and 100 then choose table2
* and then use table2 connection and statement and do a SELECT * on that table
*/
ResultSet rs = statement[what_table_statement].executeQuery(selectTableSQL);
}
}
}
目前我有两个表,这意味着每个线程将为每个表建立两个连接,然后根据随机生成数使用该特定表连接在该表上执行 SELECT *。
算法:-
- 生成 1 到 100 之间的随机数。
- 如果该随机数小于
table1.getPercentage()
然后选择table1
然后用于对该数据库table1 statement object
进行创建。SELECT sql call
- 否则选择
table2
然后使用该数据库table2 statement object
创建一个。SELECT sql call
我的问题-
我很难弄清楚应该如何应用上述算法以及我应该如何比较random number
每个tables percentage
表,然后决定我需要使用哪个表,然后确定我需要使用哪个表table connection and statements
来制作SELECT sql call
.
所以这意味着我需要检查getPercentage()
每个表的方法,并将它们与随机数进行比较。
现在我只有两个表,将来我可以有三个表,百分比分布可能是80 10 10
.
更新:-
class ReadTask implements Runnable {
private Connection[] dbConnection = null;
private ConcurrentHashMap<ReadTableConnectionInfo, Connection> tableStatement = new ConcurrentHashMap<ReadTableConnectionInfo, Connection>();
public ReadTask(LinkedHashMap<String, XMPReadTableConnectionInfo> tableList) {
this.tableLists = tableList;
}
@Override
public run() {
int j = 0;
dbConnection = new Connection[tableLists.size()];
//loop around the map values and make the connection list
for (ReadTableConnectionInfo ci : tableLists.values()) {
dbConnection[j] = getDBConnection(ci.getUrl(), ci.getUser(), ci.getPassword(), ci.getDriver());
tableStatement.putIfAbsent(ci, dbConnection[j]);
j++;
}
Random random = new SecureRandom();
while ( < 60 minutes) {
double randomNumber = random.nextDouble() * 100.0;
ReadTableConnectionInfo table = selectRandomConnection(randomNumber);
for (Map.Entry<ReadTableConnectionInfo, Connection> entry : tableStatement.entrySet()) {
if (entry.getKey().getTableName().equals(table.getTableName())) {
final String id = generateRandomId(random);
final String selectSql = generateRandomSQL(table);
preparedStatement = entry.getValue().prepareCall(selectSql);
preparedStatement.setString(1, id);
rs = preparedStatement.executeQuery();
}
}
}
}
private String generateRandomSQL(ReadTableConnectionInfo table) {
int rNumber = random.nextInt(table.getColumns().size());
List<String> shuffledColumns = new ArrayList<String>(table.getColumns());
Collections.shuffle(shuffledColumns);
String columnsList = "";
for (int i = 0; i < rNumber; i++) {
columnsList += ("," + shuffledColumns.get(i));
}
final String sql = "SELECT ID" + columnsList + " from "
+ table.getTableName() + " where id = ?";
return sql;
}
private ReadTableConnectionInfo selectRandomConnection(double randomNumber) {
double limit = 0;
for (ReadTableConnectionInfo ci : tableLists.values()) {
limit += ci.getPercentage();
if (random.nextDouble() < limit) {
return ci;
}
throw new IllegalStateException();
}
return null;
}
}