Please don't suggest me to use InternalFrame or Dialogs. I can't start the project from beginning.
Theme: I'm building a GUI program to display mark-sheet. I've taken 3 JFrames & 1 simple class...
Frame1.java
It's having 1 JTextField to enter roll_no. & 2 buttons to feedData in DB & showResult. feedData button calls Frame2 & showResult button calls Frame3.
Frame2.java
For feeding data have several JTextFields & Buttons that transfer content to mySQL DB.
Frame3.java
is a result window that fetches content from DB.
Support.java
Contains static variables & getter-setter methods for them
.....
.....//contains in Support.java
public boolean add() {
query = "Insert into table1 (enroll,Sname,Fname,sub1,sub2,sub3,sub4,sub5 )values(?,?,?,?,?)";
try {
PreparedStatement psmt = conn.prepareStatement(query);
psmt.setString(1, enroll);
psmt.setString(2, Sname);
psmt.setString(3, Fname);
psmt.setInt(4, sub1);
psmt.setInt(5, sub2);
psmt.setInt(6, sub3);
psmt.setInt(7, sub4);
psmt.setInt(8, sub5);
int y = 0;
y = psmt.executeUpdate();
if (y == 0) {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
add() is called on pressing save button in Frame2.java . . . If catch block is executing, why println(query) printing NULL
Based on some of your question tags and responses in the comments to other answers and on the question itself, I'm presuming that somewhere in your code, you intend to call
Class.forName("com.mysql.jdbc.Driver").newInstance();
conn = DriverManager.getConnection(url, username, password);
This is not happening before your add() method is called. In order to fix it, I'd recommend this (bulk of code borrowed from Vivek bhatnagar's answer):
try {
conn = DriverManager.getConnection(url, username, password);
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO `table`
(pid,tid,rid,tspend,description) VALUE
(?,?,?,?,?)");
pstmt.setString(1, pid );
pstmt.setString(2, tid);
pstmt.setString(3, rid);
pstmt.setInt(4, tspent);
pstmt.setString(5,des );
pstmt.executeUpdate();
} catch (Exception e) {
// whatever you want to do to handle the exception
} finally {
// close your connection
}
If you're on Java 7, set up like this:
try (Connection conn = DriverManager.getConnection(url, username, password)) {
try (PreparedStatement pstmt = conn.prepareStatement(/*sql here*/)) {
// Your code here
} catch (SQLException sqle) {
// handle exceptions from the statement
}
} catch (SQLException outerSqlEx) {
// handle exceptions from connecting
}
How could I tell what your problem was (general help for NullPointerException)?
NullPointerException is only thrown when you try to call a method on a null variable (and at a few other specific times, as noted in the API documentation). The easy way to locate a NullPointerException is to look for the line the stack trace indicates, and then look for the dots on the line. There's only two lines in your try block that can throw a NullPointerException.
Statement stmt = conn.createStatement();
// could be here ----^
and
y = stmt.executeUpdate(query);
// or --^
So let's look at the dots. The first one will throw when conn is null. The second one will throw when stmt is null. In your original code, which you've now edited in response to the other answers, you set the value of query after you called conn.createStatement();. Since query was still null in your catch block, we know that it hadn't yet been set, and thus it must be the first one, so conn is null at that point in the program.
Furthermore, since the API Documentation for createStatement
implies that it will either return a valid Connection object or throw an SQLException, we can be pretty sure that stmt will never be null when executeUpdate is called.
In your try block, you are calling a method that is possible to throw an exception before setting the variable in question:
Statement stmt = conn.createStatement();
query = "Insert into table1 (enroll,Sname,Fname,sub1,sub2,sub3,sub4,sub5 )values('" + getEnroll() + "','" + getSname() + "','"+getFname()+"',"+getSub1()+","+getSub2()+","+getSub3()+","+getSub4()+","+getSub5()+")";
Therefore, if your code fails on the conn.createStatement() line, it will enter the catch block without the query variable being initialized.
You can fix this simply by switching the order of the statements, or by putting the query line outside and before the try/catch blocks.
Adding to what #Southpaw answered :
you can use something like this also :
PreparedStatement pstmt = con.prepareStatement("INSERT INTO `table`
(pid,tid,rid,tspend,description) VALUE
(?,?,?,?,?)");
pstmt.setString(1, pid );
pstmt.setString(2, tid);
pstmt.setString(3, rid);
pstmt.setInt(4, tspent);
pstmt.setString(5,des );
pstmt.executeUpdate();
Kindly Note its benefits:
1."Query is rewritten and compiled by the database server"
If you don't use a prepared statement, the database server will have to parse, and compute an execution plan for the statement each time you run it. If you find that you'll run the same statement multiple times (with different parameters) then its worth preparing the statement once and reusing that prepared statement. If you are querying the database adhoc then there is probably little benefit to this.
2."Protected against SQL injection"
This is an advantage you almost always want hence a good reason to use a PreparedStatement everytime. Its a consequence of having to parameterize the query but it does make running it a lot safer. The only time I can think of that this would not be useful is if you were allowing adhoc database queries; You might simply use the Statement object if you were prototyping the application and its quicker for you, or if the query contains no parameters.
Related
Well this method is working except that it makes me think I'm not doing it correctly. I have 2 tables related where
One subject has many school year. (a subject can have many or can belong to different school years)
One school year has many subjects
Subject
code PK
creator
dateCreated
description
name
units
yearLevel
SchoolYearSubjects
id PK
code FK
dateAdded
schoolyear
Here's the method.
public Boolean add(){
Boolean success ;
String SQLa = "INSERT INTO subject(name,code,units,description,yearlevel,creator) "
+ "VALUES (?,?,?,?,?,?)";
String SQLb = "INSERT INTO schoolyearsubjects(code,schoolyear,addedBy) values(?,?,?)";
try(Connection con = DBUtil.getConnection(DBType.MYSQL);
PreparedStatement ps1 = con.prepareStatement(SQLa);
PreparedStatement ps2= con.prepareStatement(SQLb);){
//a.)Prepare ps1
ps1.setString(1,subjectName );
ps1.setString(2,subjectCode );
ps1.setInt(3, subjectUnits);
ps1.setString(4, subjectDescription);
ps1.setString(5, subjectYearLevel);
ps1.setString(6, Login.getUsername());
//b.)Prepare ps2
ps2.setString(1,subjectCode);
ps2.setString(2, schoolYearStart+"-"+schoolYearEnd);
ps2.setString(3, Login.getUsername());
//c.) execute both statements
ps1.executeUpdate();
ps2.executeUpdate();
success = true;
} catch (SQLException e) {
success = false;
JOptionPane.showMessageDialog(null,e.getClass()+" "+e.getMessage());
}
return success;
}
I'm kind of hesitant to stick with having 2 prepared statement inside one method.
How can I ensure the successful execution of BOTH statements considering that code column is Foreign Key and that both has to execute within the same function?
Also, to add, the add() method is tied to just one button.
Please give me advice and correct me if there's anything I'm doing wrong.
Thanks.
There's nothing wrong with two prepared statements in one block.
Guaranteed execution of multiple is what you call a "transaction" in SQL, and in Java, you can do it the following way (starting inside your try block):
con.setAutoCommit(false); // switch to transactional mode
...
ps1.executeUpdate();
ps2.executeUpdate();
con.commit(); // commit the transaction
}
catch(...) {
con.rollback(); // undo everything that happened
}
Note, that you'll have to move your connection object to the outside of the try-with-resources, so that you have access to it in the catch-block. (Which you usually would do anyway, as a connection is an "expensive" object that normally has a longer life.)
I have users table in MySQL and I created a stored procedure so that when get username and password from swing textfields passed them into stored procedure and learn if is there exist that user to login, but I can not get resultset actually in phpMyAdmin stored procedure work properly but in netbeans can not get resultset and runtime never stop in console , running always.
I do not think there is a problem in my code somewhere else because it is so simple code.
Here is my stored procedure in MySQL
SELECT * FROM `users` WHERE `users`.`E-Mail` = #p0 AND `users`.`Password` = #p1
it takes two parameter varchar and I tried before those as a text
Here is the specific part of my java code
public void loginPass(String email, String password){
try {
DriverManager.registerDriver((Driver) Class.forName("com.mysql.jdbc.Driver").newInstance());
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/askdocdb","root","");
CallableStatement mystatement = connection.prepareCall("{CALL sp_Login (?, ?)}");
mystatement.setString(1, email);
mystatement.setString(2, password);
// mystatement.setString("#p0", email);
// mystatement.setString("#p1", password);
boolean situation = mystatement.execute();
System.out.println(situation);
// resultset = mystatement.executeQuery();
resultset = mystatement.getResultSet();
String res = resultset.getString(2);
System.out.println(res);
// resultset = mystatement.executeQuery();
while(resultset.next()){
System.out.println("asdsad");
}
resultset.close();
} catch (Exception e) {
}
}
The reason of comment lines, I tried any possible combination of syntax
situation returns true
res does not return
and can not enter into while statement
Thank you for your support and comments already now.
It's difficult to say what exactly is wrong with your code as there are quite a few possible points for failure if you choose to use a stored procedure for this simple task (incorrect syntax in the procedure, problems with getting the return value over JDBC, etc). I would simply run the SQL query over JDBC for checking the credentials:
public void registerDriver() {
try {
DriverManager.registerDriver((Driver) Class.forName(
"com.mysql.jdbc.Driver").newInstance());
} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException | SQLException e) {
throw new RuntimeException("Could not register MySQL driver!", e);
}
}
public boolean checkLogin(String email, String password) {
try (Connection connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/askdocdb", "root", "");
PreparedStatement ps = connection
.prepareStatement("SELECT 1 FROM users WHERE "
+ "E-Mail = ? AND Password = ?")) {
ps.setString(1, email);
ps.setString(2, password);
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
return true; // username and password match
} else {
return false; // no row returned, i.e. no match
}
}
} catch (SQLException e) {
throw new RuntimeException(
"Error while checking user credentials!", e);
}
}
What was changed:
JDBC driver registration has been extracted into a separate method (registerDriver()), which you only need to call once (e.g. after the program has started), not each time you check for credentials.
Resources such as Connection, PreparedStatement and ResultSet are now being closed properly (even if an exception is thrown) because they are declared through the try-with-resources statement.
The method now returns a boolean that corresponds to whether the credentials were valid or not, making it easier to use from calling code.
Exceptions that cannot be handled (e.g. SQLException) are rethrown as RuntimeExceptions (instead of just swallowing them in an empty catch block).
Basically, when an SQLException is thrown, either there is a programming error in the code (invalid query syntax) or something severely wrong with the database. In either case, the only option is usually to halt your program. You can declare throws SQLException in the method signature if you'd want to handle the situation in the calling method instead.
Finally, it needs to be mentioned that you should never store passwords in the database as plain text, to avoid anyone with read access to the db to login as an arbitrary user. Instead, you should store password hashes, or even better, salted hashes. More on this e.g. in Best way to store password in database.
I am currently using Java to try to INSERT a customer in my Database:
public void saveCustomer(Customer c) {
getConnection();
try {
CallableStatement pstmt = con.prepareCall("{call sp_saveCustomer(?,?)}");
pstmt.setString(1, c.getName());
pstmt.setString(2, a.getLastName());
pstmt.executeUpdate();
closeConnection();
} catch (SQLException e) {
// Handle Exception
}
}
When a user tries to INSERT a duplicate record, the catch block will trigger. What I'm worried about is that I don't know if this means a performance hit. Isn't a better way to check if a customer already exists? Something like:
public void saveCustomer(Customer c) {
getConnection();
boolean exists = false;
CallableStatement pstmt = con.prepareCall("{call sp_checkCustomerExistence(?,?)}");
pstmt.setString(1, c.getName());
pstmt.setString(2, a.getLastName());
ResultSet rs = pstmt.executeQuery();
if (rs.next()) exists = true;
if ( exists ){
closeConnection();
return;
}
CallableStatement pstmt = con.prepareCall("{call sp_saveCustomer(?,?)}");
pstmt.setString(1, c.getName());
pstmt.setString(2, a.getLastName());
pstmt.executeUpdate();
closeConnection();
}
What would be the best solution based on the best performance? Should I check myself if the customer exists or should I let the Exception be thrown?
I think checking the duplicate is preferable than catching the exceptions. Only suggestion I have it to perform the check in your procedure itself if you can i.e. create a procedure as sp_check_and_save_customer which will check for duplicate and save if it doesn't already exist. This way there will be very less time difference between the check and insert, which becomes more crucial in heavy loaded applications.
Still, please have your exception handling as well as it is still possible that another process inserts the data in between the check and insert.
Checking before hand = two database calls or two IO interactions. Attempting to just insert with the possibility of an exception occurring exception is only one. As long as the exceptions are handled, they aren't necessarily a bad thing.
Although probably not preferred, it would be the fastest of the two methods you've listed.
} catch (SQLException e) {
The SQLException that you are catching could mean anything. It doesn't necessarily mean that it occured because of a duplicate row in the database table. So, simply it is not reliable enough to be used for that use-case.
You just have to make a call before trying to create one, to handle it in a proper manner.
I was working on a servlet that will generate a unique code and update that in a mySQL database.
Now, in that, I want to catch any exception thrown in case that unique code already exists in the mySQL table and generate a new code and try updating the database. The problem is I want to do this WITHIN the for loop itself. The code is as follows:
try
{
connection = datasource.getConnection();
SQLUpdate = "INSERT INTO Voucher_dump VALUES( '"+unique_code+"','08-10-2011 04:48:48','0')";
PreparedStatement ps1 = connection.prepareStatement(SQLUpdate);
ps1.executeUpdate();
ResultSet r = ps1.getResultSet(); // this is where I'm checking if it's a duplicate
if(r==null)
out.println("This is a duplicate");
else out.println("Updated");
trial12= "08-10-2011 04:48:480.03999855056924717a";
SQLUpdate = "INSERT INTO Voucher_dump VALUES( '"+trial12+"','08-10-2011 04:48:48','0')";
ps1 = connection.prepareStatement(SQLUpdate);
ps1.executeUpdate();
r = ps1.getResultSet();
if(r==null)
out.println("This is a duplicate");
else out.println("Updated");
}
catch (SQLException sqle)
{
sqle.printStackTrace();
}
I don't want to wait till the end of the entire loop to catch the SQLException (I have already defined this key in mySQL as primary). The moment, the result comes back as a duplicate entry, I want to re-generate this key and attempt the update again.My output for this particular code is coming blank on my output page (all other parameters are showing correctly). Neither is "This is a duplicate" displayed nor is "Updated". Maybe, ResultSet is not the best way to do it. Could you guys give me some advice on what would be the best way forward ?
Some advice in no particular order:
Close the connection in a finally block.
Close statements individually if you'll be creating many of them before closing the connection. ("Many" is defined by your DBAs.)
Format your code.
Don't use stdout and/or stderr from real code. Pick a logging framework.
Consider using some helper classes to simplify (and correct) your database access, like Spring's JdbcTemplate.
Make sure to include relevant context when you post example code.
Due to #6, I don't know what out is, but I suspect the reason you're not seeing anything is that you're inserting a duplicate value with the first statement, which will cause a SQLException from that line, not at getResultSet(), where you seem to expect it. Since the error is written to stdout, it'll show up in your server logs somewhere, but nothing will be written to out. I'm not sure why you think getResultSet() will return null or not null depending on whether there was a constraint violation. Take a look at the javadoc for that method.
Update: 7. As BalusC points out, never, ever concatenate a string directly into a JDBC Statment. Use PreparedStatment's placeholders and set* methods. For info on SQL injection, see Wikipedia and XKCD.
How about this code?
try {
Class.forName(driver).newInstance();
conn = DriverManager.getConnection(url + dbName);
System.out.println("Connected to the database");
int i = 1; //get the unique code
boolean isInserted = false;
while (!isInserted) {
try {
PreparedStatement preparedStatement = conn.prepareStatement("INSERT INTO test values (?)");
preparedStatement.setInt(1, i);
preparedStatement.executeUpdate();
isInserted = true;
} catch (com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException e) { //Catch the particular exception which throws error on unique constraint. This may depend on Java/MySQL your version
i++; //get the next unique code
}
}
System.out.println("Disconnected from database");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (Exception e) {
}
}
As soon as my code gets to my while(rs.next()) loop it produces the ResultSet is closed exception. What causes this exception and how can I correct for it?
EDIT: I notice in my code that I am nesting while(rs.next()) loop with another (rs2.next()), both result sets coming from the same DB, is this an issue?
Sounds like you executed another statement in the same connection before traversing the result set from the first statement. If you're nesting the processing of two result sets from the same database, you're doing something wrong. The combination of those sets should be done on the database side.
This could be caused by a number of reasons, including the driver you are using.
a) Some drivers do not allow nested statements. Depending if your driver supports JDBC 3.0 you should check the third parameter when creating the Statement object. For instance, I had the same problem with the JayBird driver to Firebird, but the code worked fine with the postgres driver. Then I added the third parameter to the createStatement method call and set it to ResultSet.HOLD_CURSORS_OVER_COMMIT, and the code started working fine for Firebird too.
static void testNestedRS() throws SQLException {
Connection con =null;
try {
// GET A CONNECTION
con = ConexionDesdeArchivo.obtenerConexion("examen-dest");
String sql1 = "select * from reportes_clasificacion";
Statement st1 = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY,
ResultSet.HOLD_CURSORS_OVER_COMMIT);
ResultSet rs1 = null;
try {
// EXECUTE THE FIRST QRY
rs1 = st1.executeQuery(sql1);
while (rs1.next()) {
// THIS LINE WILL BE PRINTED JUST ONCE ON
// SOME DRIVERS UNLESS YOU CREATE THE STATEMENT
// WITH 3 PARAMETERS USING
// ResultSet.HOLD_CURSORS_OVER_COMMIT
System.out.println("ST1 Row #: " + rs1.getRow());
String sql2 = "select * from reportes";
Statement st2 = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
// EXECUTE THE SECOND QRY. THIS CLOSES THE FIRST
// ResultSet ON SOME DRIVERS WITHOUT USING
// ResultSet.HOLD_CURSORS_OVER_COMMIT
st2.executeQuery(sql2);
st2.close();
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
rs1.close();
st1.close();
}
} catch (SQLException e) {
} finally {
con.close();
}
}
b) There could be a bug in your code. Remember that you cannot reuse the Statement object, once you re-execute a query on the same statement object, all the opened resultsets associated with the statement are closed. Make sure you are not closing the statement.
Also, you can only have one result set open from each statement. So if you are iterating through two result sets at the same time, make sure they are executed on different statements. Opening a second result set on one statement will implicitly close the first.
http://java.sun.com/javase/6/docs/api/java/sql/Statement.html
The exception states that your result is closed. You should examine your code and look for all location where you issue a ResultSet.close() call. Also look for Statement.close() and Connection.close(). For sure, one of them gets called before rs.next() is called.
You may have closed either the Connection or Statement that made the ResultSet, which would lead to the ResultSet being closed as well.
Proper jdbc call should look something like:
try {
Connection conn;
Statement stmt;
ResultSet rs;
try {
conn = DriverManager.getConnection(myUrl,"","");
stmt = conn.createStatement();
rs = stmt.executeQuery(myQuery);
while ( rs.next() ) {
// process results
}
} catch (SqlException e) {
System.err.println("Got an exception! ");
System.err.println(e.getMessage());
} finally {
// you should release your resources here
if (rs != null) {
rs.close();
}
if (stmt != null) {
stmt.close();
}
if (conn != null) {
conn.close();
}
}
} catch (SqlException e) {
System.err.println("Got an exception! ");
System.err.println(e.getMessage());
}
you can close connection (or statement) only after you get result from result set. Safest way is to do it in finally block. However close() could also throe SqlException, hence the other try-catch block.
I got same error everything was correct only i was using same statement interface object to execute and update the database.
After separating i.e. using different objects of statement interface for updating and executing query i resolved this error. i.e. do get rid from this do not use same statement object for both updating and executing the query.
Check whether you have declared the method where this code is executing as static. If it is static there may be some other thread resetting the ResultSet.
make sure you have closed all your statments and resultsets before running rs.next. Finaly guarantees this
public boolean flowExists( Integer idStatusPrevious, Integer idStatus, Connection connection ) {
LogUtil.logRequestMethod();
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = connection.prepareStatement( Constants.SCRIPT_SELECT_FIND_FLOW_STATUS_BY_STATUS );
ps.setInt( 1, idStatusPrevious );
ps.setInt( 2, idStatus );
rs = ps.executeQuery();
Long count = 0L;
if ( rs != null ) {
while ( rs.next() ) {
count = rs.getLong( 1 );
break;
}
}
LogUtil.logSuccessMethod();
return count > 0L;
} catch ( Exception e ) {
String errorMsg = String
.format( Constants.ERROR_FINALIZED_METHOD, ( e.getMessage() != null ? e.getMessage() : "" ) );
LogUtil.logError( errorMsg, e );
throw new FatalException( errorMsg );
} finally {
rs.close();
ps.close();
}
A ResultSetClosedException could be thrown for two reasons.
1.) You have opened another connection to the database without closing all other connections.
2.) Your ResultSet may be returning no values. So when you try to access data from the ResultSet java will throw a ResultSetClosedException.
It happens also when using a ResultSet without being in a #Transactional method.
ScrollableResults results = getScrollableResults("select e from MyEntity e");
while (results.next()) {
...
}
results.close();
if MyEntity has eager relationships with other entities. the second time results.next() is invoked the ResultSet is closed exception is raised.
so if you use ScrollableResults on entities with eager relationships make sure your method is run transactionally.
"result set is closed" happened to me when using tag <collection> in MyBatis nested (one-to-many) xml <select> statement
A Spring solution could be to have a (Java) Spring #Service layer, where class/methods calling MyBatis select-collection statements are annotated with
#Transactional(propagation = Propagation.REQUIRED)
annotations being:
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
this solution does not require to set the following datasource properties (i.e., in JBoss EAP standalone*.xml):
<xa-datasource-property name="downgradeHoldCursorsUnderXa">**true**\</xa-datasource-property>
<xa-datasource-property name="resultSetHoldability">**1**</xa-datasource-property>