What is wrong with this getGeneratedKeys() JDBC statement? - java

This code fragment
PreparedStatement statement = connect.prepareStatement(
query, Statement.RETURN_GENERATED_KEYS);
statement.executeUpdate(query);
try (ResultSet generatedKeys = statement.getGeneratedKeys()) {
...
}
keeps throwing
java.sql.SQLException: Generated keys not requested. You need to specify Statement.RETURN_GENERATED_KEYS to Statement.executeUpdate() or Connection.prepareStatement().
I'd say that generatedkeys ARE requested at creation of the statement, but apparently I'm wrong. What is the issue here? (I'm new to JDBC. What I'm trying to do is retrieving the primary key value which has been automatically set (AUTO_INCREMENTed) during the preceding record insertion. Maybe there is a better way to do that... I'm using mysql.)

Your problem is this line:
statement.executeUpdate(query);
don't pass the query parameter in use the no parameter version:
statement.executeUpdate();
The first version doesn't use the prepared statement you already made but instead makes a new one using your query String (without the RETURN_GENERATED_KEYS option)

Remove the parameter from
statement.executeUpdate(query);
change to
statement.executeUpdate();
because you have already prepared the statement in
PreparedStatement statement = connect.prepareStatement(
query, Statement.RETURN_GENERATED_KEYS);

Related

error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? or tel=?' at line 1

Here's my query:
select *
from reg
where indexno=?
or tel=?
And here's my code:
Class.forName("com.mysql.cj.jdbc.Driver");
Connection con =DriverManager.getConnection("jdbc:mysql://url","unam","pass");
String query = "select * from reg where indexno= ? or tel=?";
PreparedStatement ps = con.prepareStatement(query);
ps.setString(1, in.getText());
ps.setString(2, tl.getText());
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(query);
Let's take a closer look at what your code is doing.
Connecting to the database:
Connection con =DriverManager.getConnection("jdbc:mysql://url","unam","pass");
Creating the SQL query:
String query = "select * from reg where indexno= ? or tel=?"`;
Creating a prepared statement:
PreparedStatement ps = con.prepareStatement(query);
Setting some bind parameter values:
ps.setString(1, in.getText());
ps.setString(2, tl.getText());
Creating a whole new non-prepared statement (wait, what? Why are we not using the prepared statement we spent some time creating?):
Statement st = con.createStatement();
Using the new non-prepared statement to execute the SQL query.
ResultSet rs = st.executeQuery(query);
As a result of the last two lines, your SQL query is sent straight to the MySQL database. MySQL doesn't understand what the ? marks are for, and hence complains with a syntax error about them.
When handling prepared statements, JDBC drivers will either replace the ? marks with the database's own syntax for bind parameters (unless the database supports ? marks directly, but not all databases do), or put the values directly in the SQL string after suitable escaping of any characters, before they send the SQL to the database. Statements don't support bind parameters, and will just send the SQL string they are given straight to the database.
Your code creates a PreparedStatement and sets two bind parameter values. It seems a shame not to actually use your prepared statement once you've created it. You can get the result set you want out of it by calling ps.executeQuery(). There is no need for the separate Statement you created by calling connection.createStatement().
The fix therefore is to remove the last two lines of the code in your question and add the following line in place of them:
ResultSet rs = ps.executeQuery();

Which way is better for update database record?

I have two method for update:
String query = "update mytable set name = 'new_value' where id ='20' ";
Connection conn;
PreparedStatement pState;
try {
conn = DriverManager.getConnection(dbUrl, "root", "2323");
pState = conn.prepareStatement(query);
pState.executeUpdate();
} catch (SQLException sql) {
sql.printStackTrace();
}
OR:
String query = "update mytable set name = ?" + "where id = ?";
Connection conn;
PreparedStatement pState;
int s;
try {
conn = DriverManager.getConnection(dbUrl, "root", "2323");
pState = conn.prepareStatement(query);
pState.setStringt(1, "new_value");
pState.setString(2, "20");
s = pState.executeUpdate(); // if s = 1 then update done successfully
} catch (SQLException sql) {
sql.printStackTrace();
}
Both methods update database record correctly, Which is better?
Second approach is good practice to avoid SQL Injection attacks.
And following is enough to construct query String, another + concatenation is not required.
String query = "update mytable set name = ? where id = ?";
I would say the second approach.
You aren't returning anything, so why create a result set and go down that path?
Edit:
Even after your comment, I would still use the second template. It's more flexible. Additionally, it's faster. The PreparedStatement is pre-compiled in the database which allows the database to execute a parametric query using the statement faster than a normal query. This won't happen if you use string concatenation (like in your first example).
See: http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html
Additionally, from that page:
The main feature of a PreparedStatement object is that, unlike a
Statement object, it is given a SQL statement when it is created. The
advantage to this is that in most cases, this SQL statement is sent to
the DBMS right away, where it is compiled. As a result, the
PreparedStatement object contains not just a SQL statement, but a SQL
statement that has been precompiled. This means that when the
PreparedStatement is executed, the DBMS can just run the
PreparedStatement SQL statement without having to compile it first.
Although PreparedStatement objects can be used for SQL statements with
no parameters, you probably use them most often for SQL statements
that take parameters. The advantage of using SQL statements that take
parameters is that you can use the same statement and supply it with
different values each time you execute it.
The second way is more faster if you use frequently the same query. Depends of the database vendor, the query is cached and the efficiency is higher than that using flat sentences. But all that depends on the implementation of the JDBC driver and the services provided by the database.
See more in Using Prepared Statements in the The Java Tutorials.

How can I get auto generated keys and set the resultset type?

I have this SQL statement:
con = cpds.getConnection();
con.setAutoCommit(false);
SQL = "INSERT INTO person(accountID,addressID,lastName,firstName,middleName,suffix,gender,birthDate, [language], ethinicity) "
+ "VALUES(?,?,?,?,?,?,?,?,?,?)";
PreparedStatement stmt = con.prepareStatement(SQL,ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
What I want to be able to do is get the generated keys for this statement. Now I have done this before, but without setting the resultset typescroll parameter. It seems that there is no argument that does this either:
PreparedStatement stmt = con.prepareStatement(SQL,ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, Statement.RETURN_GENERATED_KEYS)
What I want to know is this: How can I set the resultset type to typescroll insensitive AND get generated keys?
Statement#getGeneratedKeys() returns a ResultSet that you can use to retrieve the keys as
ResultSet rsKeys = statement.getGeneratedKeys();
if (rsKeys.next()) {
person.setId(rsKeys.getLong(1));
}
How can I set the resultset type to typescroll insensitive AND get generated keys?
Doing this doesn't make sense because you can expect to retrieve keys only after doing an insert. While you would want to set the scroll type only for a resultset i.e. after a query. So, the two things are mutually exclusive and hence the API obviously doesn't support it.
statement.getGeneratedKeys(); would help

Execution of SQL statement in Java function

I have to read the below SQL statement from one properties.
update scoreconfig set scorestatus=0 where scoreversion=props.getProperty("scoreversion");
And value for score version I've to take it from other properties file.
But, when I prepare a statement in java function as below:
final String query = strLine;
PreparedStatement ps=con.prepareStatement(query);
where query has
update scoreconfig set scorestatus=0 where scoreversion=props.getProperty("scoreversion");
But I get
Error: ORA-00911: invalid character
...when I do ps.execute();
I assume props is a Properties instance or similar. If so, the props.getProperty("scoreversion") part is meant to happen at the Java layer, not in the database. Instead:
String sql = "update scoreconfig set scorestatus=0 where scoreversion=?";
PreparedStatement ps = con.prepareStatement(sql);
// If scoreversion is a String:
ps.setString(1, props.getProperty("scoreversion"));
ResultSet rs = ps.executeQuery();
...or if scoreversion is an int, use this instead of the setString line:
// It scoreversion is an int:
ps.setInt(1, Integer.parseInt(props.getProperty("scoreversion")));
...etc., convert as appropriate.
Basically, when you use prepareStatement, you use ? where parameters should go, and then you use setXyz on the PreparedStatement instance to set those parameters. (Oddly, they start with 1, not 0.) Note that even when the parameter is a String, you don't put quotes around it in the SQL you pass into prepareStatement; that's handled for you (along with properly escaping that string to prevent SQL injection, so PreparedStatement and setXyz are your friends, you'll get to know them well).

Java does not run prepare statements with parameter

I am using PreparedStatement to query my table. Unfortunately, I have not been able to do so.
My code is as simple as this:
PreparedStatement preparedStatement = connection.prepareStatement(
"Select favoritefood from favoritefoods where catname = ?");
preparedStatement.setString(1, "Cappuccino");
ResultSet resultSet = preparedStatement.executeQuery();
The error thrown is java.sql.SQLException: ORA-00911: invalid character. As if it never run through the parameter given.
Thanks for your time. I've spend a day to debug this yet still unsuccessful.
As mention by Piyush, if I omit the semicolon at the end of statement, a new error is thrown. java.sql.SQLException: ORA-00942: table or view does not exist. But I can assure you this table is indeed exist.
UPDATE
shoot. i edited the wrong sql. now it is successful. thx for your time.
Do you get this error if you try binding values from the shown sql and excute it from the SQL prompt or any SQL editor?
Make sure your query is not having semicolon (";") at the end of it or anywhere in the query.
try giving it this way..
String query="Select favoritefood from favoritefoods where catname = ?";
preStat = conn.preparedStatement(query); // conn is the connection object
preStat.setString(1,"Cappuccino");
ResultSet resultSet=preStat.executeQuery();

Categories

Resources