This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How to get the insert ID in JDBC?
Hi, I'm using JDBC to connect on database through out Java.
Now, I do some insert query, and I need to get the id of last inserted value (so, after a stmt.executeUpdate).
I don't need something like SELECT id FROM table ORDER BY id DESC LIMIT 1, because I may have concurrency problems.
I Just need to retrieve the id associated to the last insertion (about my instance of the Statement).
I tried this, but seems it doesn't work on JDBC :
public Integer insertQueryGetId(String query) {
Integer numero=0;
Integer risultato=-1;
try {
Statement stmt = db.createStatement();
numero = stmt.executeUpdate(query);
ResultSet rs = stmt.getGeneratedKeys();
if (rs.next()){
risultato=rs.getInt(1);
}
rs.close();
stmt.close();
} catch (Exception e) {
e.printStackTrace();
errore = e.getMessage();
risultato=-1;
}
return risultato;
}
In fact, every time risultato = -1, and I get java.sql.SQLException: Generated keys not requested. You need to specify Statement.RETURN_GENERATED_KEYS to Statement.executeUpdate() or Connection.prepareStatement().
How can I fix this problem? Thanks Stackoverflow People :)
Wouldn't you just change:
numero = stmt.executeUpdate(query);
to:
numero = stmt.executeUpdate(query, Statement.RETURN_GENERATED_KEYS);
Take a look at the documentation for the JDBC Statement interface.
Update: Apparently there is a lot of confusion about this answer, but my guess is that the people that are confused are not reading it in the context of the question that was asked. If you take the code that the OP provided in his question and replace the single line (line 6) that I am suggesting, everything will work. The numero variable is completely irrelevant and its value is never read after it is set.
Alternatively you can do:
Statement stmt = db.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
numero = stmt.executeUpdate();
ResultSet rs = stmt.getGeneratedKeys();
if (rs.next()){
risultato=rs.getString(1);
}
But use Sean Bright's answer instead for your scenario.
Related
I have this error code in the dialog box: java.sql.SQLException: No value specified for parameter 5 when i try to update my JTable/JTextFields into my SQL database.
I have checked similar questions on the site, but non seem to have the solution to my problem. I have checked the database, i have checked my connection code, the update code and can't find where this extra parameter making the problem should be? Please help a new beginner!
So now i understand that the problem is at WHERE id=? as i suspected, but my id only exist as a row count/main key in my SQL DB, so it is going to be different depending on which row you choose/click on, so i can't set a specific value beforehand at the pst.setInt(5, ? ). What to insert instead then - so i dont lose the automatic row count on my clients list in the JTable?
//This method contains all codes for database connection.
private void upDateDB() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/num klienter", "root", "");
PreparedStatement pst = con.prepareStatement("SELECT * FROM klient");
ResultSet rs =pst.executeQuery();
ResultSetMetaData StData = rs.getMetaData();
q = StData.getColumnCount();
DefaultTableModel RecordTable = (DefaultTableModel)table.getModel();
RecordTable.setRowCount(0);
while(rs.next()){
Vector<String> columnData = new Vector<String>();
for (i = 1; i <= q; i++) {
columnData.add(rs.getString("id"));
columnData.add(rs.getString("Name"));
columnData.add(rs.getString("Birthday"));
columnData.add(rs.getString("Description"));
columnData.add(rs.getString("Other"));
}
RecordTable.addRow(columnData);
}} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
}}
updateButton.addActionListener(new ActionListener() {
public void actionPerformed (ActionEvent arg0) {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/num klienter", "root", "");
PreparedStatement pst = con.prepareStatement("UPDATE klient SET Name=?,Birthday=?,Description=?,Other=? WHERE id=?");
table.getSelectedRow();
pst.setString(1, nameTxt.getText());
pst.setString(2, dayTxt.getText()+"-" + monthTxt.getText()+"-" + yearTxt.getText());
pst.setString(3, descriptionTxt.getText());
pst.setString(4, otherTxt.getText());
pst.executeUpdate();
JOptionPane.showMessageDialog(null, "Updated in database");
upDateDB();
}catch (Exception ex){
JOptionPane.showMessageDialog(null, ex);
}
Class.forName("com.mysql.cj.jdbc.Driver");
this can just be removed. It hasn't been neccessary for 20 years.
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/num klienter", "root", "");
This is a memory leak; the connection is opened, and will remain open forever; your SQL server won't allow more than a handful of open connections, so pretty soon your MySQL server will be unreachable by any service (including this java code) until you kill the java app which closes the connections. Use try with resources for all resources you create.
PreparedStatement pst = con.prepareStatement("SELECT * FROM klient");
This is also a resource and needs try-with-resources.
ResultSet rs =pst.executeQuery();
You guessed it. Try-with-resources a third time. If you find the code becoming unwieldy, JDBC is very low level and not all that great for 'end user' coding. Use a nice abstraction like JDBI or JOOQ.
columnData.add(rs.getString("Fødselsdag"));
non-ASCII in your column names? That's never going to go well. I strongly suggest you don't do it this way.
q = StData.getColumnCount();
for (i = 1; i <= q; i++) {
This is bizarre. q holds the column count - that's the number of columns in your query. And then you hardcode the 5 column names, so q is always 5. Then, you add all 5 values (id, Navn, Fødselsdag, etc), and then do that 5 times, for a total of 25 runs, and your data repeated 5 times. It is not clear what you are trying to accomplish by asking for the known information (get the column count from the metadata, which you already know).
PreparedStatement pst = con.prepareStatement("UPDATE klient SET Navn=?,Fødselsdag=?,Beskrivelse=?,Andet=? WHERE id=?");
I count 5 ?, but only 4 pst.setString statements. You forgot pst.setInt(5, theValue).
The update code gets all the same caveats about try-with-resources.
pst.setString(2, dayTxt.getText()+"-" + monthTxt.getText()+"-" + yearTxt.getText());
Not how you do date stuff with DBs. There is a pst.setDate, but optimally you should use pst.setObject, passing an instance of java.time.LocalDate. Whether MySQL actually supports that - not sure, you'd have to check.
The solution for my problem was to insert the 5th pst. statement for the id=? like this:
pst.setInt(5,table.getRowCount());
My code is having some error, and when I'm writing a roll number which is not present in the database and pressing the delete button then also a message pops up saying "record deleted successfully".
Actually I wanted to create a project of students report and by connecting java and MySQL. So I wrote code for the delete button, in which if the roll no of a student is written and pressed delete it will delete the record of that particular student.
so hope u understood my problem and looking forward for an accurate answer.
Class.forName("java.sql.DriverManager");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost/stud","root","");
Statement stmt=con.createStatement();
String query="delete from info where rollno="+rn.getText();
int d = stmt.executeUpdate(query);
JOptionPane.showMessageDialog(null,"record deleted successfully!!!");
rn.setText("");
First of all, use PreparedStatement in which you fill in the parameters instead of composing a SQL-string.
May avoid very nasty errors (How does the SQL injection from the "Bobby Tables" XKCD comic work?). So
PreparedStatement stmt = con.prepareStatement("DELETE FROM info WHERE rollno=?");
stmt.setLong(1, Long.parseLong(rn.getText()));
int d = stmt.executeUpdate();
As far as your question is concerned:
The method executeUpdate returns the number of rows affected.
If it equals 0, no rows were deleted.
if (d == 0)
{
JOptionPane.showMessageDialog(null,"This record does not exist");
// Return or thrown an exception or whatever to interrupt the operation
}
else
JOptionPane.showMessageDialog(null,"record deleted successfully!!!");
showMessageDialog should get executed only if the value of d variable is positive i.e. some records got deleted from database. e.g.
Class.forName("java.sql.DriverManager");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost/stud","root","");
Statement stmt=con.createStatement();
String query="delete from info where rollno="+rn.getText();
int d = stmt.executeUpdate(query);
if(d>0){
JOptionPane.showMessageDialog(null,"record deleted successfully!!!");
}
rn.setText("");
Check if result of executeUpdate is > 0. If yes, your entry was deleted.
Enter in rn: 1 or 1=1 and enjoy. Using PreparedStatements will prevent this evil SQL injection. Also it takes care of apostrophes around SQL strings and escaping apostrophe and other chars.
Connection con=DriverManager.getConnection("jdbc:mysql://localhost/stud","root","");
String query="delete from info where rollno=?";
try (PreparedStatement stmt = con.prepareStatement(query)) {
stmt.setLong(1, Integer.parseLong(rn.getText()));
int d = stmt.executeUpdate();
if (d != 0) {
JOptionPane.showMessageDialog(null, "Record deleted successfully.",
JOptionPane.INFORMATION_MESSAGE);
}
}
This try-with-resources will ensure that stmt is always closed
I am trying to calculate over time to add it to salary the overtime time stored in table attendance and the salary is stored in other table contain total basic hourly
I want to get the result from the 2 tables display them in java another store in another table for future reference
int Eid = Integer.parseInt(jTextField2.getText());
try{
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/hr","root","adam");
String query="SELECT * FROM sallary where Eid ="+Eid +";"
java.sql.PreparedStatement preparedStatement = null;
preparedStatement = con.prepareStatement(query);
String select="select 83 *((time_to_sec(sum(overtime)) /60)/60)from att where Eid="+Eid +";";
java.sql.PreparedStatement preparedStatement2 = null;
preparedStatement2 = con.prepareStatement(select);
int eid;
double basic ,total,hourly;
ResultSet rs2 = preparedStatement2.executeQuery();
ResultSet rs = preparedStatement.executeQuery();
double overtime=rs2.getDouble(1);
// I tried this on MySQL command line it worked, however on java its error:
// the right syntax to use near 'sum(overtime)' at line 2
eid =rs.getInt("Eid");
basic =rs.getDouble("basic");
total=rs.getDouble("total");
hourly=rs.getDouble("hourly");
Object[] row = {eid,basic,total,hourly,overtime};
model = (DefaultTableModel) st.getModel();
model.addRow(row);
} catch (ClassNotFoundException | SQLException ex) {
Logger.getLogger(payroll.class.getName()).log(Level.SEVERE, null, ex);
}
The actual error message you got was something like "See the manual for your version of MySQL for the right syntax to use near 'sum(overtime)' at line 2." This error message tells you exactly what you need to do.
Looking at the manual:
https://dev.mysql.com/doc/refman/5.7/en/select.html
You can see that the SELECT statement syntax does not include a semicolon at the end.
The semicolon is a statement separator, useful when you give multiple statements at the console. JDBC queries are one statement at a time, so the semicolon makes no sense and is a syntax error.
By the way, you should leave out the statement Class.forName("com.mysql.jdbc.Driver");. There is simply no need for it. It was needed in earlier versions, but has been unnecessary for the last 15 years or so.
This question already has answers here:
SQLException: Exhausted Resultset
(3 answers)
Closed 7 years ago.
i have problem with the below code. help me!!
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn=DriverManager.getConnection("jdbc:oracle:thin:#127.0.0.1:1521:xe","system","**********");
Statement st=conn.createStatement();
String sql="select password from db where username='user'";
ResultSet rs=st.executeQuery(sql);
rs.next();
String password=rs.getString("password");
if(password.equals(pass))
{
RequestDispatcher rd=req.getRequestDispatcher("/home.jsp");
rd.forward(req,res);
}
else
{
out.println("invalid username and password");
}
when i execute this code i am getting an java sql exception : exhausted result set. thanks in advance...
Instead of using rs.next();, use it with while e.g while(rs.next()). Once you got the resultset, the pointer will point to the first record. Each time you do a rs.next(), the pointer will advances to the next record. If you use with while, once you reach to the end of your resultset, rs.next() will return false once all records are iterated. In your case, since you are not checking whether resultset has exhausted and trying to advanced the pointer, you are getting the exception.
That is correct, because if you enter wrong username or password, NO record will be returned. So, when you use the rs.next(); in this case, it is trying to access the first row of the empty result set
String password=rs.getString("password");//error, if rs is empty
in the where clause you are not using user variable
where clause should be where username='"+user+"'";
and
instead of
rs.next();
use
if(rs.next())
{
String password=rs.getString("password");
........
}
This question already has answers here:
ResultSet exception - before start of result set
(6 answers)
Closed 5 years ago.
try
{
PreparedStatement s = (PreparedStatement) conn.prepareStatement("SELECT voters.Check,count(*) FROM voting.voters where FirstName="+first+"and LastName="+last+" and SSN="+voter_ID);
//java.sql.Statement k = conn.createStatement();
rs=s.executeQuery();
//s.executeQuery("SELECT voters.Check,count(*) FROM voting.voters where FirstName="+first+"and LastName="+last+" and SSN="+voter_ID);
System.out.println(rs.first());
c=rs.getInt(1);
d=rs.getInt(2);
System.out.println(c);
System.out.println(d);
if(c==1 && d==1)
{
s.executeUpdate("update cand set total=total+1 where ssn="+can_ID);
System.out.println("Succeful vote");
System.out.println("after vote");
s.executeUpdate("update voters set voters.Check=1 where ssn="+voter_ID);
toclient=1;
PreparedStatement qw = (PreparedStatement) conn.prepareStatement("select FirstName from cand where ssn="+can_ID);
// rs=k.executeQuery("select FirstName from cand where ssn="+can_ID);
rs1 = qw.executeQuery();//Error Here Plz help me
String name1= (String) rs1.getString(1);
System.out.println(name1);
s.executeUpdate("update voters set VTO="+name1+"where ssn="+voter_ID);
System.out.println(rs.getString(1));
}
else
{
if(c != -1)
toclient =2;
if( d ==0)
toclient =3;
if( d>1)
toclient =4;
}
System.out.println("out-----------");
rs.close();
s.close();
}
catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Error IS :
java.sql.SQLException: Before start of result set
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1072)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:986)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:981)
The common practice is to use rs.next() method with while cycle:
PreparedStatement st = conn.prepareStatement("select 1 from mytable");
ResultSet rs = st.executeQuery();
while (rs.next()) {
// do something with result set
}
rs.close();
st.close();
I've omitted try/catch/finally clauses for clarity. Note that you should invoke each close() method in separate finally block.
While rs1.first() may work, to avoid exception I would like to avoid it and use rs1.next() instead.
See javadoc of ResultSet.first():
SQLException - if a database access error occurs; this method is called on a closed result set or the result set type is TYPE_FORWARD_ONLY
SQLFeatureNotSupportedException - if the JDBC driver does not support this method
while next doesn't have this limitation
Code:
if (rs1.next()) {
String name1 = rs1.getString(1);
}
Tips: avoid useless type casting (your code is full of them)
In your code snippet you create PreparedStatements but you do not use them correctly. Prepared statements are meant to be used as a kind of 'statement template' which is bound to values before it executes. To quote the javadoc:
PreparedStatement pstmt = con.prepareStatement(
"UPDATE EMPLOYEES SET SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1, 153833.00)
pstmt.setInt(2, 110592)
This has two big advantages over your current usage of PreparedStatement:
one PreparedStatement can be used for multiple executes
it prevents a possible SQL injection attack
The second one here is the biggie, if for instance your variables first and last are collected in a user interface and not reformatted, you run the risk of parts of SQL being input for those values, which then end up in your statements! Using bound parameters they will just be used as values, not part of the SQL statement.
When you get a resultset, the cursor is placed before the first row. Trying to get anything before moving your cursor to the first row will cause the error you received. You need to move the cursor to the first row using this line:
rs1.first();
before calling
String name1 = (String) rs1.getString(1);
Of course, make sure the resultset contains entries before calling rs1.getString(1).
Call rs1.first() before using the ResultSet.
Moves the cursor to the first row in this ResultSet object.
Initially the cursor position of the ResultSet is before the start of the set. The first() method returns true if there is data in the set. So preferably:
if (rs1.first()) {
String name1 = (String) rs1.getString(1);
}
So, to be sure the proper use of PreparedStatment, here is your original example adjusted for best practices (note the cast is redundant):
PreparedStatement s = conn.prepareStatement(
"SELECT voters.Check,count(*) " +
"FROM voting.voters " +
"where FirstName=? and LastName=? and SSN=?");
s.setString(1,first);
s.setString(2,last);
s.setString(3,voter_ID);
ResultSet rs = s.executeQuery();
while( rs.next() ) {
c = rs.getInt(1);
d = rs.getInt(2);
}
Hope this helps... :)