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();};
}
)
I am making board and now trying to make search function.
but values doesn't come out if I search keyword
I have tried to run on oracle with printed sql and parameter(optionText,searchText..) it worked fine but result set doesnt have value
public List<boardVO> getBoardList(String optionText,String searchText,int totalNum , int nowPage){
List<boardVO> list = new ArrayList<boardVO>();
try {
connectDB();
String sql = "select * from "
+ "(select rownum as rnum,recordno,userid,title,content,views,regdate from";
if(optionText!=null && !optionText.equals("") && searchText!=null &&!searchText.equals("")) {
sql += " (select * from boardlist where ? like ?))";
}else{
sql += " boardlist)";
}
sql += "where rnum>=? and rnum<=? order by recordno desc";
pstmt = conn.prepareStatement(sql);
int finalNum = totalNum -(5*(nowPage-1));
if(optionText!=null && !optionText.equals("") && searchText!=null &&!searchText.equals("")) {
pstmt.setString(1, optionText);
pstmt.setString(2, "%"+searchText+"%");
if(finalNum>4) {
pstmt.setInt(3, finalNum-4);
pstmt.setInt(4, finalNum);
}else {
pstmt.setInt(3, 1);
pstmt.setInt(4, finalNum);
}
}else {
pstmt.setInt(1, finalNum-4);
pstmt.setInt(2, finalNum);
}
rs = pstmt.executeQuery();
while(rs.next()) {
boardVO vo = new boardVO();
System.out.println("while");
vo.setRecordNo(rs.getInt(2));
vo.setUserid(rs.getString(3));
vo.setTitle(rs.getString(4));
vo.setContent(rs.getString(5));
/* System.out.println(vo.getContent()); */
vo.setViews(rs.getInt(6));
vo.setRegdate(rs.getString(7));
list.add(vo);
}
} catch (Exception e) {
System.out.println("get board list error");
e.printStackTrace();
}finally {
closeDB();
}
return list;
}
I think this is your problem:
(select * from boardlist where ? like ?)
It looks like you are trying to pass both a column name and a searchable value to your query: you can't do this with parameters. Both assignments will be treated as literals, so your executed code will be something like this:
select * from boardlist where 'COLUMN_NAME` like '%some string%'
Perfectly valid SQL, just won't return any results.
If this is the case you need to change the assemblage of the statement to include the column name ...
if(optionText!=null && !optionText.equals("") && searchText!=null &&!searchText.equals("")) {
sql += " (select * from boardlist where " + optionText + " like ?))";
}else{
... and remove the parameter assignment:
if(optionText!=null && !optionText.equals("") && searchText!=null &&!searchText.equals("")) {
pstmt.setString(1, "%"+searchText+"%");
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.
I have the below code whose sql script works perfectly on sql developer but when used in java code i.e
String MergeSQLMapping = "MERGE INTO test.test_table USING dual ON (CLN_POL_CODE = 22222) "
+ "WHEN MATCHED THEN "
+ "UPDATE SET COMPANY_NAME = 'kevin', POL_ID = '22222', MAPPED_BY = '22222' "
+ "WHEN NOT MATCHED THEN INSERT (COMPANY_NAME, POL_ID, CLN_POL_CODE, MAPPED_BY) "
+ "VALUES ('kevin', '22222', '22222', 'workerservice'); ";
System.out.println(MergeSQLMapping);
dbMergeConnection = DBConnection.getStagingConnection();
try {
PreparedStatement ps = dbMergeConnection.prepareStatement(MergeSQLMapping);
ps.execute();
dbMergeConnection.commit();
ps.close();
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
}
i get the following error
ORA-00933: SQL command not properly ended
Any help accorded will be appreciated.
sql3 = "select avg(eff),min(eff),max(eff) from(select ("+baseParam+"/"+denom+"))as eff from ras)as s"; This is query whose output i want.
When i execute the code i get the error stating check your mysql version for syntax. I am using string to store the name of columns. I want to find the efficienccy with respect to 2000 Job_Render i.e. efficiency for each job_render. But what i get is total efficiency of all job_render. when i use the sql syntax with their direct column names. I have commented that query too for the reference. I want to find efficiency of each job render with respect to their 2000 JOBID. Bottom line is i want to find efficiency of 2000 JOBID each whose formula is Job_Render/LC_Final+LC_Preview. I have stored Job_Render in String baseParam and sum of both LC in String Denom. Please help me out.
public class Efficiency {
static final String DB_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_CONNECTION = "jdbc:mysql://localhost:3306/";
static final String DB_USER = "root";
static final String DB_PASSWORD = "root";
static final String dbName = "raas";
public static void main(String[] args) {
try{
effFunc();
}
catch (Exception q){
q.getMessage();
}
}
static void effFunc() throws ClassNotFoundException,SQLException{
Connection conn = null;
// STEP 2: Register JDBC driver
Class.forName(DB_DRIVER);
// STEP 3: Open a connection
System.out.println("Connecting to a selected database...");
conn = DriverManager.getConnection(DB_CONNECTION + dbName, DB_USER,
DB_PASSWORD);
System.out.println("Connected database successfully...");
String baseParam;
//String[] subParam ;
baseParam= "Job_Render";
String sql3="";
String denom="";
final String[] COL={ "LC_Final","LC_Preview"};
denom = "(" + COL[0] + "+" + COL[1] + ")";
Statement stmt = null;
stmt = conn.createStatement();
// sql3 = "select 'Efficiency' Field,avg(eff),min(eff),max(eff) from(select (Job_Render/(LC_Final+LC_Preview))as eff from ras)as s";
sql3 = "select avg(eff),min(eff),max(eff) from(select ("+baseParam+"/"+denom+"))as eff from ras)as s";
System.out.println(sql3);
//
try{
ResultSet res = stmt.executeQuery(sql3);
//System.out.println(res);
while(res.next()){
// String JobID = res.getString("JobID");
// System.out.println("Job ID : " + JobID);
String col1 = res.getString(1);
System.out.println(col1);
double avg = res.getDouble(2);
System.out.println("Average of eff is:"+avg);
double min = res.getDouble(3);
System.out.println("Min of eff is:"+min);
double max = res.getDouble(4);
System.out.println("Max of eff is:"+max);
}}
catch(Exception e){
e.getStackTrace();
System.out.println(e.getMessage());
}
}}
Your code runs the query sql1 which is the empty string,
String sql1="";
// sql1 = "select * from raas.jobs";
ResultSet res = stmt.executeQuery(sql1); // sql1 = ""
should be
ResultSet res = stmt.executeQuery(sql3);
Edit
Then to get the value(s)
String col1 = res.getString(1);
double avg = res.getDouble(2);
double min = res.getDouble(3);
double max = res.getDouble(4);