I'm a newbie in Java and I'm trying to find a way to retrieve a key from Hashtable. The code below was written to retrieve values from in a database and insert in Hashtable in key/value pair format using a stored procedure.
private Hashtable loadRspCodeMappingFromDB(String node_name)
throws SQLException
{
//TO DO:
// Take a look at the SDK user guide -> Programming conventions -> Database access using JDBC.
// Use the stored procedure you've created to fill a Hashtable to return.
// Two events have been created in events.er for your use:
// RspCodeMappingLoaded, and
// ErrorReadingRspCodeMapping
Hashtable resp_mapping_table = new Hashtable();
Connection cn = null;
CallableStatement stmt = null;
ResultSet rs = null;
try
{
cn = JdbcManager.getDefaultConnection();
stmt = cn.prepareCall("{call samplenid_get_rsp_map(?)}");
stmt.setString(1, node_name);
rs = stmt.executeQuery();
while(rs.next()){
tm_rsp_code = rs.getString(1);
Interchange_rsp_code = rs.getString(2);
resp_mapping_table.put(tm_rsp_code, Interchange_rsp_code);
}
JdbcManager.commit(cn, stmt, rs);
}
finally
{
JdbcManager.cleanup(cn, stmt, rs);
}
return resp_mapping_table;
}
The second code block is written to retrieve the mapped key from a Hashtable and include in a transaction message, but unfornately I'm getting this error: "cannot convert from element type Object to Map.Entry.
public Action processMsgFromRemote(AIntegrationDriverEnvironment env,Iso8583Post msg)
throws XPostilion, SQLException
{
//TO DO:
// 1. Check if the message is a response message
// 2.1 Check the integration driver environment to discover the sink node name
// 2.2 If the rsp code mapping has not yet been loaded, load rsp code
// mapping from table now. Use the loadRspCodeMappingFromDB() method
// below.
// 3.1 Check if a mapping exists
// 3.2 If a mapping exists, set the value to transaction manager
// 4. Return the action with the message to Transaction Manager
Action action = new Action();
boolean check_msg_type = Iso8583Post.MsgType.isResponse(msg.getMsgType());
if(check_msg_type){
String node_name = env.getSinkNodeName();
if( rsp_map == null)
{
rsp_map = loadRspCodeMappingFromDB(node_name);
}
else{
String rsp_code_from_cache_loader = (String) rsp_map.get(tm_rsp_code);
String rsp_code_msg_from_interchange = msg.getField(Iso8583.Bit._039_RSP_CODE);
if(rsp_code_from_cache_loader.equals(rsp_code_msg_from_interchange)){
for(Map.Entry entry: rsp_map.entrySet()){
if(rsp_code_from_cache_loader.equals(entry.getValue())){
tm_rsp_code = (String) entry.getKey();
break;
}
}
}
}
}
action.putMsgToTranmgr(msg);
return action;
}
I would like to know what would be the solution to this error. How should I fix it ?
Related
So, I was using a datasource which was defined in Spring, which was working fine. Then I updated my project to take the datasource from the Weblogic server which the application is running on. This too, works fine for most calls to the database, except for one scenario - This scenario is involved sending a list of objects to the database, based on database types which are defined in Java by using Structs.
The full method is:
#Override
public List<String> saveAllocation(String originalId, List<Parcel> parcels) throws SQLException {
if(originalId == null || parcels == null) {
return null;
}
List<String> results = null;
String result = null;
String log = null;
OracleConnection oracleConnection = (OracleConnection)jdbcTemplate.getDataSource().getConnection();
try {
OracleCallableStatement cs = (OracleCallableStatement) oracleConnection.prepareCall("{ call PACKAGE.Update(?, ?, ?, ?) }");
Struct[] cpoList = new Struct[parcels.size()];
for(int i = 0; i < parcels.size(); i++) {
Object[] obj = new Object[] { parcels.get(i).getParcel_id(), parcels.get(i).getPublicID().toUpperCase() };
Struct struct = oracleConnection.createStruct("SCHEME_NAME.PARCEL_OBJ", obj);
cpoList[i] = struct;
}
Array array = oracleConnection.createARRAY("SCHEME_NAME.PARCEL_TAB", cpoList);
cs.setString(1, originalId);
cs.setArray(2, array);
cs.registerOutParameter(3, Types.VARCHAR);
cs.registerOutParameter(4, Types.VARCHAR);
cs.executeUpdate();
log = cs.getObject(3).toString();
result = cs.getObject(4).toString();
results = new ArrayList<>();
results.add(result);
results.add(log);
} catch(SQLException e) {
//Log exception
return results;
} catch(Exception e) {
//Log exception
return results;
} finally {
if (cs != null) {
cs.close();
}
}
return results;
}
}
The database objects are defined as:
PARCEL_OBJ
create or replace TYPE parcel_obj AS OBJECT
(PARCEL_ID VARCHAR2(11),
PUBLIC_ID VARCHAR2(20));
PARCEL_TAB
create or replace TYPE parcel_tab IS TABLE OF parcel_obj;
The application fails on the line
Array array = oracleConnection.createARRAY("SCHEME_NAME.PARCEL_TAB", cpoList);
The exception message is:
java.sql.SQLException: Fail to convert to internal representation: weblogic.jdbc.wrapper.Struct_oracle_sql_STRUCT#187>
My JNDI connection is defined in my application.properties like:
spring.datasource.jndi-name=jdbc/pio
Any help would be appreciated!
As the documentation mentions.
By default, data type objects for Array, Blob, Clob, NClob, Ref,
SQLXML, and Struct, plus ParameterMetaData and ResultSetMetaData
objects are wrapped with a WebLogic wrapper.
In some cases setting the wrapping parameter to false can improve significantly the performance and allows the application to use a native driver.
I don't see a problem disabling that option since it is causing the problem when calling objects like struct in the first place.
I have a problem with loading objects from a SQLite database.
First of all, this is my table definition:
CREATE TABLE MyTable (
rowid INTEGER PRIMARY KEY,
data BLOB
);
This is the simple class which I want to store and reload:
public class MyHashMap extends HashMap<String, Integer> {
private static final long serialVersionUID = 0L;
}
Then I'm filling the map with some data and store it with an SQL INSERT statement in the database. Everything works fine and if I execute a SELECT (with the sqlite3 command-line client) I will see the correct information.
Now I'm using the java.sql package to load the object:
String sql = "SELECT data FROM MyTable WHERE rowid = 1";
MyHashMap map = null;
try {
try (Statement stmt = db.createStatement()) {
try (ResultSet rs = stmt.executeQuery(sql)) {
if (rs.next()) {
map = rs.getObject("data", MyHashMap.class);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
There's no exception thrown but my map variable is null. I debugged the program and I can say that the getObject method is called as expected.
First, you definition of MyHashMap is incorrect
public class MyHashMap extends HashMap<Integer, String> {
private static final long serialVersionUID = 0L;
}
The main issue, though, is that SQL doesn't store Java objects; it merely stores rows of records, which consist of fields. You need to read these records one by one, and store them in your map. Roughly as follows:
MyHashMap map = new MyHashMap();
final String sql = "SELECT rowid, data FROM MyTable";
try (final Statement stmt = connection.createStatement;
final ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
map.put(rs.getInt(1), rs.getString(2));
}
}
Please note that there's a good chance that reading a Blob into a String will fail. Usually, JDBC drivers are clever enough to convert data types, but if you have raw binary data in your blob, you cannot read it into a string. You would need the getBlob method instead, and deal with the resulting object. But I can't tell from your code what you'll be storing in that blob.
Ok, I found a solution with the following method:
private Object getObjectFromBlob(ResultSet rs, String columnName)
throws ClassNotFoundException, IOException, SQLException {
InputStream binaryInput = rs.getBinaryStream(columnName);
if (binaryInput == null || binaryInput.available() == 0) {
return null;
}
ObjectInputStream in = new ObjectInputStream(binaryInput);
try {
return in.readObject();
} finally {
in.close();
}
}
I have the below class with 3 resultsets.
public class AllMetricsResultSet {
ResultSet top10Files;
ResultSet top10FilesForUsage;
ResultSet top10DataSet;
}
In another method, I have 3 different select statements(I've given only one select below, but there are 3) which assign result sets into the above.
public AllMetricsResultSet SPDataList (String alldata)
{
...........
String sSQL = "SELECT USERNAME, NUMBEROFFILES FROM FILE_INFO";
PreparedStatement stm = dbConnection.prepareStatement(sSQL);
if (stm.execute())
//TopTenantsForUsage = stm.getResultSet();
rs.top10Files = stm.getResultSet();
rs.top10FilesForUsage = stm.getResultSet();
rs.top10DataSet = stm.getResultSet()
Then finally from another method, I am calling the previous method as follows:
AllMetricsResultSet mrs = SPDataList(alldata);
while (mrs.top10Files.next())
(This while statement fails. I see that there are 10 rows returned. I tried mrs.top10Files.getFetchSize() (this also failed)
Any help would be greatly appreciated.
It's not a good practice to execute the queries in one method and read data from the result sets in a different method.
You want to finish your DB access as quick as possible and close the connection, in order to return the connection to the connection pool (relevant when you have multiple threads accessing the db) and release any db locks your statements may require.
Therefore the result set variables shouldn't br instance variables at all. You should create and consume them in the same method.
You could have, though, a separate method for each of your 3 queries, and each of them can return the data it fetched.
Instead try like this
public AllMetricsResultSet SPDataList (String alldata) {
String sSQL1 = "query1";
String sSQL2 = "query2";
String sSQL3 = "query3";
try {
PreparedStatement stm1 = dbConnection.prepareStatement(sSQL1);
PreparedStatement stm2 = dbConnection.prepareStatement(sSQL2);
PreparedStatement stm3 = dbConnection.prepareStatement(sSQL3);
if (stm1.execute())
top10Files = stm1.getResultSet();
if (stm2.execute())
top10FilesForUsage = stm2.getResultSet();
if (stm3.execute())
top10DataSet = stm3.getResultSet();
while (top10Files.next()) {
//get the resultset1 data
}
while (top10FilesForUsage.next()) {
//get the resultset2 data
}
while (top10DataSet.next()) {
//get the resultset3 data
}
// dont know why as you want to return the classType
//create an object of the class initialize it the the data you obtained
//and return it
}
catch(SQLException e)
{
e.printStackTrace();
}
finally {
//resultsetobject close
//statementObject close
//connection object close
}
}
I have code
public static String getData(String query) {
String output = "";
try {
String connectionUrl = "jdbc:sqlserver://localhost:1234;databaseName=123;user=123;password=123";
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
con = DriverManager.getConnection(connectionUrl);
String SQL = "select smth from tableName where smth";
stmt = con.createStatement();
rs = stmt.executeQuery(query);
while (rs.next()) {
output = (String) rs.getObject(1);
}
rs.close();
}
catch (Exception e) {
return "ERROR while retrieving data: " + e.getMessage();
}
return output;
}
It works if value is string. But if it integer? Or boolean? How to modify this method so it would be universal, no matter what type data I get I still return it as string?
First retreive the result in ResultSet rs,
then you can write the code like below.
You can check the instance of the object and than assign the value.
String str;
Object obj = (Object)rs.getObject(1);
if(obj instanceof String){
//do you work here for string like below
str=(String)obj;
}
else if (obj instanceof Integer){
//do your work for Integer
}
// same you can do for other types
in this line
output = (String) rs.getObject(1);
if string then use
output = rs.getString(1);
if int
output = rs.getInt(1);
click oracle for more info
You can't accurately do that without using ResultSetMetaData class to get the column type.
Get the column data according to the type of the column.
You are getting the value from the resultset presuming that it is always a String and trying to typecast the Object instance. You should make use of the retrieve methods based on the type. Most of the cases, we will be knowing the datatype of the column values from which we retried the data. You can write the program based on the column's type. that's why ResultSet API has a method for each datatype.
For String
rs.getString(1);
For Int
rs.getInt(1)
Please read the documentation of ResultSet
while (rs.next())
{
String[] data;
data = new String[100];
data[i] = rs.getString("smth");
i = i + 1;
}
Try this you got your data in array.. use array instead of object.
what about toString()?
while (rs.next()) {
output = rs.getObject(1).toString();
}
I am pretty new to Hibernate / Java (JSF 2.0) and I am attempting to call a custom query and read the results into an object that I have created Logins. Logins has two setter functions, setLoginDate(Date date) and setUserId(Integer userId) my function looks like so, The issue I am having is how to transform the result set and read in the appropriate values into a temp loginList
public List<Logins> getUserLogins() {
Session session = getSessionFactory().openSession();
List<Logins> loginList = null;
Login temp = null;
try {
String SQL_QUERY = "SELECT login_date, user_id FROM user_logins";
Query query = session.createSQLQuery(SQL_QUERY);
List results = query.list();
for(ListIterator iter = results.listIterator(); iter.hasNext(); ) {
** THIS IS THE PART I AM NOT CLEAR ON ***
temp.setLoginDate(resutls.get(0));
temp.setUserId(results.get(1));
loginList.add(temp);
temp = null;
*****************************************
return loginList;
}
} catch(HibernateException e) {
throw new PersistanceDaoException(e);
} finally {
session.close();
}
}
missing part:
Object[] row = (Object[]) iter.next();
temp = new Login();
temp.setLoginDate(row[0]);
temp.setUserId(row[1]);
you may need to cast row[i] to your target object for example if login date is a date object: temp.setLoginDate((Date) row[0]);
for a better solution, try to use ResultTransformer
you can find more about ResultTransformer in Hibernate Docs.