Common java class for json communication from server to client - java

I'm currently working in migrating a project to java, keeping the data intact (database). Most data are taken via stored procedures(SP), and there's a hell lot of SP in the database.
So, while executing each SP, I have to write a class for that, which is building up a huge pile of classes.
Hence, is there any way to generalize the class, so that I could transform every SP results to this class, and then to client side(as json)?
Following scenarios are hidden n ma qn:
Dynamic number of fields.
Dynamic field names.
Type could be string
(could deal with that).
I have tried sending data as java.util.List, but that doesn't comes in a pretty format. Have to take data assuming indexes.
PS: I have searched for the same, but couldn't find any. And sorry if I'm asking for too much.

Yes, it should be possible to write such a generic class. Here is a small example class as a starting point for you. I use Firebird with the example database employee.fdb because there are already some stored procedures defined.
So to connect to the Firebird server, I use the Jaybird JDBC driver and include the jaybird-full-2.2.5.jar JAR file.
There are several different JSON libraries for JAVA. I use the JSR 353: Java API for JSON Processing - Reference Implementation here in streaming mode (like StaX for XML). So the second external JAR here is javax.json-1.0.4.jar.
My example works only for stored procedures returning result sets. For stored procedures with output parameters a CallableStatement should be used instead of a PreparedStatement.
First, a generic SQL statement is created for the specific stored procedure with its input parameters. To call the stored procedure, a PreparedStatemend is used. The parameters are set according to the individual parameter types. (Procedures createSql() and createStatement())
In procedure convertToJson() the method ResultSet.getMetaData() is used to get the result set's column information (how many columns, column name and column type).
The executeStoredProcedure() methods are public API methods to call.
The main() method connects to the èmployee.fdb database and calls three stored procedures: GET_EMP_PROJ, MAIL_LABEL and ORG_CHART.
package com.genericsptojson;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;
import javax.json.Json;
import javax.json.stream.JsonGenerator;
import javax.json.stream.JsonGeneratorFactory;
public class GenericSpToJson {
private static final String DB_URL = "jdbc:firebirdsql:localhost/3050:/var/lib/firebird/2.5/data/employee.fdb";
private static final String DB_USER = "SYSDBA";
private static final String DB_PWD = "***";
private Connection con;
public GenericSpToJson(Connection con) {
this.con = con;
}
/**
* Creates the SQL to call the stored procedure.
*
* #param spName
* Name of stored procecdure to call
* #param paramCount
* number of input parameters
* #return SQL with placeholders for input parameters
*/
private String createSql(String spName, int paramCount) {
if(paramCount > 0) {
final StringBuilder params = new StringBuilder();
boolean isFirst = true;
for(int i = 0; i < paramCount; i++) {
if(isFirst) {
isFirst = false;
} else {
params.append(", ");
}
params.append('?');
}
return String.format("SELECT * FROM %s (%s)", spName, params.toString());
} else {
return String.format("SELECT * FROM %s", spName);
}
}
/**
* Creates a PreparedStatement to call the stored procedure. This works only
* for stored procedures creating result sets. Stored procedures with OUT
* parameters should be handled by a CallableStatement instead.
*
* #param spName
* The stored procedure name to be called.
* #param params
* The input parameters.
* #return A prepared statement. All parameters are set.
* #throws SQLException
*/
private PreparedStatement createStatement(String spName, Object... params) throws SQLException {
final PreparedStatement stmt = con.prepareStatement(createSql(spName, params.length));
for(int i = 0; i < params.length; i++) {
final Object param = params[i];
if(param instanceof String) {
stmt.setString(i + 1, (String) param);
} else if(param instanceof Integer) {
stmt.setInt(i + 1, ((Integer) param).intValue());
} else {
// Handle other param types ...
}
}
return stmt;
}
/**
* Converts the result set to JSON in streaming mode.
*
* #param spName
* The stored procedure name.
* #param rs
* The result set of the stored procedure call.
* #param out
* The output stream to write the JSON into.
* #throws SQLException
*/
private void convertToJson(String spName, ResultSet rs, OutputStream out) throws SQLException {
// Get the result set meta data to obtain column information on the fly.
final ResultSetMetaData metaData = rs.getMetaData();
// Create the JSON generator with pretty printing
final Map<String, Object> properties = new HashMap<String, Object>(1);
properties.put(JsonGenerator.PRETTY_PRINTING, true);
final JsonGeneratorFactory jsonGeneratorFactory = Json.createGeneratorFactory(properties);
final JsonGenerator generator = jsonGeneratorFactory.createGenerator(out);
generator.writeStartObject(); // root object
generator.write("storedProcedureName", spName);
generator.write("columnCount", metaData.getColumnCount());
generator.writeStartArray("records"); // records array
while(rs.next()) {
generator.writeStartObject(); // record object
// Each record object contains one field for every column.
// The field name is the columns name.
for(int col = 1; col <= metaData.getColumnCount(); col++) {
final String fieldName = metaData.getColumnName(col);
switch(metaData.getColumnType(col)) {
case Types.INTEGER:
final int intValue = rs.getInt(col);
if(rs.wasNull()) {
generator.writeNull(fieldName);
} else {
generator.write(fieldName, intValue);
}
break;
case Types.VARCHAR:
case Types.CHAR:
String stringValue = rs.getString(col);
if(rs.wasNull()) {
generator.writeNull(fieldName);
} else {
if(metaData.getColumnType(col) == Types.CHAR) {
stringValue = stringValue.trim();
}
generator.write(fieldName, stringValue);
}
break;
// Handle other types here
default:
System.out.println(String.format("Unhandled SQL type: %s", metaData.getColumnTypeName(col)));
}
}
generator.writeEnd(); // record object
}
generator.writeEnd(); // records array
generator.writeEnd(); // root object
generator.flush();
generator.close();
}
/**
* Executes the stored procedures with the given input parameters and creates
* JSON in streaming mode.
*
* #param spName
* The name of the stored procedure.
* #param out
* The output stream to write the generated JSON into.
* #param params
* The stored procedure's parameters.
*/
public void executeStoredProcedure(String spName, OutputStream out, Object... params) {
PreparedStatement stmt = null;
ResultSet rs = null;
try {
stmt = createStatement(spName, params);
rs = stmt.executeQuery();
convertToJson(spName, rs, out);
} catch (SQLException e) {
e.printStackTrace();
} finally {
// Cleaning up ...
if(stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
/**
* Convenience method to call the stored procedure and create a JSON string.
* This should only be called for short result sets. For longer result sets
* use {#link #executeStoredProcedure(String, OutputStream, Object...)} where
* it is not necessary to hold the entire JSON document in memory.
*
* #param spName
* The name of the stored procedure to call.
* #param params
* The stored procedure's parameters
* #return The stored procedure's call result as a JSON string.
* #throws UnsupportedEncodingException
*/
public String executeStoredProcedure(String spName, Object... params) throws UnsupportedEncodingException {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
executeStoredProcedure(spName, out, params);
return out.toString("UTF-8");
}
public static void main(String[] args) {
Connection con = null;
try {
Class.forName("org.firebirdsql.jdbc.FBDriver");
con = DriverManager.getConnection(DB_URL, DB_USER, DB_PWD);
final GenericSpToJson converter = new GenericSpToJson(con);
System.out.println("Executing stored procedure GET_EMP_PROJ (8):\n"
+ converter.executeStoredProcedure("GET_EMP_PROJ", 8));
System.out.println("\n\nExecuting stored procedure MAIL_LABEL (1015):\n"
+ converter.executeStoredProcedure("MAIL_LABEL", 1015));
System.out.println("\n\nExecuting stored procedure ORG_CHART:\n"
+ converter.executeStoredProcedure("ORG_CHART"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
The output is (shortened):
Executing stored procedure GET_EMP_PROJ (8):
{
"storedProcedureName":"GET_EMP_PROJ",
"columnCount":1,
"records":[
{
"PROJ_ID":"VBASE"
},
{
"PROJ_ID":"GUIDE"
},
{
"PROJ_ID":"MKTPR"
}
]
}
Executing stored procedure MAIL_LABEL (1015):
{
"storedProcedureName":"MAIL_LABEL",
"columnCount":6,
"records":[
{
"LINE1":"GeoTech Inc.",
"LINE2":"K.M. Neppelenbroek",
"LINE3":"P.0.Box 702",
"LINE4":"",
"LINE5":null,
"LINE6":"Netherlands 2514"
}
]
}
Executing stored procedure ORG_CHART:
{
"storedProcedureName":"ORG_CHART",
"columnCount":5,
"records":[
{
"HEAD_DEPT":null,
"DEPARTMENT":"Corporate Headquarters",
"MNGR_NAME":"Bender, Oliver H.",
"TITLE":"CEO",
"EMP_CNT":2
},
{
"HEAD_DEPT":"Corporate Headquarters",
"DEPARTMENT":"Sales and Marketing",
"MNGR_NAME":"MacDonald, Mary S.",
"TITLE":"VP",
"EMP_CNT":2
},
// ... SNIP ...
{
"HEAD_DEPT":"Corporate Headquarters",
"DEPARTMENT":"Finance",
"MNGR_NAME":"Steadman, Walter",
"TITLE":"CFO",
"EMP_CNT":2
}
]
}

Related

Is there a way to obtain the keys from a deleted record?

I'm using PostgreSQL to save a form in three tables, one for the name and id, another one for the fields to populate, and a third to store values for the fields.
private static final String REMOVE_FORM = "DELETE FROM forms WHERE name = ?";
private PreparedStatement removeFormQuery;
public boolean connect() throws SQLException{
this.connection = DriverManager.getConnection(URL);
this.removeFormQuery = this.connection.prepareStatement(REMOVE_FORM);
}
public void close() throws SQLException {
if(null != this.connection) {
this.connection.close();
}
if(null != this.removeFormQuery) {
this.removeFormQuery.close();
}
}
private void removeForm(String form) {
try {
removeFormQuery.setString(1, form);
int execute = removeFormQuery.executeUpdate();
System.out.println(execute);
ResultSet generatedKeys = removeFormQuery.getGeneratedKeys();
while (generatedKeys.next()) {
int anInt1 = generatedKeys.getInt("id");
removeFieldQuery.setInt(1, anInt1);
if (removeFieldQuery.execute())
System.out.println("remove field failed");
else
System.out.println("remove field success");
ResultSet generatedFieldsKeys = removeFieldQuery.getGeneratedKeys();
while (generatedFieldsKeys.next()) {
int anInt = generatedFieldsKeys.getInt("id");
removeListItemQuery.setInt(1, anInt);
if (removeListItemQuery.execute())
System.out.println("remove listItem failed");
else
System.out.println("remove listItem success");
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
The code doesn't generate keys after the remove query is executed, am I missing something?
While you haven't told us what queries you are running, if they are deletes then you wouldn't expect any generated keys.
From the Javadoc for Statement.getGeneratedKeys():
* Retrieves any auto-generated keys created as a result of executing this
* Statement object. If this Statement object did
* not generate any keys, an empty ResultSet
* object is returned.
Keys may be auto generated when you insert into a table, creating a new row which needs a primary key, but when you delete a row no key generation occurs.

Pulling data from json inside mysql to java

So I have a claim script that I'm trying to put together, that claims the product after purchase. The program is built inside of Java. The problem I'm running into is that there is a custom field they input on their purchase, and the store itself inserts it into a JSON format. So I need to execute a query that pulls the custom field into the WHERE statement, like so :
public class StoreClaim implements Runnable {
public static final String HOST = "104.161.43.58"; // website ip address
public static final String USER = "eseezjte_forum";
public static final String PASS = "Fishsticks123";
public static final String DATABASE = "eseezjte_forum";
private Player player;
private Connection conn;
private Statement stmt;
public StoreClaim(Player player) {
this.player = player;
}
public void run() {
try {
if (!connect(HOST, DATABASE, USER, PASS)) {
return;
}
String name = player.getUsername().replace("_", " ");
ResultSet connect = executeQuery("SELECT ps_claimed, ps_item_id, ps_custom_fields->$.1 AS claimed FROM nexus_purchases WHERE ps_custom_fields->$.1 = '"+name+"' AND ps_claimed='0'");
while (connect.next()) {
player.sm("WORKING!");
return;
}
destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
*
* #param host the host ip address or url
* #param database the name of the database
* #param user the user attached to the database
* #param pass the users password
* #return true if connected
*/
public boolean connect(String host, String database, String user, String pass) {
try {
this.conn = DriverManager.getConnection("jdbc:mysql://"+host+":3306/"+database, user, pass);
return true;
} catch (SQLException e) {
System.out.println("Failing connecting to database!");
return false;
}
}
/**
* Disconnects from the MySQL server and destroy the connection
* and statement instances
*/
public void destroy() {
try {
conn.close();
conn = null;
if (stmt != null) {
stmt.close();
stmt = null;
}
} catch(Exception e) {
e.printStackTrace();
}
}
/**
* Executes an update query on the database
* #param query
* #see {#link Statement#executeUpdate}
*/
public int executeUpdate(String query) {
try {
this.stmt = this.conn.createStatement(1005, 1008);
int results = stmt.executeUpdate(query);
return results;
} catch (SQLException ex) {
ex.printStackTrace();
}
return -1;
}
/**
* Executres a query on the database
* #param query
* #see {#link Statement#executeQuery(String)}
* #return the results, never null
*/
public ResultSet executeQuery(String query) {
try {
this.stmt = this.conn.createStatement(1005, 1008);
ResultSet results = stmt.executeQuery(query);
return results;
} catch (SQLException ex) {
ex.printStackTrace();
}
return null;
}
So i need to insert into this Result Set the JSON I'm trying to pull from.
This is what I'm trying to pull from the database and insert as the name to verify which user bought the product to claim.
I get the error :
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '>$.1 AS claimed FROM nexus_purchases WHERE ps_custom_fields->$.1 = 'quantum' ...' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1052)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3609)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3541)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2618)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2568)
at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1557)
at quantum.site.StoreClaim.executeQuery(StoreClaim.java:139)
at quantum.site.StoreClaim.run(StoreClaim.java:45)
at java.lang.Thread.run(Thread.java:748)
java.lang.NullPointerException
at quantum.site.StoreClaim.run(StoreClaim.java:46)
at java.lang.Thread.run(Thread.java:748)
which points to :
ResultSet connect = executeQuery("SELECT ps_claimed, ps_item_id, ps_custom_fields->$.1 AS claimed FROM nexus_purchases WHERE ps_custom_fields->$.1 = '"+name+"' AND ps_claimed='0'");
I need the execute to check the databse, find a row in which the name == the custom field "1": variable, and where claimed == 0, and I will need to pull the ps_item_id from that row to execute inside another file. How do i properly access the array and check if the player name is == to the "1": variable?
After trying multiple different ways, I found through JSON object how to parse the data. I had to initiate a first ResultSet, and than from that result set, pull the custom_field and than pull that into a JSON Object, parse the "1" to a string, and than use another ResultSet with that string to get that row
String name = player.getUsername().replace("_", " ");
ResultSet connect = executeQuery("SELECT * FROM nexus_purchases WHERE ps_claimed='0'");
while (connect.next()) {
String str = connect.getString("ps_custom_fields");
JSONObject obj = new JSONObject(str);
String n = obj.getString("1");
ResultSet check = executeQuery("SELECT * FROM nexus_purchases WHERE '"+n+"' = '"+name+"' AND ps_claimed='0'");
while (check.next()) {
player.sm("WORKING!");
return;
}
}

Implementation of ODCITableDescribe in a Java Stored Procedure

The current question is the second part of this ODCI related question.
I have implemented a collection type in Oracle SQL which is practically defined as a type and a table of that type.
CREATE TYPE row_type AS OBJECT
(
C1 VARCHAR2(50),
C2 VARCHAR2(50),
C3 VARCHAR2(50)
);
/
CREATE TYPE row_type_set AS TABLE OF row_type;
Also, I have defined an ODCI type with its implementation as a Java Stored Procedure within database:
SQL:
CREATE OR REPLACE TYPE ODCIImpl AS OBJECT (
key INTEGER,
STATIC FUNCTION ODCITableStart(sctx OUT ODCIImpl, cur SYS_REFCURSOR)
RETURN NUMBER
AS LANGUAGE JAVA
NAME 'ODCIImpl.ODCITableStart(oracle.sql.STRUCT[], java.sql.ResultSet) return java.math.BigDecimal',
MEMBER FUNCTION ODCITableFetch(self IN OUT ODCIImpl, nrows IN NUMBER,
outSet OUT row_type_set) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'ODCIImpl.ODCITableFetch(java.math.BigDecimal, oracle.sql.ARRAY[]) return java.math.BigDecimal',
MEMBER FUNCTION ODCITableClose(self IN ODCIImpl) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'ODCIImpl.ODCITableClose() return java.math.BigDecimal'
);
/
Java Stored Procedure:
import java.io.*;
import java.util.*;
import oracle.sql.*;
import java.sql.*;
import java.math.BigDecimal;
import oracle.CartridgeServices.*;
// stored context type
public class StoredCtx
{
ResultSet rset;
public StoredCtx(ResultSet rs) { rset=rs; }
}
// implementation type
public class ODCIImpl implements SQLData
{
private BigDecimal key;
final static BigDecimal SUCCESS = new BigDecimal(0);
final static BigDecimal ERROR = new BigDecimal(1);
final static int MAX_COLUMNS = 3;
// Implement SQLData interface.
String sql_type;
public String getSQLTypeName() throws SQLException
{
return sql_type;
}
public void readSQL(SQLInput stream, String typeName) throws SQLException
{
sql_type = typeName;
key = stream.readBigDecimal();
}
public void writeSQL(SQLOutput stream) throws SQLException
{
stream.writeBigDecimal(key);
}
// type methods implementing ODCITable interface
static public BigDecimal ODCITableStart(STRUCT[] sctx,ResultSet rset)
throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
// create a stored context and store the result set in it
StoredCtx ctx=new StoredCtx(rset);
// register stored context with cartridge services
int key;
try {
key = ContextManager.setContext(ctx);
} catch (CountException ce) {
return ERROR;
}
// create a ODCIImpl instance and store the key in it
Object[] impAttr = new Object[1];
impAttr[0] = new BigDecimal(key);
StructDescriptor sd = new StructDescriptor("ODCIIMPL",conn);
sctx[0] = new STRUCT(sd,conn,impAttr);
return SUCCESS;
}
public BigDecimal ODCITableFetch(BigDecimal nrows, ARRAY[] outSet)
throws SQLException
{
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
// retrieve stored context using the key
StoredCtx ctx;
try {
ctx=(StoredCtx)ContextManager.getContext(key.intValue());
} catch (InvalidKeyException ik ) {
return ERROR;
}
// get the nrows parameter, but return up to 10 rows
int nrowsval = nrows.intValue();
// create a vector for the fetched rows
Vector v = new Vector(nrowsval);
int i=0;
StructDescriptor outDesc =
StructDescriptor.createDescriptor("ROW_TYPE", conn);
Object[] out_attr = new Object[MAX_COLUMNS];
ResultSetMetaData rsmd = ctx.rset.getMetaData();
int columnsNumber = rsmd.getColumnCount();
while(nrowsval>0 && ctx.rset.next()){
for(int j = 0; j < columnsNumber; j++) {
if(j == MAX_COLUMNS)
break;
out_attr[j] = (Object)ctx.rset.getString(j+1);
}
v.add((Object)new STRUCT(outDesc, conn, out_attr));
i+=1;
nrowsval-=1;
}
// return if no rows found
if(i==0) return SUCCESS;
// create the output ARRAY using the vector
Object out_arr[] = v.toArray();
ArrayDescriptor ad = new ArrayDescriptor("ROW_TYPE_SET",conn);
outSet[0] = new ARRAY(ad,conn,out_arr);
return SUCCESS;
}
public BigDecimal ODCITableClose() throws SQLException {
// retrieve stored context using the key, and remove from ContextManager
StoredCtx ctx;
try {
ctx=(StoredCtx)ContextManager.clearContext(key.intValue());
} catch (InvalidKeyException ik ) {
return ERROR;
}
// close the result set
Statement stmt = ctx.rset.getStatement();
ctx.rset.close();
if(stmt!=null) stmt.close();
return SUCCESS;
}
}
After all of this, I've implemented a pipelined function that can be called using a cursor.
CREATE OR REPLACE FUNCTION Exec_Remote_SQL_JSP(p SYS_REFCURSOR) RETURN row_type_set
PIPELINED USING ODCIImpl;
/
My question now is how can we implement an ODCITableDescribe method in a Java Stored Procedure in order to output any data type in the emulated table? First of all, is it possible at all? I didn't seem to find any relevant information about this on the Oracle documentation from here and here
If it is possible to do so, it is self-explainable that we do not need anymore the collection types mentioned at the beginning. The emulated table should have the same size and data types as the table from which we intend to select information.

error in get connection method [duplicate]

My error:
java.sql.SQLException: Listener refused the connection with the following error:
ORA-12516, TNS:listener could not find available handler with matching protocol
stack
The Connection descriptor used by the client was:
//10.2.5.21:9001/XE
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java
:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java
:261)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:387)
at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:
414)
at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:165)
at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtensio
n.java:35)
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:801)
at oracle.jdbc.pool.OracleDataSource.getPhysicalConnection(OracleDataSou
rce.java:297)
at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java
:221)
at oracle.jdbc.pool.OracleDataSource.getConnection(OracleDataSource.java
:165)
at utilityService.DB_util.setOracleConnectionActive(DB_util.java:99)
at utilityService.DB_util.getRecPreparedAuthentication(DB_util.java:124)
My common db connection class:
package utilityService;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import oracle.jdbc.pool.OracleDataSource;
public class DB_util {
String propValue = "";
ResultSet rec = null;
Statement stm = null;
PreparedStatement pre_stm = null;
CallableStatement call_stm = null;
Connection conn1 = null;
/**
* Constructure to get oracle connection
*/
public DB_util() {
Util util=new Util();
propValue=util.getFilePathToSave();
//propValue = Util.propValue;// get oracle connection
setOracleConnectionActive();
}
/**
* Close all oracle connections and result sets.
*/
public void setOracleConnectionClose() {
try {
if (conn1 != null || !conn1.isClosed()) {
if (rec != null) {
rec.close();
rec = null;
}
if (stm != null) {
stm.close();
stm = null;
}
if (pre_stm != null) {
pre_stm.close();
pre_stm = null;
}
if (call_stm != null) {
call_stm.close();
call_stm = null;
}
conn1.commit();
conn1.close();
conn1 = null;
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* return a result set according to sql sent
*
* #param SQL
* #return
*/
public ResultSet getRec(String SQL) {
try {
setOracleConnectionActive();
stm = conn1.createStatement();
rec = stm.executeQuery(SQL);
return rec;
} catch (Exception ex) {
ex.printStackTrace();
return rec;
}
}
/**
* Activate oracle connection
*/
private void setOracleConnectionActive() {
try {
if (conn1 == null || conn1.isClosed()) {
OracleDataSource ods = new OracleDataSource();
if (propValue != null) {
ods.setURL(propValue);
}
conn1 = ods.getConnection();
System.out.println("DB connection CONNECTED......");
conn1.setAutoCommit(false);
}
} catch (Exception ex) {
//setOracleConnectionActive();
ex.printStackTrace();
System.out.println("DB connection FAILED......");
}
}
/**
* send prepared result set with user authenticate
*
* #param SQL
* #param strInputUserMobile
* #param strInputUserName
* #param strInputUserPassword
* #return
*/
public ResultSet getRecPreparedAuthentication(String SQL,
String strInputUserMobile, String strInputUserName,
String strInputUserPassword) {
try {
setOracleConnectionActive();
pre_stm = conn1.prepareStatement(SQL);
pre_stm.setString(1, strInputUserMobile);
pre_stm.setString(2, strInputUserName);
pre_stm.setString(3, strInputUserPassword);
rec = pre_stm.executeQuery();
return rec;
} catch (Exception ex) {
ex.printStackTrace();
return rec;
}
}
/**
* insert sql to db which is send as a sql
*
* #param SQL
* #return
*/
public int insertSQL(String SQL) {
int output = 0;
try {
setOracleConnectionActive();
stm = conn1.createStatement();
output = stm.executeUpdate(SQL);
conn1.commit();
output = 1;
} catch (Exception ex) {
try {
conn1.rollback();
output = 0;
} catch (SQLException e) {
e.printStackTrace();
output = 0;
}
ex.printStackTrace();
}
return output;
}
/**
* Send a callable statement according to sent sql
*
* #param SQL
* #return
*/
public CallableStatement callableStatementSQL(String SQL) {
int output = 0;
try {
setOracleConnectionActive();
call_stm = conn1.prepareCall(SQL);
} catch (Exception ex) {
try {
conn1.rollback();
output = 0;
} catch (SQLException e) {
e.printStackTrace();
output = 0;
}
ex.printStackTrace();
}
return call_stm;
}
}
Every transaction I refer this class and do my fetching & CRUD operations.
Is there any issue with my code?
You opened a lot of connections and that's the issue. I think in your code, you did not close the opened connection.
A database bounce could temporarily solve, but will re-appear when you do consecutive execution.
Also, it should be verified the number of concurrent connections to the database. If maximum DB processes parameter has been reached this is a common symptom.
Courtesy of this thread: https://community.oracle.com/thread/362226?tstart=-1
I fixed this problem with sql command line:
connect system/<password>
alter system set processes=300 scope=spfile;
alter system set sessions=300 scope=spfile;
Restart database.
For me the problem was not the number of connexions, but the "matching protocol" part. Changing the ojdbc version solved the problem.

how to pass a java object to oracle stored procedure with following details

I have my ORACLE table with structure as
desc extraction_log1
Name Null
Type
------------------------------ -------- ------------------------------------------------------------ ---------------------------------------------------------------------------------------------------- -----------------------------
ROW_NUM NOT NULL NUMBER
DATE_TIME TIMESTAMP(8)
USER_NAME VARCHAR2(32)
PLATFORM_NAME VARCHAR2(20)
R_OBJECT_ID VARCHAR2(16)
Then I created an object type in oracle as
create or replace type EXTRACTION_LOG_TYPE as object (
USER_NAME VARCHAR2(32),
R_OBJECT_ID VARCHAR2(16),
);
Then I created procedure in a package as
create or replace package body PAC_BEAN is
--The insert procedure will receive EXTRACTION_LOG_TYPE and put it into table EXTRACTION_LOG1.
procedure PRO_INSERT_LOG(ELT in EXTRACTION_LOG_TYPE) is
begin
insert into EXTRACTION_LOG1 ( R_OBJECT_ID, USER_NAME)
values (ELT.R_OBJECT_ID, ELT.USER_NAME);
commit;
exception
when others then
rollback;
end PRO_INSERT_LOG;
end PAC_BEAN;
and coming to my java side I have declared a bean with
public class ExtractionLogType {
//Name declared in Oracle
public static final String ORACLE_OBJECT_NAME = "EXTRACTION_LOG_TYPE";
//The attributes
private String R_OBJECT_ID;
private String USER_NAME;
//setters and getters
public String getR_OBJECT_ID() {
return R_OBJECT_ID;
}
public void setR_OBJECT_ID(String rOBJECTID) {
R_OBJECT_ID = rOBJECTID;
}
public String getUSER_NAME() {
return USER_NAME;
}
public void setUSER_NAME(String uSERNAME) {
USER_NAME = uSERNAME;
}
}
in my Class containing main
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBLogger{
String dbUrl;
Connection con;
//constructor for creation of connection object
as and when an object of DBLogger is instantiated
public DBLogger(){
dbUrl = "jdbc:oracle:thin#my url";
try {
//load Oracle Driver class
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.err.println("Oracle driver class not found");
}
try {
//instantiate connection object
con = DriverManager.getConnectio (dbUrl,"userId","pwd");
} catch (SQLException e) {
e.printStackTrace();
System.err.println("Connection object to oracle cant be established");
}
}
public static void main(String args[]){
try{
DBLogger db=new DBLogger();
CallableStatement cs = null;
ExtractionLogType elt=new ExtractionLogType();
elt.setR_OBJECT_ID("79479479A900");
elt.setUSER_NAME("Jeevan");
cs = db.con.prepareCall("{call PAC_BEAN.PRO_INSERT_LOG(?)}");
/*
* *code to insert the above object into our Database
*
*/
cs.execute();
System.out.println("insert procedure executed successfully");
db.con.close();
} //end try
catch (SQLException e) {
e.printStackTrace(); }
catch(Exception e) { e.printStackTrace();
}
}
}
I can't figure out the code to make the object get inserted into my database.
can anyone suggest me regarding this.
Thank You.
You will have to define a array descriptor for your database type, this example could help you:
final ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor("EXTRACTION_LOG_TYPE", con);
// create an Object Array
Object[] data = new Object[2];
// set the values in order of appearance
data[0] = elt.getUSER_NAME();
data[1] = elt.getR_OBJECT_ID();
// Create the Array
ARRAY array = new ARRAY(descriptor, con, data);
// put it on your statement
cs.setArray(1, array);
// execute ...
This is terrible idea to create any objects in SYSTEM schema of the database. It is the same bad idea to connect your app straight to this scheme either.
This looks like a lack of privileges disallowing you to get what you want. Create new schema, dedicated user of this schema and then create all required object using this new user (it will be the owner of your objects). This way you can avoid "issue" where you cannot access something you supposed to have an access to.

Categories