PSQLException thrown when trying to execute SELECT query - java

I have problem with my SQL request, when I run my request, I receive this message error:
org.postgresql.util.PSQLException: A result was returned when none was expected.
Here is my request:
Connexion con = new Connexion();
try {
c = con.Connect();
stmt = c.createStatement();
int sqlCalcul = stmt.executeUpdate(
"SELECT inventaire FROM calcul WHERE designation='" + designation +
"' AND date=(SELECT MAX(date) FROM calcul)");
stmt.close();
// c.commit();
c.close();
} catch (Exception e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
System.exit(0);
}
System.out.println("Records created successfully");

You should use executeQuery instead of executeUpdate:
ResultSet sqlCalcul = stmt.executeQuery("SELECT inventaire...")
executeUpdate is used for a INSERT, UPDATE, or DELETE statement, and will throw an exception if a ResultSet is returned. executeQuery should be used for SELECT statements.
Take a look at PostgreSQL's tutorial using the JDBC driver for more information.

Related

Using invalidate table in a prepared statement

I'm attempting to call:
"invalidate metadata " + table_name
If I execute the query directly, I fall foul of a sonarqube rule that states that the code is vulnerable to a SQL Injection attack. (It isn't, as I've validated the table name elsewhere.)
String query = "invalidate metadata " + table;
try (Connection con = hiveConnectionFactory.getConnection(hiveConnDetailsHelperBean)) {
try (PreparedStatement stmt = con.prepareStatement(query)) {
stmt.execute();
LOGGER.debug("metadata invalidated " + table);
}
} catch (SQLException | MoLiConnectionException e) {
String errorMessage = "Error Running Query: "+ query;
throw new MoLiConnectionException(errorMessage, e);
}
If I attempt to use a prepared statement as suggested by SonarQube I get an exception:
String query = "invalidate metadata ?";
try (Connection con = hiveConnectionFactory.getConnection(hiveConnDetailsHelperBean)) {
try (PreparedStatement stmt = con.prepareStatement(query)) {
stmt.setString(1, table);
stmt.execute();
LOGGER.debug("metadata invalidated " + table);
}
} catch (SQLException | MoLiConnectionException e) {
String errorMessage = "Error Running Query: "+ query;
throw new MoLiConnectionException(errorMessage, e);
}
AnalysisException: Syntax error in line 1:
invalidate metadata 'dru_jhutc.time_test'
^
Encountered: STRING LITERAL
Expected: DEFAULT, IDENTIFIER
CAUSED BY: Exception: Syntax error
My question is: How can I use a prepared statement to get around the sonarqube rule?

What does "java.sql.SQLException: Unsupported feature" mean?

My question is related to this post and a post of mine . I am trying to pass REF_CURSOR as an IN parameter while calling a PL/SQL procedure using JDBC. Here is my code:
public int printMaxSalAllDept()
{
Connection conn = null;
OracleCallableStatement callStmt = null;
int rowCount = -1;
try
{
// Register the Jdbc Driver
// Class.forName(JDBC_DRIVER_ORACLE);
// Create a Database connection
conn = DriverManager.getConnection(DB_URL,DB_USER,DB_PWD);
// Create a query string to get the ResultSet of your choice
String getRsQuery = "SELECT e.department_id , e.last_name , "
+ "e.salary FROM employees e , (SELECT department_id , "
+ "MAX(salary) AS maxSal FROM employees GROUP BY department_id) "
+ "m WHERE e.department_id = m.department_id "
+ "AND e.salary = m.maxSal ORDER BY e.salary";
// Create a Statement
Statement stmt = conn.createStatement();
// Execute the statement
ResultSet rs = stmt.executeQuery(getRsQuery);
// Create a SQL String
String callProc = "{ call HR.EMP_PKG.print_max_sal_all_dept(? , ?) }";
// Create a Callable Statement
callStmt = (OracleCallableStatement) conn.prepareCall(callProc);
// Bind values to the IN parameter
callStmt.setCursor(1, rs);
// callStmt.setNull(1,OracleTypes.CURSOR);
// Register OUT parameters type to the SQL type of the value returned
callStmt.registerOutParameter(2, java.sql.Types.NUMERIC);
// Execute Callable Statements
callStmt.execute();
// Retrieve value from the OUT parameters
rowCount = callStmt.getInt(0);
System.out.println("Number of rows in the cursor :" + rowCount);
}
catch (SQLException se)
{
System.out.println("Exception occured in the database");
System.out.println("Exception message: "+ se.getMessage());
System.out.println("Database error code: "+ se.getErrorCode());
se.printStackTrace();
}
finally
{
// Clean up
if(callStmt != null)
{
try
{
callStmt.close();
}
catch (SQLException se2)
{
se2.printStackTrace();
}
}
if(conn != null)
{
try
{
conn.close();
}
catch (SQLException se2)
{
se2.printStackTrace();
}
}
}
return rowCount;
}
When I run the above code I get the following exception:
Exception occured in the database
java.sql.SQLException: Unsupported feature
at oracle.jdbc.driver.OraclePreparedStatement.setCursorInternal(OraclePreparedStatement.java:5867)
at oracle.jdbc.driver.OracleCallableStatement.setCursor(OracleCallableStatement.java:5297)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.setCursor(OraclePreparedStatementWrapper.java:410)
at com.rolta.HrManager.printMaxSalAllDept(HrManager.java:1038)
at com.rolta.HrManager.main(HrManager.java:1344)
Exception message: Unsupported feature
Database error code: 17023
I have seen couple of posts in this forum and others which suggests updating to the latest version of JDBC driver fixes this issue. In my case I am using the latest version of JDBC driver for Oracle ( ojdbc6.jar the very first jar under Oracle Database 11g Release 2 11.2.0.4 JDBC Drivers) . So i don't think its the version that's causing the issue.
If what I was doing was illegal the exception message thrown would have indicated that. But here with "Unsupported Feature" message it seems like this feature is either unavailable for my database(or its version that I am using (11g) ) or for the version of the JDBC driver that I am using. Is this the right interpretation of this exception ?
I would say that the feature is not supported in any version of the JDBC driver, and will never be supported. The version of the database in this situation is not relevant.
I can't say why there ever was a setCursor() method declared in OraclePreparedStatement. I would guess that it was a mistake in the design of the API. In fact, you get a deprecation warning if you compile any code that attempts to call setCursor():
C:\>javac -Xlint JavaRefCursorTest.java
JavaRefCursorTest.java:28: warning: [deprecation] setCursor(int,ResultSet) in OraclePreparedStatement has been deprecated
((OracleCallableStatement)cstmt2).setCursor(1, rSet);
^
1 warning
This deprecation warning suggests that Oracle are planning to remove this method in the future.
I've also run my JavaRefCursorTest class from my answer to one of your previous questions with the Oracle 12c JDBC driver (ojdbc7.jar). The end result is only slightly different: the type of exception thrown when calling setCursor() is java.sql.SQLFeatureNotSupportedException instead of java.sql.SQLException. So upgrading the JDBC driver JAR won't help.
In your case, I can't see the reason why you would want to get a ref cursor out of the database and into a JDBC ResultSet, only to pass the same ResultSet straight back to the database. You can call the procedure with a ref cursor directly, using a PL/SQL block such as the one below:
String plsql =
"DECLARE" +
" l_curs SYS_REFCURSOR; " +
"BEGIN" +
" OPEN l_curs FOR" +
" SELECT e.department_id , e.last_name ," +
" e.salary FROM employees e , (SELECT department_id ," +
" MAX(salary) AS maxSal FROM employees GROUP BY department_id)" +
" m WHERE e.department_id = m.department_id" +
" AND e.salary = m.maxSal ORDER BY e.salary;" +
"" +
" HR.EMP_PKG.print_max_sal_all_dept(l_curs, ?);" +
"END;"
PreparedStatement stmt = conn.prepareStatement(plsql);
stmt.registerOutParameter(1, java.sql.Types.NUMERIC);
stmt.execute();

JDBC update using prepared statement

I am trying to update a table using Java JDBC. The method I am using does not throw any errors but the table is not updating. The create table method is below:
public static void Table()
{
Connection c = null;
Statement stmt = null;
try {
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:WalkerTechCars.db");
System.out.println("Opened database successfully");
stmt = c.createStatement();
String sql = "CREATE TABLE IF NOT EXISTS CUSTOMERS2 " +
"(PHONE TEXT PRIMARY KEY NOT NULL," +
" SURNAME TEXT NOT NULL, " +
" FIRSTNAME TEXT NOT NULL, " +
" HOME TEXT, " +
" ADDRESS TEXT, " +
" POSTCODE Text)";
stmt.executeUpdate(sql);
stmt.close();
c.close();
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
}
System.out.println("Customers2 created successfully");
}
The update method is below:
public static void updateCustomers()
{
Connection c = null;
PreparedStatement pstmt = null;
try {
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:WalkerTechCars.db");
c.setAutoCommit(false);
System.out.println("Opened database successfully");
String query = "UPDATE CUSTOMERS2 set ADDRESS = ? where PHONE = ? ";
pstmt = c.prepareStatement(query); // create a statement
pstmt.setString(1, "1"); // set input parameter 1
pstmt.setString(2, "DOES THIS WORK"); // set input parameter 2
pstmt.executeUpdate(); // execute update statement
pstmt.close();
c.close();
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
}
System.out.println("Update Completed successfully HELLO");
}
I have tried to find some clear instructions on this but cant find any. I do not really understand JDBC and prepared statement very well
When autoCommit is false (c.setAutoCommit(false);), you must manually commit the transaction...
Add...
c.commit()
After pstmt.executeUpdate();
You code also has a flaw, in that if some kind of error occurs during the preparation or execution of the statement, both the Connection and PreparedStatement could be left open, causing a resource leak
If you're using Java 7+ you can use the try-with-resources feature, for example...
try {
Class.forName("org.sqlite.JDBC");
try (Connection c = DriverManager.getConnection("jdbc:sqlite:WalkerTechCars.db")) {
c.setAutoCommit(false);
System.out.println("Opened database successfully");
String query = "UPDATE CUSTOMERS2 set ADDRESS = ? where PHONE = ? ";
try (PreparedStatement pstmt = c.prepareStatement(query)) {
pstmt.setString(1, "1"); // set input parameter 1
pstmt.setString(2, "DOES THIS WORK"); // set input parameter 2
pstmt.executeUpdate(); // execute update statement
c.commit();
}
} catch (SQLException exp) {
exp.printStackTrace();
}
} catch (ClassNotFoundException exp) {
exp.printStackTrace();
System.out.println("Failed to load driver");
}
This will ensure that regardless of how you leave the try block the resource will be closed.
You might also consider taking a look at the JDBC(TM) Database Access
Your update method will set ADDRESS to 1 if there is any row in table with PHONE = does this work.
Try to put Address in 1st Input parameter and Phone 2nd Input parameter
When a connection is created, it is in auto-commit mode.
We need to use [setAutoCommit] method only when we need to make Auto Commit false and make it manual commit after executing the query.
More details at Oracle site on JDBC Transaction.

Error while getting resultset

I have a class in which i am getting resultset from the database:
public ResultSet GetDataFromDB() {
ResultSet resultset = null;
try {
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
System.out.println("Connecting to the database...");
Connection connection = DriverManager.getConnection(
"jdbc:oracle:thin:#host:1521:DBname", "user123","pass123");
Statement statement = connection.createStatement();
resultset = statement.executeQuery("select * from tablename");
while (resultset.next()) {
System.out.println(resultset.getInt(1) + " " +
resultset.getInt(2) + " " +
resultset.getInt(3) + " " +
resultset.getString(4));
}
// statement.close();
//connection.close();
} catch (Exception e) {
System.out.println("The exception raised is:" + e);
}
return resultset;
}
In this classs i am able to print the data which i am getting in resultset. but when i tried to get this resultset in another class:
Classname obj= new Classname();
ResultSet tempResultSet = obj.GetDataFromDB();
System.out.println("Records Exist "+tempResultSet.next()); <-----false
I am not getting any data here.
also there is no datatable here in java like in .net so that i can use that...Please concern
thanks
while (resultset.next()) {
You already read all of the data from the ResultSet in this loop.
ResultSet is a single-use, forward-only view of the data; you can only iterate it once.

problem with prepare statement

I wrote this query but it has a error.
String x = String.valueOf(jTable1.getModel().getValueAt(row, 2) );
try {
PreparedStatement preparedStatement1 = connection.prepareStatement("select sportman_code, "
+ "customer_code from sportman where sportman_code = ?");
preparedStatement1.setString(1, x);
preparedStatement1.executeUpdate();
} catch (Exception e) {
System.out.print(e.getMessage());
}
this is it's error
Can not issue executeUpdate() for SELECTs
what is problem?
Try
ResultSet resultSet = preparedStatement1.executeQuery();
instead of
preparedStatement1.executeUpdate();
resultSet = preparedStatement.executeQuery();
For issuing SQL SELECT's you have to use executeQuery and not executeUpdate. Also i see a ; hanging out there.

Categories

Resources