Insert/update to multiple DB connections in loop using JDBC PreparedStatement - jdbc

I am working on a program which is supposed to do inserts/updates to a DB table using JDBC program. Inserts/updates need to happen to 2 separate DB instances. There is an input XML file which is read by program, input file has about 1800 records. For each record, I need to do updates as per record read from XML file if record already exists in DB. Do insert otherwise. I am using below program to do the work and it doesn't give consistent results when I execute the program. Looks like PreparedStatement for DB2 in if and else section is actually pointing to DB1 because after successful insert/update to DB1 for the first record, it fails to do the same for DB2 saying primary key violation but DB2 is a different connection and I don't have the record there so primary key violation for DB2 doesn't make sense! Seems that connection information is getting mixed somehow.
Below is how the program looks. I have given only relevant sections of the program. PreparedStatment2 and PreparedStatement4 are not giving expected results. Please note that I have verified connection2 and that's indeed pointing to DB2 and not DB1. Weird thing is that every time I execute the program, it starts working for the record which didn't work in last execution so each program execution gets me past the issue of 1 record in loop and start giving the problem for next one! Can someone help me understanding why PreparedStatement2 and 4 are not working as expected for DB2?
Thanks,
Chanchal
Connection connection1 = null;
Connection connection2 = null;
Statement statement = null;
PreparedStatement preparedStatement1 = null;
PreparedStatement preparedStatement2 = null;
PreparedStatement preparedStatement3 = null;
PreparedStatement preparedStatement4 = null;
ResultSet resultSet1 = null;
try
{
connection1 = DriverManager.getConnection(properties.getProperty(RT_DB1_URL), properties.getProperty(RT_DB1_USER), properties.getProperty(RT_DB1_PWD));
connection2 = DriverManager.getConnection(properties.getProperty(RT_DB2_URL), properties.getProperty(RT_DB2_USER), properties.getProperty(RT_DB2_PWD));
//Get list
for (int temp = 0; temp < list.getLength(); temp++) {
//Get fieldValueA,fieldValueB, fieldValueC, fieldValueD values from a XML file
//Find if record exists in DB
String selectQuery = "select * from table_x where fieldA='" + fieldValueA + "'";
resultSet1 = statement.executeQuery(selectQuery);
if(resultSet1.next()){
// Update table
String query = "update table_x set fieldB = ?,fieldC = ?,fieldD = ? where fieldA = ?";
preparedStatement1 = connection1.prepareStatement(query);
preparedStatement2 = connection2.prepareStatement(query);
preparedStatement1.setString(1, fieldValueB);
preparedStatement1.setString(2, fieldValueC);
preparedStatement1.setString(3, fieldValueD);
preparedStatement1.setString(4, fieldValueA);
int k = preparedStatement1.executeUpdate();
logger.info("Records successfully updated in RT DB1 for fieldA=" + fieldValueA);
//Closing the statement as it exceeds oracle cursor limit otherwise with default cursor limit of 300
if (preparedStatement1 != null) preparedStatement1.close();
preparedStatement2.setString(1, fieldValueB);
preparedStatement2.setString(2, fieldValueC);
preparedStatement2.setString(3, fieldValueD);
preparedStatement2.setString(4, fieldValueA);
int k = preparedStatement2.executeUpdate();
logger.info("Records successfully updated in RT DB2 for fieldA=" + fieldValueA);
//Closing the statement as it exceeds oracle cursor limit otherwise with default cursor limit of 300
if (preparedStatement2 != null) preparedStatement2.close();
}
else{
//Insert to the table
String queryInsert = "insert into table_x(fieldA,fieldB,fieldC,fieldD)";
queryInsert = queryInsert + " values(?,?,?,?)";
preparedStatement3 = connection1.prepareStatement(queryInsert);
preparedStatement4 = connection2.prepareStatement(queryInsert);
preparedStatement3.setString(1, fieldValueA);
preparedStatement3.setString(2, fieldValueB);
preparedStatement3.setString(3, fieldValueC);
preparedStatement3.setString(4, fieldValueD);
int k = preparedStatement3.executeUpdate();
logger.info("Records successfully inserted in RT DB1 for fieldA=" + fieldValueA);
if (preparedStatement3 != null) preparedStatement3.close();
preparedStatement4.setString(1, fieldValueA);
preparedStatement4.setString(2, fieldValueB);
preparedStatement4.setString(3, fieldValueC);
preparedStatement4.setString(4, fieldValueD);
int k = preparedStatement4.executeUpdate();
logger.info("Records successfully inserted in RT DB2 for fieldA=" + fieldValueA);
if (preparedStatement4 != null) preparedStatement4.close();
} // End loop
} catch (Exception e) {
e.printStackTrace();
}
finally{
try { if (resultSet1 != null) resultSet1.close(); } catch (Exception e) {e.printStackTrace();};
try { if (statement != null) statement.close(); } catch (Exception e) {e.printStackTrace();};
try { if (connection1 != null) connection1.close(); } catch (Exception e) {e.printStackTrace();};
try { if (connection2 != null) connection2.close(); } catch (Exception e) {e.printStackTrace();};
}

It is fine, to create the prepared statements before the loop. So they can be reused within every loop. Also you can do batch processing and send all data to the DBs after running all. If there are some 1000 records, it might sense to flush the batch earlier, but 1800 records can be processed within a batch in one time. I could not test this code, but I hope it gives you some hints.
Connection connection1 = null;
Connection connection2 = null;
Statement statement = null;
PreparedStatement preparedStatement1 = null;
PreparedStatement preparedStatement2 = null;
PreparedStatement preparedStatement3 = null;
PreparedStatement preparedStatement4 = null;
ResultSet resultSet1 = null;
try
{
connection1 = DriverManager.getConnection(properties.getProperty(RT_DB1_URL), properties.getProperty(RT_DB1_USER), properties.getProperty(RT_DB1_PWD));
connection2 = DriverManager.getConnection(properties.getProperty(RT_DB2_URL), properties.getProperty(RT_DB2_USER), properties.getProperty(RT_DB2_PWD));
// Update table
String query = "update table_x set fieldB = ?,fieldC = ?,fieldD = ? where fieldA = ?";
preparedStatement1 = connection1.prepareStatement(query);
preparedStatement2 = connection2.prepareStatement(query);
String queryInsert = "insert into table_x(fieldA,fieldB,fieldC,fieldD)";
queryInsert = queryInsert + " values(?,?,?,?)";
preparedStatement3 = connection1.prepareStatement(queryInsert);
preparedStatement4 = connection2.prepareStatement(queryInsert);
//Get list
for (int temp = 0; temp < list.getLength(); temp++) {
//Get fieldValueA,fieldValueB, fieldValueC, fieldValueD values from a XML file
//Find if record exists in DB
String selectQuery = "select * from table_x where fieldA='" + fieldValueA + "'";
resultSet1 = statement.executeQuery(selectQuery);
if(resultSet1.next()){
preparedStatement1.setString(1, fieldValueB);
preparedStatement1.setString(2, fieldValueC);
preparedStatement1.setString(3, fieldValueD);
preparedStatement1.setString(4, fieldValueA);
preparedStatement1.addBatch();
logger.info("Records successfully added RT DB1 for fieldA=" + fieldValueA);
preparedStatement2.setString(1, fieldValueB);
preparedStatement2.setString(2, fieldValueC);
preparedStatement2.setString(3, fieldValueD);
preparedStatement2.setString(4, fieldValueA);
preparedStatement2.addBatch();
logger.info("Records successfully added in RT DB2 for fieldA=" + fieldValueA);
}
else{
//Insert to the table
preparedStatement3.setString(1, fieldValueA);
preparedStatement3.setString(2, fieldValueB);
preparedStatement3.setString(3, fieldValueC);
preparedStatement3.setString(4, fieldValueD);
preparedStatement3.addBatch();
logger.info("Records successfully added RT DB1 for fieldA=" + fieldValueA);
if (preparedStatement3 != null) preparedStatement3.close();
preparedStatement4.setString(1, fieldValueA);
preparedStatement4.setString(2, fieldValueB);
preparedStatement4.setString(3, fieldValueC);
preparedStatement4.setString(4, fieldValueD);
preparedStatement4.addBatch();
} // End loop
// now, we are flushing the batch to the DBs
int[] k1 = preparedStatement1.executeBatch();
int[] k2 = preparedStatement2.executeBatch();
int[] k3 = preparedStatement3.executeBatch();
int[] k4 = preparedStatement4.executeBatch();
logger.info("updated " + String.format("%,d",k1.lenght) + " Records in DB1 and " + String.format("%,d",k2.lenght) + " inserted " + String.format("%,d",k3.length) + " Records in DB1 and " + String.format("%,d",k4.length) + " in DB2");
} catch (Exception e) {
e.printStackTrace();
}
finally{
try { if preparedStatement1 != null ) preparedStatement1 } catch (Exception e) {e.printStackTrace();};
try { if preparedStatement2 != null ) preparedStatement2 } catch (Exception e) {e.printStackTrace();};
try { if preparedStatement3 != null ) preparedStatement3 } catch (Exception e) {e.printStackTrace();};
try { if preparedStatement4 != null ) preparedStatement4 } catch (Exception e) {e.printStackTrace();};
try { if (resultSet1 != null) resultSet1.close(); } catch (Exception e) {e.printStackTrace();};
try { if (statement != null) statement.close(); } catch (Exception e) {e.printStackTrace();};
try { if (connection1 != null) connection1.close(); } catch (Exception e) {e.printStackTrace();};
try { if (connection2 != null) connection2.close(); } catch (Exception e) {e.printStackTrace();};
}
)

Related

Problem two query db2 sqlserver is not print output

This is the correct example, which does not work:
If the LANGUAGE column is the same as the LANGUAGE COLUMN and the NLS_CLASS_NAME column is the same as the KEYWORD COLUMN
Given that they are true, if you noticed the language string I turned it into lowercase and I cut the string so that it becomes "en", since it was first ENG
You must print the language list, keyword is translation
I noticed that it takes a long time to start up, then it prints continuously but incorrectly, because it doesn't print the translation in the for loop.
Can you help me kindly?
I noticed that it takes a long time to start up, then it prints continuously but incorrectly, because it doesn't print the translation in the for loop.
Can you help me kindly?
//Traduzione in Db2 a SqlServer
public void getTraduzione() throws Exception {
List<DizioPt> listDizio = new ArrayList<DizioPt>();
List<ClassHdrNls> listHdr = new ArrayList<ClassHdrNls>();
String className = "";
String language = "";
String nlsClassName = "";
String lingua = "";
String keyword = "";
String traduzione = "";
Database database = new Database();
// Db2
Connection dbConnectionDb2 = null;
Statement statementDb2 = null;
// SqlServer
Connection dbConnectionSqlServer = null;
Statement statementSqlServer = null;
// Query Db2
String queryDb2 = "select * from THERA.CLASS_HDR_NLS WHERE
THERA.CLASS_HDR_NLS.LANGUAGE='en'";
// Query SqlServer
String querySqlServer = "select * from DIZIOPT WHERE
DIZIOPT.LINGUA='ENG'";
try {
// Connessione --> SqlServer
dbConnectionSqlServer = database.getConnectionSqlServer();
statementSqlServer = dbConnectionSqlServer.createStatement();
// Connessione -->Db2
dbConnectionDb2 = database.getConnectionDb2();
statementDb2 = dbConnectionDb2.createStatement();
// Risultato SqlServer
ResultSet rsSqlServer = statementSqlServer.executeQuery(querySqlServer);
// Risultato Db2
ResultSet rsDb2 = statementDb2.executeQuery(queryDb2);
while (rsSqlServer.next() && rsDb2.next()) {
ClassHdrNls classHdrNls = new ClassHdrNls();
className = rsDb2.getString("CLASS_NAME");
classHdrNls.setClassName(className);
language = rsDb2.getString("LANGUAGE");
classHdrNls.setLanguage(language);
nlsClassName = rsDb2.getString("NLS_CLASS_NAME");
classHdrNls.setNlsClassName(nlsClassName);
listHdr.add(classHdrNls);
DizioPt diziopt = new DizioPt();
lingua = rsSqlServer.getString("LINGUA");
diziopt.setLingua(lingua);
keyword = rsSqlServer.getString("KEYWORD");
diziopt.setKeyword(keyword);
traduzione = rsSqlServer.getString("TRADUZIONE");
diziopt.setTraduzione(traduzione);
listDizio.add(diziopt);
for (int i = 0; i < listHdr.size(); i++) {
for (int j = 0; j < listDizio.size(); j++) {
if (listHdr.get(i).getNlsClassName().equalsIgnoreCase(listDizio.get(j).getKeyword())
&& listHdr.get(i).getLanguage()
.equalsIgnoreCase(listDizio.get(j).getLingua().toLowerCase().substring(0, 2))) {
System.out.println("Class name: " + listHdr.get(i).getClassName());
System.out.println("Lingua: " + listHdr.get(i).getLanguage());
System.out.println("Testo: " + listHdr.get(i).getNlsClassName());
System.out.println("Traduzione: " + listDizio.get(j).getTraduzione());
}
}
}
}
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
if (statementDb2 != null && statementSqlServer != null) {
statementDb2.close();
statementSqlServer.close();
}
if (dbConnectionDb2 != null && dbConnectionSqlServer != null) {
dbConnectionDb2.close();
dbConnectionSqlServer.close();
}
}
}

SonarQube nonconstant String in SQL statements

I'm scanning my code with SonarQube and I'm getting the following bugs:
-A prepared statement is generated from a nonconstant String
-Nonconstant string passed to execute method on an SQL statement
I have an sql query to which I append based on some conditions.
Example:
PreparedStatement ps = null;
StringBuilder sql = new StringBuilder("UPDATE" + tableName + " SET some_field = ? WHERE a_field = a_value");
if (myObject.getField1() != null) {
sql.append(" AND Field1 = " + myObject.getField1());
}
if (myObject.getField2() != null) {
sql.append(" AND Field2 = " + myObject.getField2());
}
if (myObject.getField3() != null) {
sql.append(" AND Field3 = " + myObject.getField3());
}
if (myObject.getField4() != null) {
sql.append(" AND Field4 = " + myObject.getField4());
}
...
**ps = connection.prepareStatement(sql.toString());** //generating bug
if (myObject.getSomeField() == null) {
ps.setNull(1, nevermind);
} else {
ps.setString(1, myObject.getSomeField());
}
I tried passing a final String = sql.toString(); to the prepareStatement() function and it still generates the bug.
The issue that's being raised is that you're assembling your SQL command with concatenation: which table to update, which columns to set and what values to put in them.
You should find a way to hard code the table and columns and use parameter binding for the values.

running an SQL update statement in java

There are many questions related to this topic, but I couldn't find a solution to my problem.
I have a table of "products" which I am trying to update in netbeans. The SQL statements works in SQL dev, and I have double checked my connection etc.
update products
set pvolume = 2, pprice = 15
where productid = 3;
output: 1 rows updated.
but running in netbeans it won't execute. If I have missed some small syntax issue I apologize, but I really need help with this method.
public boolean editProduct(int ID, String name, int volume, int quantity, String description, int price) {
boolean success = false;
Connection con = ConnectionTools.getInstance().getCurrentConnection();
String SQLString1 = "UPDATE products "
+ "SET pname = ?, "
+ "pvolume = ?, "
+ "pquantity = ?, "
+ "pdescription = ?, "
+ "pprice = ? "
+ "WHERE productID = ?";
PreparedStatement statement = null;
try {
statement = con.prepareStatement(SQLString1);
statement.setString(1, name);
statement.setInt(2,volume);
statement.setInt(3, quantity);
statement.setString(4, description);
statement.setInt(5, price);
statement.setInt(6, ID);
statement.executeUpdate();
success = true;
}catch (Exception e){
System.out.println("Insertion error!");
System.out.println(e.getMessage());
}finally {
try {
statement.close();
} catch (SQLException e) {
System.out.println("Statement close error!");
System.out.println(e.getMessage());
}
}
return success;
}
Running through the debug it seems to run through the try as far as statement.setInt(6, ID) but then does not execute. Here is the output:
Insertion error!
ORA-00971: missing SET keyword
Any help/advice would be appreciated! Thanks
You have to use brackets: update products set (pvolume = 2, pprice = 15) where productid = 3

Spring JDBC Framework Conditional Prepared Statement

public ResultSet getAdCampaignDetailsbyName(ADCampaignDetails Obj,
Connection conn, ResultSet rs, PreparedStatement pstmt) throws SQLException {
String query = "select adCampaignName,adCampaignId from AdCampaignDetails";
query += " where 1=1 ";
if (Obj.getAdCamapignName() != null)
query += " and adCampaignName = ?";
if (Obj.userId != "")
query += " and userId = ?";
pstmt = conn.prepareStatement(query);
int i = 0;
if (Obj.getAdCamapignName() != null)
pstmt.setString(++i, Obj.getAdCamapignName());
if (Obj.userId != "")
pstmt.setString(++i, Obj.userId);
System.out.println(" Q : " + query);
rs = pstmt.executeQuery();
return rs;
}
I am new to Spring , in this above query, i have used two conditions , How to execute query with condition in Spring JDBC Framework?
You can use SimpleJDBCTemplate.
// SQL query
String query = "select adCampaignName,adCampaignId from AdCampaignDetails where 1=1";
// Map with parameter value
Map<String, Object> parameters = new HashMap<String, Object>();
if (adCampaignName!=null){
parameters.put("adCampaignName ", adCampaignName );
query += " AND adCampaignName = :adCampaignName";
}
if (userId!=null){
parameters.put("userId", 1);
query += " AND userId= :userId";
}
// Execute query using simpleJDBC Template
List<AdCampaignDetails> resultList = getSimpleJdbcTemplate().query(query, new customRowMapper(), parameters);
You can build the query string accordingly, just add coresponding entries in map.
Check this link for details.

Problem with cmd.ExecuteNonQuery()

I am inserting values in to Database from a Webform using ADO.NET, C#. DB I am using is Oracle Database. Values are not being inserted and the program gets struck at the cmd.ExecuteNonquery()
Here is my Code below, Please let me know If I am doing any mistake.. I am using some Static Methods will that be any problem ?..
public Boolean AddDivCo(Int32 UserNo,String ID, String Role, String DivName )
{
Boolean ret = false;
OracleCommand cmd = new OracleCommand();
OracleConnection conn = new OracleConnection();
int i = 0;
try
{
conn.ConnectionString = ConfigurationManager.ConnectionStrings["Conn_RIS"].ConnectionString;
conn.Open();
cmd.Connection = conn;
String mySQL = "INSERT INTO R4CAD_ADMIN (AdminUserNo, AdminID, AdminRole, AdminDivName)VALUES(:AdminUserNo,:AdminID,:AdminRole,:DivName)";
OracleParameter p1 = new OracleParameter("AdminUserNo", OracleType.Number);
p1.Value = UserNo;
cmd.Parameters.Add(p1);
OracleParameter p2 = new OracleParameter("AdminID", OracleType.VarChar);
p2.Value = ID;
cmd.Parameters.Add(p2);
OracleParameter p3 = new OracleParameter("AdminRole", OracleType.VarChar);
p3.Value = Role;
cmd.Parameters.Add(p3);
OracleParameter p4 = new OracleParameter("DivName", OracleType.VarChar);
p4.Value = DivName;
cmd.Parameters.Add(p4);
cmd.CommandText = mySQL;
i = cmd.ExecuteNonQuery();
if (i != 0)
{
ret = true;
}
else
{
ret = false;
}
}
catch (Exception err)
{
Console.WriteLine(err.Message.ToString());
}
finally
{
cmd.Dispose();
//cmd = null;
//conn = null;
conn.Close();
}
return ret;
}
Is there a primary key defined on this table? If so, then my guess is that you have another session that already has inserted a record with this key, but has not yet terminated the transaction with a commit or rollback. I don't see a commit as part of your code - I assume you're doing that somewhere else?
Execute your code above once more, and while it's hung run the following query from another session:
SELECT
(SELECT username FROM v$session WHERE sid=a.sid) blocker,
a.sid,
' is blocking ',
(SELECT username FROM v$session WHERE sid=b.sid) blockee,
b.sid
FROM v$lock a JOIN v$lock b ON (a.id1 = b.id1 AND a.id2 = b.id2)
WHERE a.block = 1
AND b.request > 0;
This should tell you if you're being blocked by another session and what the SID is of that session.

Resources