SQL, JDBC "Invalid column index" error with simple query - java

I'm new to STRUTS and JDBC, my application tries to connect to a simple DB that has 3 tables, right now all is doing is trying to query 1 table that only stores "first, last names and a Id field"
System.out.println("-------- Oracle JDBC Connection Testing ------");
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
System.out.println("Where is your Oracle JDBC Driver?");
e.printStackTrace();
return null;
}
System.out.println("Oracle JDBC Driver Registered!");
try {
connection =
DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:xe","david","changeit");
} catch (SQLException e) {
System.out.println("Connection Failed! Check output console");
e.printStackTrace();
return null;
}
if (connection != null) {
System.out.println("You made it, take control your database now!");
} else {
System.out.println("Failed to make connection!");
}
where I would like to get the result of 1 column if a match occurs:
String sql = "SELECT S_ID FROM Students WHERE firstname=? AND lastname=?";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, firstname);
ps.setString(2, lastname);
rs = ps.executeQuery();
while (rs.next()) {
studentid = rs.getString(1);
ret = SUCCESS;
}
} catch (Exception e) { ...
As far as I can tell the connection is made,
the SQL query
Select s_id from Students where firstname='first' and lastname='last';
when run on SQL Dev. works and gives me a single result.
I don't really get a stack trace the code just jumps from right before the 'while (rs.next()) {..' directly into the finally block
} catch (Exception e) {
e.printStackTrace();
ret = ERROR;
} finally {
if (connection != null) {
try {
connection.close();
} catch (Exception e) {
}
}
}

I'm not sure how Oracle drivers work. But below statement is what i see on Oracle site. Are you getting a non empty resultset ?
As you are not getting a nullpointerexception on .next(), i'm wondering if Oracle drivers return an empty ResultSet, which may lead to this problem.
http://docs.oracle.com/cd/B28359_01/java.111/b31224/getsta.htm
In case of a standard JDBC driver, if the SQL string being executed
does not return a ResultSet object, then the executeQuery method
throws a SQLException exception. In case of an Oracle JDBC driver, the
executeQuery method does not throw a SQLException exception even if
the SQL string being executed does not return a ResultSet object.

Like I said I'm new at using this.
The problem was that my schema didn't have the CONNECT role assigned to it.
Solution log in as 'SYSTEM' and grant the role to my schema
grant connect to MY_SCHEMA;

Related

Jdbc connection using java

I have Rest-Api in the java.
That will take dbUrl, dbUserName, dbPassWord, dbDriver and sql query
and gives me the result set and after I will be converting into json format.
Class.forName("oracle.jdbc.driver.OracleDriver");
connectionUrl = "jdbc:oracle:thin:#" + server + ":" + dbName + "";
conn = DriverManager.getConnection(connectionUrl, userName, password);
try {
stmt = conn.createStatement();
output = resultSetHandler(stmt.executeQuery(query)); // this method convert ResultSet to Json
} catch (SQLException e) {
throw new Error(e);
} finally {
if (stmt != null) {
stmt.close();
}
}
} catch (SQLException e) {
throw new Error(e);
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (SQLException ex) {
throw new Error(ex);
}
}
The problem here is that When 30 users use this api at one time means It will throw an error for few users....
and also I will not be using just oracle and I will be using postgres, mysql also
Consider using DB connection pool such as Hikari or C3P0 (both available at Maven Repository). Opening a connection every time is very inefficient and you may run out of connections which may be the error you are getting. Please post your error.
Use try-with-resources instead of doing the finally block. It will automatically call close() on Autoclosable objects such as Connection, Statement, PreparedStatement, ResultSet, etc.
try (
Connection myConnection = MyConnectionPool.getConnection();
Statement stmt = myConnection.createStatement();
ResultSet rs = stmt.executeQuery(query)
) {
// Do work with rs
}

CachedRowSet and SQLite JDBC driver

I'm trying to use CachedRowSet with SQLite and Xerial driver https://bitbucket.org/xerial/sqlite-jdbc .
If I call execute() method like that:
Connection connection = DriverManager.getConnection("jdbc:sqlite:sample.db");
CachedRowSet crs = new CachedRowSetImpl();
crs.setCommand("select * from person");
crs.execute(connection);
I'm getting the SQLException "not implemented by SQLite JDBC driver":
at com.sun.rowset.internal.CachedRowSetReader.readData(Unknown Source)
at com.sun.rowset.CachedRowSetImpl.execute(Unknown Source)
at com.sun.rowset.CachedRowSetImpl.execute(Unknown Source)
at com.oracle.tutorial.jdbc.CachedRowSetSample.testPaging(CachedRowSetSample.java:100)
at com.oracle.tutorial.jdbc.CachedRowSetSample.main(CachedRowSetSample.java:273)
on the other hand ResultSet and populate() insteed of excecute() works ok:
Connection connection = DriverManager.getConnection("jdbc:sqlite:sample.db");
statement = connection.createStatement();
ResultSet rs = statement.executeQuery("select * from person");
CachedRowSet crs = new CachedRowSetImpl();
crs.populate(rs);
Does anybody know whats wrong with execute()?
Unfortunately there's a handful of JDBC functions you'll have to implement workarounds for when using SQLite. This happens to be one of them. Probably the best alternate solution is to put the entire result set into a List<> and work with that:
// Variables.
final int TIMEOUT_DEFAULT=30;
String query = "select * from person";
ResultSet rs;
Statement statement;
List<String[]> people;
...
// Create query and execute. (Connection established, database open.)
try {
statement = connection.createStatement();
statement.setQueryTimeout(TIMEOUT_DEFAULT);
connection.setAutoCommit(true);
rs = statement.executeQuery(query);
} catch (SQLException e) {
// If error, close connection & ignore close errors.
try { connection.close(); }
catch (SQLException e2) { /* Ignore */ }
// Throw new error.
throw new SQLException("Query failed",e);
}
// Retrieve results.
try {
people = new ArrayList<>();
while (rs.next()) {
people.add(new String[]{
rs.getString(1), rs.getString(2), rs.getString(3)
});
}
} catch (SQLException e) {
// If error, close connection & ignore close errors.
try { connection.close(); }
catch (SQLException e2) { /* Ignore */ }
// Throw new error.
throw new SQLException("Error retrieving data",e);
}
// Close connection, ignore error.
try {
connection.close();
} catch (SQLException e) { /* Ignore */ }
// Print output.
for (String[] p : people) {
System.out.println(Arrays.deepToString(p));
}
An answer in this post contains a comment about simulating a function if it's not supported by your driver.

combination of Oracle database and in-memory database in java program

I am going to enhance the performance of my program. For this purpose I am going to implement some parts of my program to be done in memory instead of database. I dont know which one is better in this regards, in-memory database or normal java data structure.For in-memory database I considered Tentimes from oracle and H2. So another question would be which solution is better for around 100 million records of data on single machine for single user? Also another question would be is the old way of database connection works fine in this way? Here is the connection that I used for oracle, What is the appropriate Driver for this purpose.
public static Connection getConnection(){
//If instance has not been created yet, create it
if(DatabaseManager.connection == null){
initConnection();
}
return DatabaseManager.connection;
}
//Gets JDBC connection instance
private static void initConnection(){
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String connectionUrl = "jdbc:oracle:thin:#localhost:1521:" + dbName;
DatabaseManager.connection =
DriverManager.getConnection(connectionUrl,"****","****");
}
catch (ClassNotFoundException e){
System.out.println("Oracle driver is not loaded!");
System.exit(0);
}
catch (SQLException e){
System.out.println(e.getMessage());
System.exit(0);
}
catch (Exception e){
}
}
public static ResultSet executeQuery(String SQL) throws SQLException
{
CachedRowSetImpl crs = new CachedRowSetImpl();
ResultSet rset = null ;
Statement st = null;
try {
st = DatabaseManager.getConnection().createStatement();
rset = st.executeQuery(SQL);
crs.populate(rset);
}
catch (SQLException e) {
System.out.println(e.getMessage());
System.exit(0);
}finally{
rset.close();
st.close();
}
return crs;
}
public static void executeUpdate(String SQL)
{
try {
Statement st = DatabaseManager.getConnection().createStatement();
st.executeUpdate(SQL);
// st.close();
}
catch (SQLException e) {
System.out.println(e.getMessage());
System.exit(0);
}
}
Regards.

How can I insert data from a connection to other connection?

I want to insert data from a table which connection is oracle to another table which connection is mysql. I use netbeans and jdbc driver.
Is it possible? I mean how can I do select data from A table (X connection) and insert B table (Y connection)
connection X = DriverManager.getConnection("jdbc:oracle:thin:#" + host__ + ":" + port__ + servic, props);
connection Y = DriverManager.getConnection("jdbc:mysql://hostname:port/dbname","username", "password");
conn.close();
Thank you.
Here is a small example that copies a database table to another database.
You just need two connections conf(rom) and cont(o). You will need to modify both getConnection parameters, table names and field types.
// Copy
Statement stf, stmt;
Connection conf, cont;
ResultSet rsf, rs;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
Class.forName("com.mysql.jdbc.Driver");
conf = DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:" + databaseFrom, "user1", "passwd1");
try {
stf = conf.createStatement();
rsf = stf.executeQuery("select * from supplier order by sname");
// read from rsf write to rs!
cont = DriverManager.getConnection("jdbc:mysql://localhost:3306/" + databaseTo, "user2", "passwd2");
stmt = cont.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
rs = stmt.executeQuery("select * from supplier order by sname");
while (rsf.next()) {
rs.moveToInsertRow();
rs.updateInt(1, rsf.getInt(1));
rs.updateString(2, rsf.getString(2));
rs.updateString(3, rsf.getString(3));
rs.updateString(4, rsf.getString(4));
rs.updateInt(5, rsf.getInt(5));
rs.updateString(6, rsf.getString(6));
rs.updateInt(7, rsf.getInt(7));
rs.updateDouble(8, rsf.getDouble(8));
rs.updateString(9, rsf.getString(9));
rs.insertRow();
}
} catch (SQLException s) {
JOptionPane.showMessageDialog(this, "problem creating database " + s);
}
} catch (Exception e) {
JOptionPane.showMessageDialog(this, e.getStackTrace());
} finally {
if (stf != null) {
try {
stf.close();
stmt.close();
} catch (SQLException e) {
// handle Exception
}
}
if (conf != null) {
try {
conf.close();
cont.close();
} catch (SQLException e) {
// handle Exception
}
}
}
You can create two classes for different connection:
public class OracleConnectionManager {
public static Connection getOracleConnection() throws SQLException, ClassNotFoundException {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection connection = null;
connection = DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:oracle","username","password");
return connection;
}
}
public class MySqlConnectionManager {
public static Connection getMySqlConnection() throws SQLException, ClassNotFoundException {
Class.forName("com.mysql.jdbc.Driver");
Connection connection = null;
connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306:mysql","username","password");
return connection;
}
}
Now you can use these classes to get the specific connections and do whatever you want.
You can get the oracle database connection and get the oracle statement > Resultsset, iterate over it
and insert the data into mysql.
Please let me know in case more information is required.
Follow these steps:
Connect to the Oracle database with one data access class
Connect to the MySQL database with a different data access class
Read row(s) from a table in the Oracle database
Perform any column transformations
Write row(s) to a table in the MySQL database
Close the database connections

JDBC result set from an Oracle PL/SQL stored procedure

What does oracleClose() and oracleCloseQuery() do in sqlj.runtime.ExecutionContext.OracleContext.
Since we upgraded jdbc driver jar to ojdbc5.jar with the oracleClose() in the finally block we get the below exception when using resultset.next() and not with oracleCloseQuery(). Is it safe to use oracleCloseQuery(). The database is Oracle 11g and WAS 6.1.X.X. Appreciate your response.
Here is the error message :
java.sql.SQLException: Closed Statement: next
at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:70)
at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:131)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:197)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:261)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:269)
at oracle.jdbc.driver.OracleResultSetImpl.next(OracleResultSetImpl.java:205)
at com.westgroup.pubsvc.rms.models.ResultSetSRC.getNextResult(ResultSetSRC.java:112)
The exception is telling you that the Statement which has returned this ResultSet is been closed while you're attempting to iterate over the ResultSet. This indicates that you're using ResultSet outside the try block where the Statement is been executed and that you're probably using the ResultSet as return value of the method. This is a bad practice.
I'd suggest you to rewrite your JDBC code so that the ResultSet is been processed in the very same try block as the Statement is been executed, or that the methods returns something like as List<Entity> instead of a ResultSet.
Here's a kickoff example of the correct JDBC idiom:
public List<Entity> list() throws SQLException {
// Declare resources.
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
List<Entity> entities = new ArrayList<Entity>();
try {
// Acquire resources.
connection = database.getConnection();
statement = connection.createStatement("SELECT id, name, value FROM entity");
resultSet = statement.executeQuery();
// Gather data.
while (resultSet.next()) {
Entity entity = new Entity();
entity.setId(resultSet.getLong("id"));
entity.setName(resultSet.getString("name"));
entity.setValue(resultSet.getInteger("value"));
entities.add(entity);
}
} finally {
// Close resources in reversed order.
if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {}
if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
// Return data.
return entities;
}
By the way, you don't need Oracle JDBC driver specific classes/methods here. It's all just java.sql.*. This way you keep the JDBC code portable among databases.

Categories