SQL-Exception in Java strange - java

I have a program which is connected to a db2 z/os database. I get the following Exception:
com.ibm.db2.jcc.am.SqlException: DB2 SQL Error: SQLCODE=-805, SQLSTATE=51002, SQLERRMC=NULLID.SYSLH21E.5359534C564C3031, DRIVER=3.66.46
this one says my program is running out of statements. So I checked everything and summarised all sql-action:
Connection_1
Connection_2
Resultset set1 = Connection_1.PreparedStatement(Select Table).open
try {
while (set1.next()) {
Resultset set2 = Connection_1.PreparedStatement(find Dataset).open
try{
if(set2.next()) {
Connection_2.PreparedStatement(Insert in Table).open
Connection_2.PreparedStatement(Insert in Table).close
Connection_2.PreparedStatement(update in Table).open
Connection_2.PreparedStatement(update in Table).close
}finally {
set2.close
PreparedStatemtn(find Dataset).close
}
if (something is true){
Connection_2.commit)()
}
}
}
}finally{
set1.close
PreparedStatement(Select Table).close
Connect_2.close
}
Then in the moment just before my program chrash i create a lot of preparedStatements:
for (int i = 0; i< 10000; i++){
PreparedStatement statement = CONNECTION.prepareStatement("SELECT * FROM TABLE");
}
Then I get the following Error:
Exception stack trace:
com.ibm.db2.jcc.am.SqlException: DB2 SQL Error: SQLCODE=-805, SQLSTATE=51002, SQLERRMC=NULLID.SYSLH219 0X5359534C564C3031, DRIVER=3.66.46
Concurrently open statements:
1. SQL string: SELECT * FROM TABEL
Number of statements: 10000
2. SQL string: SELECT * FROM OTHER_TABLE
Number of statements: 1
********************
So this looks like there is no problem with open Statements. Are there other possibilitys for an exception like this? Maybe I select to many datasets?
Resultset set1 = Connection_1.PreparedStatement(Select Table).open
This table got round about 4_000_000 datasets.
I hope someone can help me. If you need more information just tell me.
Kindly Regards!

Related

Calling PL-SQL Procedure over database link from Java

here my objective is to call a procedure over a database link in java. procedure takes one input and has got cursor as an output.
to check if my code is working properly, I created dummy procedure in my database and tried executing. it is working, able to get cursor and play with it.
however when i am calling some procedure over database link, getting error as
java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00201: identifier 'HR_CLICK_GET_EMP_DETAILS#IBSLUAT1.WORLD' must be declared
I had a call with developer who had created these procedure. according to him procedures exist at this end and access is already given to my user.
Now my questions and queries are
is there something different, i have to do while calling a procedure over database link(code is below)
what are the things i should be asking to sql developer. by the way database link is right.
String prc_name = "HR_CLICK_GET_CM_AND_ABOVE#IBSLUAT1.WORLD(?,?)";
String runSP = "{ call "+prc_name+" }";
String runSP1 = "{ call get_user_by_userId(?,?) }"; this one is working
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:#xx.xx.xxx.xx:port:SERVICE", "username", "password"); // uat
CallableStatement cs = conn.prepareCall(runSP);
cs.setString(1, "705151");
cs.registerOutParameter(2, OracleTypes.CURSOR);
cs.execute();
// get refcursor and convert it to ResultSet
ResultSet resultSet = (ResultSet) cs.getObject(2);
ResultSetMetaData rsmd = resultSet.getMetaData();
int columnCount = rsmd.getColumnCount();
System.out.println("Total Columns in ResultSet : "+columnCount);
System.out.println("Now Analyzing column one by one:\n\n-----------------------------------------------");
for (int i = 1; i <= columnCount; i++ ) {
String name = rsmd.getColumnName(i);
System.out.println("Column No:"+i+">>>>>>>>"+name);
}
}
catch(SQLException s)
{
s.printStackTrace();
}
catch(ClassNotFoundException s)
{
s.printStackTrace();
}
thanks in advance
Ashish
Try to use the Oracle user's name who owns the procedure as a prefix:
username.HR_CLICK_GET_EMP_DETAILS#IBSLUAT1.WORLD
Answer is "synonym".
SQL Developer has created a synonym for HR_CLICK_GET_EMP_DETAILS as HR_CLICK_GET_EMP_DETAILS#IBSLUAT1.WORLD
that is what he informed me, I could not quite wrap my head around that but able to hit the procedure.
but now , able to get get the metadata of a result set but unable to traverse rows.
I'm getting an error:
java.sql.SQLException: ORA-24338: statement handle not executed
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:743)
at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:207)
at oracle.jdbc.driver.T4CStatement.fetch(T4CStatement.java:1018)
at oracle.jdbc.driver.OracleResultSetImpl.close_or_fetch_from_next(OracleResultSetImpl.java:291)
at oracle.jdbc.driver.OracleResultSetImpl.next(OracleResultSetImpl.java:213)
at ashishtest.StoredProcedureCursor.main(StoredProcedureCursor.java:80)
I guess, new forum is required for this error.
also I am not marking this as solved as not sure how solution works.

Uncaught SoapFault exception: [soapenv:Server] Before start of result set

I am developing a web service for e-commerce website, and i am returning all products based on some supplier_id from java into php client but it is giving me this error
Fatal error: Uncaught SoapFault exception: [soapenv:Server] Before start of result set in C:\wamp\www\eshop\viewProductsSupplier.php:194 Stack trace: #0 C:\wamp\www\eshop\viewProductsSupplier.php(194): SoapClient->__soapCall('viewProducts', Array) #1 {main} thrown in C:\wamp\www\eshop\viewProductsSupplier.php on line 194
I have tried to check whether the query executes or not but it is all fine
//php code
$soapclient = new SoapClient('http://localhost:8090/Eshop_ecommerce/services/Eshop_ecommerce?wsdl', ['trace' => 1]);
session_start();
$id=array('id'=>#$_SESSION['supplierId']);
$response=$soapclient->__soapCall("viewProducts",$id);
if (isset($response->Name))
{
print $response;
}
else
{
print "Data is null";
}
//Java code
ViewProductsResponse res = new ViewProductsResponse();
Class.forName(driver);
conn = DriverManager.getConnection(url,username,password);
stmt = conn.createStatement();
String Query=null;
String in=viewProducts.getViewProductsRequest();
if(!in.isEmpty())
{
Query="SELECT * FROM product";
}
else
{
Query="SELECT * FROM product WHERE product_supplier_id='"+viewProducts.getViewProductsRequest()+"'";
}
ProductArray pa=new ProductArray();
ResultSet result= stmt.executeQuery(Query);
//System.out.println(result);
while(result.next())
{
Product p= new Product();
//System.out.println(result.getString("product_id"));
p.setId(result.getString("product_id"));
p.setName(result.getString("product_name"));
p.setPrice(result.getString("product_price"));
p.setStock(result.getString("product_stock"));
String supplierNameQuery="SELECT supplier_id,supplier_name FROM supplier WHERE supplier_id='"+result.getString("product_supplier_id")+"'";
ResultSet resultSupplierName = stmt.executeQuery(supplierNameQuery);
p.setSupplierName(resultSupplierName.getString("supplier_name"));
String catQuery="SELECT * FROM product_category WHERE category_id='"+result.getString("product_category_id")+"'";
ResultSet resCat= stmt.executeQuery(catQuery);
p.setCategoryName(resCat.getString("category_name"));
pa.setProduct(p);
res.setProducts(pa);
}
//res.setViewProductsResponse("Data Entered");
return res;
where as i expect it to print all the resulting products
A ResultSet returned from Statement#executeQuery is positioned before the first row (see linked-in JavaDoc). In order for such ResultSet to point to the first row it needs re-positioned to it, for example using the next() method. This is done for the outer SELECT but not for the two inner ones. Further the return value from next() call needs to be checked in order to see if there is any row at all in that ResultSet.
This can be achieved for example like this:
if(resultSupplierName.next()) {
p.setSupplierName(resultSupplierName.getString("supplier_name"));
}
if(resCat.next()) {
p.setCategoryName(resCat.getString("category_name"));
}
Please note that the posted code has other open issues, for example the JDBC resources are not closed. I would strongly suggest to look either into JEE or Spring (giving that the code apparently runs in aplication server) or at least at this. Further is the code prone to SQL injection

Java SQL Exception while Inserting large amount of Data

I am trying to Insert large amount of data from one table to another table. The two tables are in different regions. When I Insert data, the ID (I am using to create connection)is able to insert data for less number of rows. If It inserts data for more than 500 rows it throws exception
com.ibm.db2.jcc.b.SqlException: DB2 SQL error: SQLCODE: -551, SQLSTATE: 42501, SQLERRMC: DB2GCS;EXECUTE PACKAGE;NULLID.SYSLH203.
I am not able to find why it shows authorization exception for the same id if data is more.
My Code Snippet :
while(RSet.next()){
stmt=test_conn.prepareStatement("Insert Query");
for(int i=1;i<=columnCount;i++){
stmt.setString(i,RSet.getString(i));
}
stmt.addBatch();;
}
stmt.executeBatch();
Thanks in Advance for Your Help.
Your code is actually not batching correctly and this could be the reason why it's breaking. The problem is that you're preparing your insert query over and over again needlessly.
You need to prepare it just once outside the loop like
test_conn.setAutoCommit(false);
stmt = test_conn.prepareStatement("INSERT INTO ...");
while(RSet.next()){
for(int i = 1; i <= columnCount; i++){
stmt.setString(i, RSet.getString(i));
}
stmt.addBatch();
}
stmt.executeBatch();
test_conn.commit();

How to use join between two tables correctly in sql I have an exception

I've faced a problems with sql queries, and I need your help plz :(.
In my code I want to display the names of students from c#Log when entering the id of this course this is the c#Log table : HERE
and this is the courses table :HERE
This is my code :
public void searchRows() throws ClassNotFoundException, SQLException
{
String logName=null;
Class.forName("com.mysql.jdbc.Driver");
Connection con = (Connection) DriverManager.getConnection("jdbc:mysql://localhost/psd_DB?"
+ "user=root&password=123");
Scanner s=new Scanner(System.in);
System.out.println("Enter the course id you want to display its log:");
courseId=Integer.parseInt(s.nextLine());
PreparedStatement st1 = (PreparedStatement) con.prepareStatement(" SELECT * FROM courses WHERE courseId="+courseId);
ResultSet r=(ResultSet) st1.executeQuery();
while(r.next())
{
logName=r.getString("courseName")+"Log";
}
//System.out.println(logName);
PreparedStatement st2 = (PreparedStatement) con.prepareStatement("SELECT "+logName+"."+"studentName FROM "+logName+" INNER JOIN courses ON "+logName+"."+courseId+"="+"courses."+courseId+";");
st2.executeQuery();
}
when I've entered 2 , the output is this exception :
Exception in thread "main" com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Unknown column 'C' in 'field list'
First of all you are using PreparedStatement but still you code is vulnerable to SQL Injection.
Do it like this:
courseId=Integer.parseInt(s.nextLine());
PreparedStatement st1 = (PreparedStatement) con.prepareStatement("
SELECT * FROM courses WHERE courseId=?");
st1.setInt(1,courseId);
ResultSet r = st1.executeQuery();
Also the exception is quite self-explanatory :
Unknown column C meaning you are trying to select a column from your table that does not exist, so better check if you are accessing correct columns.
A workaround : print the sql queries before executing them so that you know which query is getting executed (you can remove this print statements after once you get your expected results).
The join is not the immediate problem - you are specifying an unknown column in the sql statement.
Try using a debugger to see the contents of the SQL statements, or simply output them to the console and try running them manually against your database

java.lang.OutOfMemoryError: Java heap space error when performing millions of queries

In my application, I need to perform millions of queries to MySQL database. The codes look as follows:
for (int i=0; i< num_rows ; i++) {
String query2="select id from mytable where x='"+ y.get(i) "'";
Statement stmt2 = Con0.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
ResultSet rs2 = stmt2.executeQuery(query2);
... // process result in rs2
rs2.close();
}
where num_rows is around 2 million. After 600k loops, java report an error and exit:
java.lang.OutOfMemoryError: Java heap space error.
What's wrong in my codes? How should I avoid such an error?
Thanks in advance!
Close your statements as well.
Statement is no good solution here. Try the following code:
PreparedStatement pre = Con0.prepareStatement("select id from mytable where x=?");
for (int i=0; i< num_rows ; i++) {
pre.setString(1, y.get(i));
ResultSet rs2 = pre.executeQuery();
... // process result in rs2
rs2.close();
pre.clearParameters();
}
pre.close();
I don't know if the answer accepted by you have solved your problem, since it doesn't change anything that could cause the problem.
The problem is when ResultSet is caching all the rows returned by the query, which can either be stored while you iterate through set, or prefetched. I've had similar problem with PostgreSQL JDBC driver, which ignored the cursor fetch size, when running in no-trasactional mode.
The JDBC driver should use cursors for such queries, so you should check driver's documentation about fetchSize parameter. As alternative, you can manage cursors yourself executing SQL command to create cursor and fetch next X rows.
Using a preparedStatement, since only the value of X changes in each loop, declared outside de loop should help. You're also, at least in the shown code, not closing the statement used, which might not help the garbage collector to free the used memory.
Assuming that you are using a single connection for all your queries, and assuming your code is more complicated than what you show us, it is critical that you ensure that each Statement and each ResultSet is closed when you are finished with it. This means that you need a try/finally block like this:
for (int i=0; i< num_rows ; i++) {
String query2="select id from mytable where x='"+ y.get(i) "'";
Statement stmt2 = Con0.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
ResultSet rs2 = null;
try {
rs2 = stmt2.executeQuery(query2);
... // process result in rs2
} finally {
try {
stmt2.close();
} catch (SQLException sqle) {
// complain to logs
}
try {
if (rs2 != null) { rs2.close(); }
} catch (SQLException sqle) {
}
}
}
If you do not aggressively and deterministically close all result set and statement objects, and if you do requests quickly enough, you will run out of memory.

Categories

Resources