Java Callablestatement doesn't wait until .execute() ends - java

I am trying to get value from a Table_X . But those table values inserted by a procedure. I am calling procedure like ps.execute() and i would like to wait until it ends and get all results from Table_X , everything looks like working. But it only returns a few results from Table_X not all. So I think it doesn't wait until procedure ends. So it only returns some inserted values.
How can I fix it ?
Edit : Codes ;
CallableStatement pstmt = con.prepareCall("{ ? = call "+job.getSP()+" }");
pstmt.registerOutParameter(1, Types.INTEGER);
pstmt.execute();
Then I am calling a method
Map<String,String> errors = MTRCMtdJob.GetDataControlErrors();
Those method gets value from Table_X

I presume there is only one issue, the transaction isolation level is allowing dirty reads even before the procedure transaction is committed. I recommend that you put the reading the table section in a new transaction block by using commit after the procedure transaction. And also please check the transaction isolation level.

Related

Statement.execute always returns true for a boolean query executed from Java

When I execute a SQL query from Java and store the boolean returned, the query always returns true which shouldn't be the case at all. So I emptied the table and fired the query again, and yet it returns true for the emptied table. I have attached a picture of the table. I want the query to return true or false, so I can store it in Java. Can someone please specify an alternate code for this, please?
This is my code on java for the query.
boolean avail = st.execute("SELECT EXISTS(SELECT * from sales WHERE product='"+n+"' AND ord_date='"+sqlDate+"');");
And this is my code for result set
Statement st = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
This is the table, name of the table is 'sales'
I'm new to MySQL, a more specific approach is appreciated.
Statement.execute will return true regardless of what the query returns. You are still supposed to retrieve the actual result of the query.
Returns
true if the first result is a ResultSet object; false if it is an update count or there are no results
As you execute an EXISTS statement, there will always be a result (true or false). The actual value still has to be retrieved:
You must then use the methods getResultSet or getUpdateCount to retrieve the result, and getMoreResults to move to any subsequent result(s).
For reference: https://docs.oracle.com/javase/8/docs/api/java/sql/Statement.html#execute-java.lang.String-String
Also note that you are directly embedding strings into your query, this will leave you vulnerable to SQL injections. Please read: How can prepared statements protect from SQL injection attacks?. Recommended reading: Introduction to JDBC
The return value of Statement.execute() signals whether the query produces a result set (true) or - possibly - an update count (false). The query you execute is a select which will always produce a result set (even if empty). In other words, it will always return true for a select.
If you want to get the result of your query, then the recommend approach is to use executeQuery. However, you are also concatenating values into your query string, which is a bad idea because it leave you vulnerable to SQL injection. The recommended approach is to switch to prepared statements:
try (PreparedStatement pstmt = con.prepareStatement(
"SELECT EXISTS(SELECT * from sales WHERE product = ? AND ord_date = ?)")) {
pstmt.setString(1, n);
pstmt.setDate(2, sqlDate);
try (ResultSet rs = st.executeQuery() {
boolean avail = rs.next() && rs.getBoolean(1);
// use avail...
}
}

Execute multiple hive queries using single execute() method of statement class using java

I am using Java API to access HiveServer2, I have requirement of executing multiple hive queries in single call to execute() method of statements class. Is it possible to submit multiple queries of hive in one call to execute() method. I have hive properties to set as:
SET hive.exec.max.created.files=200000;
SET hive.exec.compress.output=true;
SET mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;
SET hive.exec.dynamic.partition = true;
SET hive.exec.dynamic.partition.mode = nonstrict;
set hive.exec.max.dynamic.partitions=5000;
set hive.exec.max.dynamic.partitions.pernode=5000;
.
.
Statement stmt = con.createStatement();
stmt.execute("SET hive.exec.max.created.files=200000");
.
.
for that now I am setting these properties one at a time using execute() method. Is there any way so i can set all these properties by executing all above statement in one call to execute() method.
Expected:
stmt.execute("SET hive.exec.max.created.files=200000;
SET hive.exec.dynamic.partition = true;
SET hive.exec.dynamic.partition.mode = nonstrict;
set hive.exec.max.dynamic.partitions=5000;
set hive.exec.max.dynamic.partitions.pernode=5000;");
Thanks.
Answer is big NO. You cannot execute multiple queries in a single execute() method. Why can't you do the same in a for loop like below
String[] queries = new String[] {"SET hive.exec.dynamic.partition = true", "set hive.exec.max.dynamic.partitions=5000"}; //and so on
Statement stmt = con.createStatement();
for(int i = 0; i < queries.length; i++){
stmt.execute(queries[i]);
}
This applies for multiple hive sql queries too like select, insert, delete, etc,. based on the sql statement resultset print or populate in the JTable.
Note : execute(), executeUpdate() and executeQuery() are not the same. Choose based on your sql statement.
execute() - Returns true if the first object that the query returns is
a ResultSet object.
executeUpdate() - Returns an integer representing the number of rows
affected by the SQL statement.
executeQuery() - Returns one ResultSet object.
Reference: docs.oracle.com/javase
HTH

JDBC: How to clear the contents of a result set before using it again?

I want to clear the contents of a result set (but nothing should happen to the underlying database) before using it again to execute a new query?
Is there any method which will delete its data (but do nothing to the underlying database, that's important), so that I can use the same resultset again to retrieve data from another query?
A quick search in the API documentation gave me the idea that deleting things through a method like deleteRow() will actually delete data from the database as well. I just want to reset/refresh/clear the resultSet, so that when it is again used to get results of another query, it should contain data from that query only, and not the previous one.
Or does it automatically remove its contents itself once we have retrieved them from it (through methods like ResultSet.getInt(), ResultSet.getString() etc.)
EDIT:-
Can we create new result sets for executing each query in the same method?
Lets say you want to execute a query like this :
ResultSet rs = statement.executeQuery("select * from people");
You would iterate of the results with something like this:
while(result.next()) {
// ... get column values from this record
}
Then you just reuse the variable rs to execute another query like:
rs = statement2.executeQuery("select * from cars");
Here is a tutorial on working with ResultSet

java.sql.SQLException: The method 'rollback' can't be called when a global transaction is active

I want to use java invoke a oracle store procedure to return OracleResultSet, the store procedure have execute delete, insert and select operate(involves two tables). I set auto commit false and when execute commit() occur the error like the Title.
The code like below:
conn.setAutoCommit(false);
resultSet = getResultByInvokeSP(conn);
conn.commit();
after commit use
conn.setAutoCommit(true);
Remove your calls to setAutoCommit() and commit(). The error suggests you have another framework which is handling your transactions for you.

NullPointerException with CallableStatement.getResultSet()

I have a stored proc in SQL Server 2005, which looks like the following (simplified)
CREATE PROCEDURE FOO
#PARAMS
AS
BEGIN
-- STEP 1: POPULATE tmp_table
DECLARE #tmp_table TABLE (...)
INSERT INTO #tmp_table
SELECT * FROM BAR
-- STEP 2: USE #tmp_table FOR FINAL SELECT
SELECT abc, pqr
FROM BAZ JOIN #tmp_table
ON some_criteria
END
When I run this proc from SQL Server Management Studio, things work fine. However, when I call the same proc from a Java program, using something like:
cs = connection.prepareCall("exec proc ?,");
cs.setParam(...);
rs = cs.getResultSet(); // BOOM - Null!
while(rs.next()) {...} // NPE!
I fail to understand why the first result set returned is NULL. Can someone explain this to me?
As a workaround, if I check cs.getMoreResults() and if true, try another getResultSet() - THIS time it returns the proper result set.
Any pointers please? (I'm using JTDS drivers, if it matters)
Thanks,
Raj
The Javadoc for getResultSet() says that it returns null "... if the result is an update count or there are no more results". It looks like your stored procedure would have an update count and a resultset, and that the getResultSet() method is (arguably) just doing what the API contract says it should do.
You could try retrieving the update count first. Otherwise, stick with your "workaround".
Kind of pointless posting an answer after the correct answer has been selected I guess.
The solution I suggest is calling
set nocount on
before the insert statement and
set nocount off
afterwards. Inserts return a resultset otherwise.

Categories

Resources