How to access this stored Procedure from JDBC Callablestatement? - jdbc

How to access this stored Procedure from JDBC Callablestatement ??
public class TestOCIApp {
public static void main(String args[]) throws ClassNotFoundException,
SQLException {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:orcle", "scott", "tiger");
CallableStatement cs = conn.prepareCall("{call test(?,?)}");
cs.setInt(1, 10);
cs.registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR);
ResultSet rs = (ResultSet)cs.getObject(2);
while(rs.next())
{
System.out.println(rs.getString(2));
}
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
I am getting Exception as
java.sql.SQLException: Invalid column index
* at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:180)*
* at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:222)*
* at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:285)*
* at oracle.jdbc.driver.OracleStatement.prepare_for_new_get(OracleStatement.java:2804)*
* at oracle.jdbc.driver.OracleStatement.getObjectValue(OracleStatement.java:4983)*
* at oracle.jdbc.driver.OracleStatement.getObjectValue(OracleStatement.java:4964)*
* at oracle.jdbc.driver.OracleCallableStatement.getObject(OracleCallableStatement.java:586)*
* at TestOCIApp.main(TestOCIApp.java:23)*
create or replace procedure test( p_deptno IN number
, p_cursor OUT SYS_REFCURSOR)
is
begin
open p_cursor FOR
select *
from emp
where deptno = p_deptno;
end test;
/

When dealign with oracle cursors,The CallableStatement object is cast to OracleCallableStatement to use the getCursor method, which is an Oracle extension to the standard JDBC application programming interface (API), and returns the REF CURSOR into a ResultSet object.
cstmt.registerOutParameter(1, OracleTypes.CURSOR);
cstmt.execute();
cursor = ((OracleCallableStatement)cstmt).getCursor(1);
while (cursor.next ()){
System.out.println (cursor.getString(1));
}
But this will couple your code to oracle database [:(]

Related

How to use oracle proxy connection with JPA repository

I'm using this openProxyConnection in the oracle method to create a proxy user to the database and used it with JDBC connection as below.
public static void openProxyConnection(OracleConnection conn, HttpUserDetails userDetails)
throws SQLException {
java.util.Properties prop = new java.util.Properties();
prop.put(OracleConnection.PROXY_USER_NAME,
userDetails.getUserName().toUpperCase()); //To uppercase needed for 11g compatibility
try {
// Open proxy connection for user
conn.openProxySession(OracleConnection.PROXYTYPE_USER_NAME, prop);
log.debug("Login proxy user: " + userDetails.getUserName());
try (PreparedStatement preparedStatement = conn
.prepareStatement("begin DBMS_APPLICATION_INFO.SET_CLIENT_INFO (?); end;")) {
preparedStatement.setString(1, userDetails.getClientIp());
preparedStatement.execute();
}
} catch (Exception e) {
throw new ProxyConnectionException("Error creating proxy connection", e);
}
}
#Override
public GetHostNameOutputDto getUserDetailsList(GetHostNameInputDto loginRequest, String spcNumber)
throws SQLException {
OracleCallableStatement statement = null;
OracleConnection connection = null;
GetHostNameOutputDto getHostNameOutputDto = new GetHostNameOutputDto();
try {
connection = (OracleConnection) dataSource.getConnection();
DbUtil.openProxyConnection(connection, httpUserDetails);
statement = (oracle.jdbc.OracleCallableStatement) connection
.prepareCall("begin ? := spc_login.get_host_name(?); end;");
statement.registerOutParameter(1, OracleTypes.VARCHAR);
statement.executeQuery();
...
As in the above example would I be able to get the proxy connection for JpaRepository? Something like below?
List<JobCode> jobCodeList = jobCodeRepository.findByLfunLbrFuncAndCorpCode("IN", "Y");

call an oracle function with array as parameter via hibernate

So i hava an oracle functiion like: function unbind (ids in id_table). It takes an array of ids to perform some updates on my database.
The question is how can I run my function in order to perform update operations?
What I've alreade tried:
1. Query query = getSession().createSQLQuery("call UNBIND(:ids)");
query.setParameter("ids", myIds);
query.executeUpdate();
but I got ora-06576 not a valid function or procedure name
Query query = getSession().createSQLQuery("execute UNBIND(:ids)");
query.setParameter("ids", myIds);
query.executeUpdate();
finish with ora-00900 invalid sql statement
Long [] myArray = movedIds.toArray(new Long[movedIds.size()]);
Boolean result = getSession().doReturningWork(new ReturningWork<Boolean>() {
#Override
public Boolean execute(Connection connection) throws SQLException {
CallableStatement callableStatement = connection.prepareCall("{ ? = call UNBIND(:ids)");
callableStatement.registerOutParameter(1, Types.INTEGER);
callableStatement.setArray(2, connection.createArrayOf("id_table", myArray));
callableStatement.execute();
return !(callableStatement.getInt(1) == 0);
}
});
finishes with java.sql.sqlfeaturenotsupportedexception unsupported feature
The app conects to the database via jboss, so I suppose that could be the problem in p. 3?
SELECT
UNBIND( id_table (6271789) ) FROM DUAL
does not work because my function performs updates...
Anyway is there any other method to run a function that takes an array as a parameter directly from java code?
here is a simple example, does this help?
import java.sql.*;
public class Class1 {
public static void main(String[] args) throws SQLException {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Connection conn = null;
try {
conn = DriverManager.getConnection(
"jdbc:oracle:thin:#//localhost/orcl","scott","tiger");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String query = "{ ? = call test_func(?) }";
CallableStatement cs = null;
try {
cs = conn.prepareCall(query);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int inVal = 0;
cs.setInt(2, inVal);
cs.registerOutParameter(1, oracle.jdbc.OracleTypes.NUMBER);
cs.executeUpdate();
int res = cs.getInt(1);
System.out.println("result is " + res);
}
}

Getting ambiguous result using JDBC Metadata API for Hive

I am trying to get Table names for hive using DatabaseMetaData in a similar way like RDBMS.
Sample code:
try (Connection con = getJdbcConnection(connectionUri, driverName, username, password);) {
DatabaseMetaData metadata = con.getMetaData();
ResultSet rs = metadata.getTables(null, null, tableName, null);
while (rs.next()) {
System.out.println(rs.getString(3));
}
} catch (SQLException e) {
}
private static void registerDriver(String driverName) {
try {
Class.forName(driverName);
} catch (ClassNotFoundException e) {
LOG.error("No class found for " + driverName + ". Details: " + e);
}
}
private static Connection getJdbcConnection(String connectionUri, String driverName, String username,
String password) throws SQLException{
registerDriver(driverName);
return DriverManager.getConnection(connectionUri, username,password);
}
There is no table in a particular database. Using different different table names, I am getting different output.
For example:
I put table name emp, there are 3 records with name emp
I put table name employee, there are 5 records with name employee
I put table name emp12, it is returning no records (which is expected)
Am I doing something wrong?
Shouldn't I use DatabaseMetaData for checking table existence?
I need to pass schema name in getTables method
Signature:
ResultSet getTables(String catalog,
String schemaPattern,
String tableNamePattern,
String[] types)
throws SQLException
I passed following agruments:
catalog = null;
schemaPattern = Hive schema Name
tableNamePattern = Hive Table Name
types = new String[] { "TABLE" }
Sample code:
try (Connection con = getJdbcConnection(connectionUri, driverName, username, password);) {
DatabaseMetaData metadata = con.getMetaData();
ResultSet rs = metadata.getTables(null, schemaName, tableName, new String[] { "TABLE" });
while (rs.next()) {
String tName = rs.getString("TABLE_NAME");
if (tName != null && tName.equals(tableName)) {
LOG.info("Table [" + tableName + "] is present in the Database.");
return true;
}
}
rs.close();
LOG.info("Table [" + tableName + "] is not present in the Database.");
return false;
} catch (SQLException e) {
LOG.error("Not able to get Table Metadata . Caused By: " + e);
}

Hive over Tez via Hive JDBC - Error

I am using Hortonworks Hadoop HDP-2.3.2.0-2950
Hive over Tez engine
Below 2 queries are from Java code.
select * from ascii -- works well
select count(*) from ascii or select count(1) from ascii -- fails with error out
My code:
package com.hadoop.hive;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
*
* #author hdpadmin
*
*/
public class HiveReadJDBCMain {
private static String driverName = "org.apache.hive.jdbc.HiveDriver";
/**
* #param args
* #throws SQLException
*/
public static void main(String[] args) throws SQLException {
Connection con = null;
PreparedStatement pst = null;
ResultSet res = null;
try {
// Load Hive Driver Clazz
Class.forName(driverName);
// No username and password required.(running in a local machine)
con = DriverManager.getConnection("jdbc:hive2://localhost:10000/labs");
//Connection con = DriverManager.getConnection("jdbc:hive2://localhost:10000/labs", "<Username>", "<Password>");
String tableName = "ascii";
// select * query
String sql = "select * from " + tableName;
System.out.println("Select Query Running: " + sql);
pst = con.prepareStatement(sql);
res = pst.executeQuery();
while (res.next()) {
System.out.println(String.valueOf(res.getInt(1)) + "\t" + res.getString(2));
}
pst.close();
res.close();
// regular hive query
sql = "select count(*) from " + tableName;
System.out.println("Count Query Running: " + sql);
pst = con.prepareStatement(sql);
res = pst.executeQuery();
while (res.next()) {
System.out.println(res.getString(1));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.exit(1);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
} finally {
res.close();
pst.close();
con.close();
}
}
}
Error
java.sql.SQLException: Error while processing statement: FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.tez.TezTask
at org.apache.hive.jdbc.HiveStatement.execute(HiveStatement.java:282)
at org.apache.hive.jdbc.HiveStatement.executeQuery(HiveStatement.java:378)
at org.apache.hive.jdbc.HivePreparedStatement.executeQuery(HivePreparedStatement.java:109)
at com.hadoop.hive.HiveReadJDBCMain.main(HiveReadJDBCMain.java:48)
Yes i have fixed by passing the below connection objects with my user name
Thanks.... :)
con = DriverManager.getConnection("jdbc:hive2://localhost:10000/labs", "hdpadmin","");
i also fixed by passing username in connection string . Thanks :)
In case your using the AWS Hive JDBC to talk with a default EMR cluster the following setup in Intellij worked for me
The trick was using user hadoop

Doesn't match table_names jdbc program showing result and sql showing result

My jdbc program code
package table;
import java.sql.*;
public class sdfjksjk {
static final String JDBC_DRIVER = "oracle.jdbc.driver.OracleDriver";
static final String DB_URL = "jdbc:oracle:thin:#192.168.1.12:1521:aftdb";
static final String USER = "system";
static final String PASS = "manager";
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(DB_URL,USER,PASS);
System.out.println("Creating statement...");
stmt = conn.createStatement();
String sql;
DatabaseMetaData md = conn.getMetaData();
ResultSet rs = md.
getTables(null, "SYSTEM", "%", null);
while (rs.next())
{
System.out.println(rs.getString(3));
}
rs.close();
stmt.close();
conn.close();
}catch(SQLException se){
se.printStackTrace();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(stmt!=null)
stmt.close();
}catch(SQLException se2){
}
try{
if(conn!=null)
conn.close();
}catch(SQLException se){
se.printStackTrace();
}
}
}
}
this code showing 231 table name,but in my sql developer select table_name from user_tables it showing 207 table names. What is the wrong in my program?
The last parameter of md.getTables is a list of table types.
You supply the value null which lists all table types ("TABLE", "VIEW" and possibly other types).
In sql developer you are just seeing regular tables (not views).
Edit:
Make the call like this to just get regular tables:
String regularTables[] = new String[] {"TABLE"};
ResultSet rs = md.
getTables(null, "SYSTEM", "%", regularTables);

Resources