I have done below sample JDBC program which retrieving user details.Now i am getting surprised that from same callable statement i am getting different result set for same output parameter index.Ideally it should return same ResultSet object.
when i got the resultset then i am moving cursor -1 to 0.
i am retrieving data from another resultset for the same output param using
column name then i am getting following exception
,
Exception in thread "main" java.sql.SQLException: Missing defines
System.out.println("Before loading connection");
DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
Connection connection = DriverManager.getConnection(
"jdbc:oracle:thin:#170.45.3.165:1541/testdb.mycomp.com",
"admin", "admin123");
System.out.println("Connection loaded " + connection);
CallableStatement callProcedure = connection
.prepareCall("{call ADMIN_USER.Fetch_User_Details(?,?)}");
callProcedure.setString(1, "userid=testid");
callProcedure.registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR);
callProcedure.execute();
ResultSet resultUserDetails = (ResultSet) callProcedure.getObject(2);
resultUserDetails.next();
ResultSet resultUserDetails1 = (ResultSet) callProcedure.getObject(2);
String username = resultUserDetails1.getString(COL_NAME_USER_NAME);
System.out.println(resultUserDetails);
System.out.println(resultUserDetails1);
System.out.println(resultUserDetails == resultUserDetails1);
Can anyone has any idea why we are getting two different resultset for same output index from callable statement?
According to CallableSatement API the expression should be like this
{call <procedure-name>[(<arg1>,<arg2>, ...)]}
try
CallableStatement callProcedure = connection.prepareCall("{call ADMIN_USER.Fetch_User_Details(?,?)}");
Have you tried to check if only reference are different (maybe due to proxy or dirty state because you perform a next() before the second `getObject())?
try
ResultSet resultUserDetails = (ResultSet) callProcedure.getObject(2);
ResultSet resultUserDetails1 = (ResultSet) callProcedure.getObject(2);
System.out.println(resultUserDetails);
System.out.println(resultUserDetails1);
// Check ref or object equality
System.out.println(resultUserDetails == resultUserDetails1);
System.out.println(resultUserDetails.equals(resultUserDetails1));
resultUserDetails.next();
String username = resultUserDetails.getString(COL_NAME_USER_NAME);
resultUserDetails1.next();
String username1 = resultUserDetails1.getString(COL_NAME_USER_NAME);
System.out.println(username);
System.out.println(username1);
// We read the same username or we are reading first and second username?
// If the are different probably resultset is the same, just with different
// reference
System.out.println(resultUserDetails.equals(resultUserDetails1));
Related
Can JDBC statement run explain plan on query string?
The code throws SQL exception
Error message: Incorrect syntax near the keyword 'plan'.
Stacktrace is null
I just copy from internet of using stmt.execute. However, it seems that stmt.execute() only Returns true if the first result is a ResultSet object; false if it is an update count or there are no results
conn = getEntityManager().unwrap(java.sql.Connection.class);
stmt = conn.createStatement();
stmt.execute("explain plan for SELECT 1 from Dual"); // throws sql exception
rs = stmt.executeQuery("select plan_table_output from table(dbms_xplan.display())");
while (rs.next())
{
System.out.println(rs.getString(1));
}
here is the code there is catch close but i delete it so can anyone replay to me
String id = null;
String root="root",student="root";
String name=jTextField1.getText();
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
Connection
con=(Connection)DriverManager.getConnection
("jdbc:mysql://localhost:3306
/dijlafinal1",root,student);
String query2="SELECT * FROM name WHERE name like ? ";
PreparedStatement pstm2=null;
pstm2=con.prepareStatement(query2);
pstm2.setString(1,"%"+name+"%");
ResultSet rs = pstm2.executeQuery(query2 );
while (rs.first()){
String name1=rs.getString("name");
id= rs.getString("id");
int epo =rs.getInt("epo");
}
jTextField2.setText(id);
}
You need to use the no-argument version of executeQuery(), i.e.
ResultSet rs = pstm2.executeQuery();
The reason is that you've already prepared the statement when you called con.prepareStatement(query2). Calling executeQuery(query2) will throw away the prepared SQL and execute the query without bind variables, leaving the ? in place -- as the error message suggests.
When working with a PreparedStatement you always call the .execute... methods without any arguments because you have already supplied the SQL command text with the .prepareStatement call. So
ResultSet rs = pstm2.executeQuery(query2 );
is incorrect. You need to simply do
ResultSet rs = pstm2.executeQuery();
I wonder if it might work if you use this?
pstm2.setString(1,"'%"+name+"%'");
I have created a package in my Oracle database which includes several procedures, now I want to call procedure from java program procedure requires two input parameter and returns nothing.
Please help me to do so, I have been using below connection to connect to database:
String i =username.getText();
String j =psswd.getText();
String k = sid.getText();
Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection("jdbc:oracle:thin:#ora211g.home.com:1654:ora11g",username,password);
st = con.createStatement();
rs =st.executeQuery("SELECT DISTINCT SUBJECT_AREA FROM REP_SUBJECT");
This thing is working fine, now how can I call procedure by passing some parameter (say two string values)
This useful blog posting will help you
http://jameajudo.blogspot.com.br/2009/03/call-procedure-oracle-with-java-and.html
The example he uses is:
String command = "{call SALDOS(?,?)}";
CallableStatement cstmt = con.prepareCall (command);
cstmt.registerOutParameter(2, Types.DECIMAL);
cstmt.execute();
2This is what you want
st = con.prepareStatement("SELECT DISTINCT SUBJECT_AREA FROM REP_SUBJECT WHERE A = ? AND B = ?");
st.setString(1, "val1");
st.setString(2, "val2");
rs =st.executeQuery();
Using con.prepareCall().
And then using the CallableStatement object that is returned for setting params and execution.
Here I got the solution of my question so thought of posting it here so that everybody can understand in detail:
Connection con = null;
ResultSet rs = null;
Statement st = null;
Class.forName = Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection( "jdbc:oracle:thin:#host:port:SID);
CallableStatement csmt = con.prepareCall("{call PACKAGE_NAME.PROCEDURE_NAME(?,?,?,?)}");
csmt.setString(1,"abc");
csmt.setString(2,"def");
csmt.setString(3,"ghi");
csmt.registerOutParameter(4,java.sql.Types.VARCHAR);
csmt.execute();
String message =csmt.getString(4);
here '?' indicates the number of input and output parameters in your procedure. I had 3 input and 1 output parameter so number of '?' in procedure are 4.
there indexing start with 1,2,3....
my first three input parameter are a string, so i am passing them to procedure using :
csmt.setString(1,"abc");
csmt.setString(2,"def");
csmt.setString(3,"ghi");
my Procedure returns string, so in order to get receive that in java first I have to register the out parameter so I have done the same using :
csmt.registerOutParameter(4,java.sql.Types.VARCHAR); /*4 becuase out parameter is 4th*/
Then I have executed callable statement and after that I am receiving the return from procedure into
String message =csmt.getString(4);
Enjoy..... \M/
I am creating a program to rename databases in mysql.
I have succeeded in everything and it successfully happens. But in the end of my script, its shows an error/exception saying "Operation not allowed after ResultSet closed". I really have no idea why this error appears even after researching about this error.
Although the full operation is successfully completed and the database is renamed.
Here is my code->
String x = (String) jComboBox1.getSelectedItem(); //jComboBox1 contains the name of current database selected
String z = JOptionPane.showInputDialog("Please enter new name for Database"); //Where user enters the name for new database.
new CustComm().setVisible(false); //Frame that carries the names of tables.
try{
Class.forName("java.sql.DriverManager");
Connection con = (Connection)
DriverManager.getConnection("jdbc:mysql://localhost:"+GlobalParams.portvar+"/",""+k,""+j);
Statement stmnt = (Statement) con.createStatement();
String query = "use "+x;
stmnt.executeQuery(query);
String query2 = "show tables";
ResultSet rs = stmnt.executeQuery(query2);
while (rs.next()){
String dname = rs.getString("Tables_in_"+x);
if(CustComm.jTextArea1.getText().equals("")){
CustComm.jTextArea1.setText(CustComm.jTextArea1.getText()+dname);
}
else{
CustComm.jTextArea1.setText(CustComm.jTextArea1.getText()+"\n"+dname);
}
String y = CustComm.jTextArea1.getText();
Scanner scanner = new Scanner(y);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
String query3 = "Create database "+z;
stmnt.executeUpdate(query3);
//alter table my_old_db.mytable rename my_new_db.mytable
String query4 = "RENAME TABLE "+x+"."+line+" TO "+z+"."+line;
stmnt.executeUpdate(query4);
String query5 = "drop database "+x;
stmnt.executeUpdate(query5);
}}}
catch(Exception e){
JOptionPane.showMessageDialog(this,e.getMessage());
}
Please help.
You shouldn't execute new queries on statement Statement stmnt = (Statement) con.createStatement(); while you use ResultSet from it, because this will close your ResultSet.
By default, only one ResultSet object per Statement object can be open
at the same time. Therefore, if the reading of one ResultSet object is
interleaved with the reading of another, each must have been generated
by different Statement objects. All execution methods in the Statement
interface implicitly close a statment's current ResultSet object if an
open one exists.
You should create 2 different statements: first for query2 and second for queries 3-5.
Also it's better to use PreparedStatement. You can read about the difference here.
Do you have to do this work via code? Have you looked into tools like Liquibase?
When I execute the following code, I get an exception. I think it is because I'm preparing in new statement with he same connection object. How should I rewrite this so that I can create a prepared statement AND get to use rs2? Do I have to create a new connection object even if the connection is to the same DB?
try
{
//Get some stuff
String name = "";
String sql = "SELECT `name` FROM `user` WHERE `id` = " + userId + " LIMIT 1;";
ResultSet rs = statement.executeQuery(sql);
if(rs.next())
{
name = rs.getString("name");
}
String sql2 = "SELECT `id` FROM `profiles` WHERE `id` =" + profId + ";";
ResultSet rs2 = statement.executeQuery(sql2);
String updateSql = "INSERT INTO `blah`............";
PreparedStatement pst = (PreparedStatement)connection.prepareStatement(updateSql);
while(rs2.next())
{
int id = rs2.getInt("id");
int stuff = getStuff(id);
pst.setInt(1, stuff);
pst.addBatch();
}
pst.executeBatch();
}
catch (Exception e)
{
e.printStackTrace();
}
private int getStuff(int id)
{
try
{
String sql = "SELECT ......;";
ResultSet rs = statement.executeQuery(sql);
if(rs.next())
{
return rs.getInt("something");
}
return -1;
}//code continues
The problem is with the way you fetch data in getStuff(). Each time you visit getStuff() you obtain a fresh ResultSet but you don't close it.
This violates the expectation of the Statement class (see here - http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html):
By default, only one ResultSet object per Statement object can be open at the same time. Therefore, if the reading of one ResultSet object is interleaved with the reading of another, each must have been generated by different Statement objects. All execution methods in the Statement interface implicitly close a statment's current ResultSet object if an open one exists.
What makes things even worse is the rs from the calling code. It is also derived off-of the statement field but it is not closed.
Bottom line: you have several ResultSet pertaining to the same Statement object concurrently opened.
A ResultSet object is automatically
closed when the Statement object that
generated it is closed, re-executed,
or used to retrieve the next result
from a sequence of multiple results.
I guess after while(rs2.next()) you are trying to access something from rs1. But it's already closed since you reexecuted statement to get rs2 from it. Since you didn't close it, I beleive it's used again below.