I have a java application which is connected to an Oracle database. I have a form where the user enters an ID called COMMUNITY_ID, a start date called START_DATE and an end date called END_DATE.
I want the application to search through the table in database for the entered values, and when the search result is correct I want it to display the sum of total values.
I have three methods; each method is responsible for searching a single text box. For example, the first method total 1 searches for the COMMUNITY_ID, and the second method searches for the START_DATE and the last one searches for the END_DATE.
I get an error message saying the result set is empty or closed. I am not sure why because I dont understand the message clearly.
The following is my code. If anyone has idea how to fix it that, please help me.
public void total3()
{
ResultSet result;
System.out.println("total 3");
String endDate = this.EndTxtBox.getText();
try
{
rs=st.executeQuery("select RECIPT_ID,COMMUNITY_ID,VALUE,START_DATE,END_DATE, ITEM_BOUGHT,REASON from RECIPTS where END_DATE = '" +endDate+"'");
//display();
this.EndTxtBox.setText(rs.getString("END_DATE"));
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null, "Searched Failed" + ex);
}
try
{
result = rs=st.executeQuery("select SUM(VALUE)from RECIPTS where END_DATE = '" +endDate+"'" );
//result = rs=st.executeQuery("select RECIPT_ID,COMMUNITY_ID,VALUE,START_DATE,END_DATE, ITEM_BOUGHT,REASON,SUM(VALUE)from RECIPTS group by RECIPT_ID,COMMUNITY_ID,VALUE,START_DATE,END_DATE, ITEM_BOUGHT,REASON ");
}
catch(Exception ex)
{
JOptionPane.showMessageDialog(null, "Error" + ex);
}
}
Any ideas, please? What is wrong with it?
You're trying to read from the result set before going to its first row:
if (rs.next()) {
endDate = rs.getString("END_DATE");
}
Your code is full of bad practices:
mixing UI code with database access code
catching Exception
selecting a whole lot of rows and columns when you're only interested by one of them
not using prepared statements
using both result and rs for the same thing
not closing statements and result sets
using String variables to store dates
poor and inconsistent indentation
Related
I need a second pair of eyes on some code. I feel like there's something simple I'm missing. I have a table in my MariaDB called jeff_tables, which contains 4 entries. I've created a utility thread that runs the following code inside the run method:
try {
getConnection();
String query = "SELECT * FROM jeff_tables";
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery(query);
//rs.last(); //returns 4 rows
//System.out.println("result set size: " + rs.getRow() );
while(rs.next()) {
Integer tenant = rs.getInt("TENANT_ID");
String table = rs.getString("TABLE_NAME");
System.out.println("Inserting k-v pair: " + tenant + " " + table);
tableNames.put(tenant, table);
}
} catch (SQLException e) {
e.printStackTrace();
}
When I uncomment the rs.last() and rs.getRow() lines, it returns 4, which is the correct number of entries it should return. However, what's actually happening is it enters my while loop, prints the correct values for the first row, then throws a null pointer on the put statement. I've also tried running this code outside of a thread, but it's doing the same thing. Any advice would be greatly appreciated. Thanks in advance.
As soon as I posted this, I saw the problem. This was just a simple instance of forgetting to instantiate the HashMap before trying to insert values into it. It's funny how sometimes it takes posting a question to open your eyes.
I have one script which fetches around 25.000 different ID values and uses them to make some changes in other table. But the programmer created this code which searches ID (dialid in the code) through the table of 10 million records (line 3) and every query in loop is executing around 1 second. My idea is to fetch last 30 days of records with the SQL and to put it into an array and check only the array.
And my question is, how to do that in Java? Is it the in_array function? I'm solid in PHP, but beginner in Java code...
private Integer getDialId(int predictiveId) {
Integer dialid = null;
StringBuilder sql = new StringBuilder("SELECT dialid from dial where PREDICTIVE_DIALID=");
sql.append(predictiveId); //this predictiveId is calculated in other part of code
ResultSet rsDialId = null;
Statement s1 = null;
try {
s1 = oracle.getConn().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE, ResultSet.CLOSE_CURSORS_AT_COMMIT);
rsDialId = s1.executeQuery(String.valueOf(sql));
if (rsDialId.next()) {
dialid = rsDialId.getInt("dialid");
}
} catch (SQLException ex) {
Logger.getLogger(MediatelCdrSync.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
if (s1 != null) {
s1.close();
}
if (rsDialId != null) {
rsDialId.close();
}
} catch (SQLException ex) {
Logger.getLogger(MediatelCdrSync.class.getName()).log(Level.SEVERE, null, ex);
}
}
System.out.println("DIALID = " + dialid);
return dialid;
}
Thnx
If you have a performance problem I'd start to see why the query takes one second per execution, if it's database time because the dial table does not have and index on PREDICTIVE_DIALID column you can do very little at the java level.
Anyway the jdbc code reveals some problems especially when used with an oracle database.
The biggest issue is that you are hardcoding your query parameter causing Oracle to re"hard parse" the query every time; the second (minor one) is that the resultset is scrollable and updatable while you need only to load the first row. If you want to make some little modification to your code you should change to somethig like this pseudo code:
PreparedStatement ps =connection.prepareStatement("SELECT dialid from dial where PREDICTIVE_DIALID=?");
for (int i=0;i<10;i++) {//your 25000 loop elements is this one
//this shoudl be the start of the body of your getDialId function that takes also a prepared statement
ps.setInt(1, i);
ResultSet rs=ps.executeQuery();
if (rs.next()) {
rs.getInt("dialid");
}
rs.close();
//your getDialId end here
}
ps.close();
With this minimal java solution you should note a performance increase, but you must chek the performance of the single query since if there is a missing index you cand very little at a java code.
Another solution, more complicated, is to to create a temporart table, fill it with all the 25000 predictiveId values and then issue a query that joins dial and you temporary table; so with one resultset(and one query) you can find all the dialid you need. A jdbc batch insert into the temp table speeds up insertion time noticeably.
If you are planning to fetch less record and store that result in some array then
I think it is better for you to limit your search by creating a view in Database with limited record's (say record for last 2 year's)
And Use that view in your select query
"SELECT dialid from dial_view WHERE PREDICTIVE_DIALID = "
Hope it will help :)
I am trying to retrieve records from oracle database for the SQL query - SELECT data FROM test where id = ?;
Here is my code to retrieve the data -
public static String retrieveData(String id) throws IOException {
String result = "";
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT data FROM test where id = ?";
connection = getDBConnection(); //this method gets the db connection
ps = connection.prepareStatement(sql);
ps.setString(1, id);
rs = ps.executeQuery();
while(rs.next()) {
result = result + rs.getString("data");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeDBConnection(); //closes db connection
}
return result;
}
When I invoke the retrieveData in the main method, it returns null. When I debug, the resultSet is empty. I am guessing the reason is I am passing my id as String, but perhaps Oracle doesn't understand something like - SELECT data FROM test where id = "1234567890";
Can someone please guide me how do I fix this? I have tried way too many things, but I can't seem to fetch the data from the db for this id. I also tried converting the id to long using Long.valueOf(String s).longValue(); and setting this as the placeholder in ps.setLong, but it didn't help. Please advise.
Type issue of id column
This is probably due to spacing difference or another subtle difference that gives the impression that they are the same.
The strings ' 123 ' or '00123' (for example) are not equivalent to '123' in VARCHAR2 type, while they are equivalent in NUMERIC type, as Oracle converts all those strings to the numeral 123.
You are better off using a NUMERIC column as your id to avoid such problems. It also makes sense to limit your valid id values to whole numbers, rather than any arbitrary string.
With Oracle you can continue to use setString as it will automatically cast the string to an integer. But I recommend you to use setInt or setLong instead (after the conversion of the id column), as other database solutions like Postgres will not accept a string to match a NUMERIC column.
Exception handling issue
When you catch a Throwable or an Exception (or their subtypes), be sure to think about whether it can be ignored, or it must be thrown for further handling (for example, to stop the program, alert the user or correct the problem).
In your code, the catch block catches the SQLException and prints the stack trace. But it doesn't do anything else.
} catch (SQLException e) {
e.printStackTrace();
} ...
This means that you are ignoring the exception and continuing the program as though nothing happened. The execution will continue on to return result; after completing the finally block.
The caller of your method will never know that an SQLException occurred, and it will wrongly assume that there were no errors and the returned data is correct.
Unless that is what you really want, what you ought to do is as follows:
} catch (SQLException e) {
e.printStackTrace(); //it doesn't matter what you do here. the next line is what's important.
throw e; //throw the exception after printing stack trace, logging, etc.
} ...
In this case your method will throw the SQLException to the caller after completing the finally block. The execution will not continue to return result;.
This way the caller of your method will receive the exception and know that an error has occurred. The caller can then act accordingly; for example, by stopping the program, alerting the user or retrying the method with a different input.
may be the reason is DEBUG. if you have a breakpoint on the line "while(rs.next())" and you watch/inspect it then then rs increments one. Then the code executes rs.next for the second time where there is no record.
maybe...
You shouldn't use datatype 'String' for id field, it can cause serious trouble. Try to covert it to numeric datatype is possible but why don't you use numeric at first. You should change to int or bigint. In additional try to catch exception like this:
try{
}catch(SQLException ex){
System.out.println("Error at:" +ex.getClass().getName() + ex.getMessage());
}
Try it again, if you can't debug it and find out why! Good luck!
Please try this. Remove all the spaces when defining field name with a ? and check
SELECT data FROM test where id=?
I am making a GUI and I need to update one column called "OCCURRENCES" whenever a patient needs help. I am using Netbeans (Java). For some reason I am not getting any errors. But My table does not Update. The executeUpdate is returning '0'. I have close all my result set statements and prepared statements at the end of the 'try', 'catch'.Also any other updates like updating from textfields, insertion of new patient and deleting patient from a table is working fine; just having problem with updating this column which initial value I have set to be zero whenever an occurrence happens I would like to call this method to increment value on column. I'm just learning to use sqlite, and I am really confuse please help here is the part of the code I am having problems with, Also it reaches the JOPtionPane message successfully.
try
{
conn = javaConnect.ConnectDB();//Returns Connection
PreparedStatement pst = conn.prepareStatement("UPDATE PEMs SET OCCURRENCES = ? "//1
+ "WHERE ROOM = ?");//2
pst.setInt(1, 1);
pst.setInt(2,1);
pst.executeUpdate();
int updated=pst.executeUpdate(); // get count to see if anything was updated
System.out.println("OCC" + updated);
JOptionPane.showMessageDialog(null, "SUCCESSFULL OCCURRENCE");
}
catch (Exception e){
JOptionPane.showMessageDialog(null, "Error UpdateOccurence :" + e);
e.printStackTrace();`enter code here`
}finally {
try{
rs.close(); pst.close(); }
catch(Exception e) { } }
My JAVA script consists of 2 JAVA classes: RMS, queryRMS
In the RMS class I call the method in the queryRMS class
RMS Java Class (I left out the start execution part, below is just the method)
for (int i = 1; i <= itemCount; i++) {
GlobalVariables.numberRow = i;
JavaDatapool.settings();
String item = queryRPM.connectDB_Multi(configFile,"SELECT ITEM FROM ORDSKU WHERE ORDER_NO = '" + orderNo + "' ORDER BY ITEM ASC",i);
JavaDatapool.writeXLS("item",item,GlobalVariables.sheetXLS);
sleep(1);
}
queryRMS JAVA class
public static String connectDB_Multi(String configFile, String query, int i) throws FileNotFoundException, IOException, SQLException, ClassNotFoundException{
Properties p = new Properties();
p.load(new FileInputStream(configFile));
String serverName = (p.getProperty("RMS_DBServerName"));
String portNumber = (p.getProperty("RMS_PortNumber"));
String sid = (p.getProperty("RMS_SID"));
String url = "jdbc:oracle:thin:#//" + serverName + ":" + portNumber + "/" + sid;
String username = (p.getProperty("RMS_Username"));
String password = (p.getProperty("RMS_Password"));
// jdbc:oracle:thin:#//localhost:1521/orcl
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection connection = DriverManager.getConnection(url,username,password);
String setr = null;
try {
Statement stmt = connection.createStatement();
try {ResultSet rset = stmt.executeQuery(query);
try {
while(rset.absolute(i))
setr = rset.getString(1);
return setr;
}
finally {
try { rset.close();
}
catch (Exception ignore) {}
}
}
finally {
try { stmt.close();
}
catch (Exception ignore) {}
}
}
finally {
try { connection.close();
}
catch (Exception ignore) {}
}
}
So what it does is call the connectDB_multi class and then returns the String where the next part is saving it inside an Excel worksheet.
The loop should return all rows, one at a time and then save it inside the Excel worksheet.
In the second time in loop the query is faulted, eventhough the query should return 1 column consisting of 2 rows.
the original contained the part while(rset.next()) instead of while(rset.absolute(i))
but next only return the first row everytime. so the script works when only one column and row is retrieved from the Database.
Your logic looks a bit messed up.
Look at the first loop you posted. You are, effectivly, executing:
SELECT ITEM FROM ORDSKU WHERE ORDER_NO = '" + orderNo + "' ORDER BY ITEM ASC
itemCount number of times. Each time you execute it, you are attempting to access the n:th row, n being loop counter. Do you see a problem there? How do you know that the query will return itemCount number of rows? Because if it doesn't, it will fail since you are attempting to access a row that doesn't exist.
What I suspect you WANT to do is something like this
Statement stmt = connection.createStatement();
ResultSet rset = stmt.executeQuery(query);
while(rset.next()) {
JavaDatapool.writeXLS("item",rset.getString(1),GlobalVariables.sheetXLS);
}
You should also seriously consider using some form of connection pooling to avoid having to re-open new connections all the time as that is a pretty time-consuming operation.
This code seems very inefficient, for each row you want to fetch from the database you read a property file, create a connection, select all matching rows, skip ahead to the row you want and return just that row. (Or at least I think that is what you are trying to do).
Your code
while(rset.absolute(i))
setr = rset.getString(1);
is probably an infinite loop as it will continue to go to the same row as long as it is ok to go to that row, so either that row does not exist (and the while exists) or the row does exist (and while continues forever).
You should probably restructure your program to only do one select and read all rows that you want and store them in your excel file. While doing this, you can debug to see if you actually are getting the data you expect.
Apart from the inefficient code of creating new connections and querying once for each row, how do you know how many rows you want?
I think in the end you want something like this
....
while(rset.next()) {
JavaDatapool.writeXLS("item",item,GlobalVariables.sheetXLS);
}
And what is the sleep(1) support to accomplish?
FYI: if you open and close statement too often as your logic or pap's solution, you can get the " java.sql.SQLException: ORA-01000: maximum open cursors exceeded" error message.
I suggest you to not do 'too much generalize'. I saw a lot of OOP programmers overdid generalization and that is painful. You should design by a goal and the goal should not be 'just alignment' nor 'code look beautiful', it has to have a purpose for designing.