I have started working on a project in which I have two tables in a different database with different schemas. So I will be having two different connection parameters to connect to the database. And after connecting to each database, I need to insert in those two tables using the sql given in corresponding table.
And I am supposed to insert in all the two tables or any one of them using JDBC depending on the command line parameters. So that means a single thread will be inserting into Table1 and Table2 or any one of them.
Command Line Parameters:- Here 10 is number of threads, 100 is number of tasks, table1 and table2 are table names.
10 100 table1 table2
Below is my code. In this code what will happen is- suppose if we are passing only one table named table1, then it will insert into that table by using the SQL meant for table1.
And also I need to insert same id in both table1 and table2 and that id is being passed as AtomicInteger to Constructor Task. So that means if id is 1, then this 1 id should be there both in table1 and table2.
final AtomicInteger id = new AtomicInteger(1);
ExecutorService service = Executors. newFixedThreadPool(noOfThreads);
for (int i = 0; i < noOfTasks * noOfThreads; i++) {
for (String arg : tableNames) {
String url = (String) prop.get(arg + ".url");
String user = (String) prop.get(arg + ".user");
String password = (String) prop.get(arg + ".password");
String driver = (String) prop.get(arg + ".driver");
String suffix = (String) prop.get(arg + ".suffix");
String sql = (String) prop.get(arg + ".sql");
service.submit( new Task(id, url, user, password, driver, sql, suffix));
}
}
Below is the Task class that implements Runnable interface
class Task implements Runnable {
private final AtomicInteger id ;
private final String url ;
private final String username ;
private final String password ;
private final String sql ;
private final String driver ;
private final String suffix ;
public Task(AtomicInteger id, String url, String user, String password, String driver, String sql, String suffix) {
this.id = id;
this.url = url;
this.username = user;
this.password = password;
this.driver = driver;
this.sql = sql;
this.suffix = suffix;
}
@Override
public void run() {
try {
dbConnection = getDBConnection(url , username , password , driver );
callableStatement = dbConnection .prepareCall(sql);
int userId = id .getAndIncrement();
callableStatement.setString(1, String.valueOf(userId));
//other callableStatement
callableStatement.executeUpdate();
}
}
So If I am running the above program with multiple threads like Number of Threads as 10 and Number of Tasks as 1000 and id if I choose as 1.
Then in both the tables same id is not there, meaning id 1 will be there only in one table either table1 or table2. The only reason I can think of is- id is AtomicInteger so everytime it will get a new id for each thread. Is there any way I can use the same id to insert in each of the tables? And then making sure id is PrimaryKey so each thread will get a new id if it is inserting again in those tables.
If I understand you correctly, you should define the counter as static to avoid duplicate
PrimaryKey:Then move the increment code to the main loop like this(do not forget to remove the
int userId = id .getAndIncrement();in theTaskclass):Besides, as the
idcounter is kept in memory, you might need to persistent it, otherwise it would be reset to 0 after restarting your application.