jdbctemplate
is throwing an error in a Multi-Threaded environment.
I'm using jdbctemplate for inserting data into MySql dB. I am sending a list of User objects to jdbcTemplate.batchUpdate. Can see the values in the DbDAO constructor and run() method, but jdbcTemplate.batchUpdate is throwing a null pointer exception.
@Repository
public class DbDAO implements Runnable {
@Qualifier("jdbcDb")
@Autowired
JdbcTemplate jdbcTemplate;
public String query;
public ArrayList<User> users;
public DbDAO() {
}
public DbDAO(final String query, final ArrayList<User> users) {
this.query = query;
this.users = (ArrayList<User>) users.clone();
System.out.println("## In DbDAO Constructor ##\n" + "Query: " + query + " Users: " + users.toString());
}
@Override
public void run() {
System.out.println(
Thread.currentThread().getId() + " In run **\n" + "Query: " + query + " Users: " + users.toString());
try {
jdbcTemplate.batchUpdate(query, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
User user = users.get(i);
ps.setLong(2, user.getUserId());
ps.setString(3, user.getUserName());
ps.setString(4, user.getUserAddress());
}
@Override
public int getBatchSize() {
return users.size();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
Exception
Query: insert into users (id, name, address) values (?, ?, ?) Users:
[User [userName=Name, userId=81, userAddress=Address], User
[userName=Name, userId=82, userAddress=Address], User [userName=Name,
userId=83, userAddress=Address], User [userName=Name, userId=84,
userAddress=Address] ]
at com.ronan.DbDAO.run(DbDAO.java:52)
at
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at
java.util.concurrent.ThreadPoolExecutor.runWorker
(ThreadPoolExecutor.java:1149)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run
(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerException
at com.ronan.DbDAO.run(DbDAO.java:52)
at
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
Found out what the issue was, sometime back. Just wanted to post this answer, so that it might be useful to someone.
Issue was with the Datasource configuration. Fixed that. :
@Bean(name="dbone")
public DataSource createDbDatasource() {
DriverManagerDataSource dataSource = new
DriverManagerDataSource();
dataSource.setUrl(datasourceOneUrl);
return dataSource;
}
@Bean(name="jdbcDb")
@Autowired
public JdbcTemplate createJdbcTemplate(@Qualifier("dbone")
DataSource dbOneDS) {
return new JdbcTemplate(dbOneDS);
}