converting resultset to multidimensional string array - java

I am trying to convert ResultSet to String[][] in Java webservice. It sounds very stupid to convert the Resultset to Strin[][]. The reason I am trying to do this is because Java webservice is called from .Net and it doesnt understand the ResultSet. I hoped it would had accepted the ResultSet as a DataTable but it didnt work out.
One of my problems is that the server I am trying to test my Java webservice is terrible and I cannot work very efficiently, so I cannot test everything.
this is my java webservice. I am trying to convert it to String[][] but it returns null. I think I am doing something wrong when I try to fill the String[][].
Is it correct way to get the rowCount and columnCount of ResultSet? what am I doing wrong?
public String[][] getValues()
{
String[][] arr;
try {
Class.forName("net.sourceforge.jtds.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:jtds:sqlserver://localhost:1433/MLS_J", "sa", "12345");
java.sql.Statement stmt = conn.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
java.sql.ResultSet rslt = stmt.executeQuery("SELECT * FROM S_USERS");
// to get row count and column count
/////////////////////////////////////
int rowSize = 0;
try {
rslt.last();
rowSize = rslt.getRow();
rslt.beforeFirst();
}
catch(Exception ex) {
}
ResultSetMetaData rsmd = rslt.getMetaData();
int columnSize = rsmd.getColumnCount();
/////////////////////////////////////
arr = new String[rowSize][columnSize];
int i =0;
while(rslt.next() && i < rowSize)
{
for(int j=0;j<columnSize;j++){
arr[i][j] = rslt.getString(j);
}
i++;
}
rslt.close();
stmt.close();
conn.close();
return arr;
} catch (Exception e) {
return null;
}
}

it is your problem
java resultset starts from 1.. so change your getString method like this. And remain all codes fine.
while(rslt.next() && i < rowSize)
{
for(int j=0;j<columnSize;j++){
arr[i][j] = rslt.getString(j+1);
}
i++;
}

A simple way to get the row count is to use COUNT(*) for your case...
java.sql.ResultSet rslt = stmt.executeQuery("SELECT COUNT(*) FROM S_USERS");

Related

Is Passing a result set in java possible?

I'm trying to make a command where i can send different queries to a SQLite / Mysql DB and return the resultset to whatever function is calling. It needs to be able to process whether there is 2 columns or 15.
The below doesn't work - presumably because it closes the resultset / connection but I'm not sure how else to do it.
Thoughts?
public static ResultSet queryDB(String query) {
try {
Connection connection = DriverManager.getConnection("jdbc:sqlite:" + Settings.SQLITE_DB_PATH);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(query);
resultSet.close();
statement.close();
connection.close();
return resultSet;
} catch (SQLException ex) {
Logger.getLogger(SQLInterp.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
You basically have 3 choices:
Don't close the ResultSet, Statement, and Connection in the method, handing off responsibility for doing that back to the caller.
Not recommended, since it is error-prone, and breaks well-formed code structure paradigms.
Pass in an object with the logic that is needed for processing the data, as suggested by Jacob G..
E.g. use a Java 8+ Consumer:
public static void queryDB(String query, Consumer<ResultSet> processor) {
try (
Connection connection = DriverManager.getConnection("jdbc:sqlite:" + Settings.SQLITE_DB_PATH);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(query);
) {
processor.accept(resultSet);
} catch (SQLException ex) {
Logger.getLogger(SQLInterp.class.getName()).log(Level.SEVERE, null, ex);
}
}
Then call it like this:
SQLInterp.queryDB("SELECT * FROM foo", rs -> {
while (rs.next()) {
// process data here
}
});
Read all the data into memory in a generic data structure, e.g. List<Map<String, Object>>:
This of course assumes that query has good unique names for each column.
public static List<Map<String, Object>> queryDB2(String query) {
try (
Connection connection = DriverManager.getConnection("jdbc:sqlite:" + Settings.SQLITE_DB_PATH);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(query);
) {
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
String[] name = new String[columnCount];
for (int i = 0; i < columnCount; i++)
name[i] = metaData.getColumnLabel(i + 1);
List<Map<String, Object>> rows = new ArrayList<>();
while (resultSet.next()) {
Map<String, Object> row = new LinkedHashMap<>();
for (int i = 0; i < columnCount; i++)
row.put(name[i], resultSet.getObject(i + 1));
rows.add(row);
}
return rows;
} catch (SQLException ex) {
Logger.getLogger(SQLInterp.class.getName()).log(Level.SEVERE, null, ex);
}
}

Retrieve data from MySQL DB using java

In here i want to obtain data from the MySQL DB & run the play method.but it execute at once.i wanted to get row one information pass that in to the ply method & get the second row information & pass it to the play method so on.
please help me to resolve this.
thank u in advance.
public class Player {
static Play PL = new Play();
public static void main(String[] args) {
try {
Statement stmt = null;
// connect to database radio
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/radio", "root", "");
stmt=conn.createStatement();
String sql = "SELECT Link FROM split";
ResultSet rs = stmt.executeQuery(sql);
//STEP 5: Extract data from result set
while(rs.next()){
//Retrieve by column name
int numColumns = rs.getMetaData().getColumnCount();
for ( int i = 1 ; i <= numColumns ; i++ ) {
System.out.println(numColumns);
String SongLocation = rs.getString(i);
System.out.println(SongLocation);
PL.play(SongLocation);
System.out.println("playing song");
}
}
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
I think you are looping through columns by using
int numColumns = rs.getMetaData().getColumnCount();
for ( int i = 1 ; i <= numColumns ; i++ ) {
...
instead try using a while loop
while (rs.next()) {
...
and because you need the index, inlude a local variable int i, that you just increment after each while loop

How to Store MySQL query into Java array?

I've found suggestions online to store the queried data into an ArrayList and then to convert the ArrayList into an Array. Below is the code that I have and it appears that I'm not doing this correctly. The SQL syntax is correct (I tested in my MySQL). Any suggestions on how to correct my code would be helpful, thanks!
public static void dxNameExerciseID(){
//String dxName = name;
//String result = null;
try{
con = DriverManager.getConnection(url, user, password);
pst = con.prepareStatement("SELECT * FROM exercise,condition_exercise,diagnosis WHERE exercise.exercise_id = condition_exercise.exercise_id_fk AND condition_exercise.diagnosis_id_fk = diagnosis.diagnosis_id AND diagnosis.diagnosis_name = 'Adductor Strain';");
rs = pst.executeQuery();
ArrayList<String> list= new ArrayList<String>();
while (rs.next()) {
list.add(rs.getString("exercise_id"));
String[] result = new String[list.size()];
result = list.toArray(result);
for(int i =0; i<result.length; i++){
System.out.println(result[i]);
}
}
}catch(SQLException ex){
}finally {
try {
if (rs != null){
rs.close();
}
if (pst != null){
pst.close();
}
if (con != null){
con.close();
}
}catch(SQLException ex){
}
}
//return result;
}
This should work better. See how you first create your ArrayList of String by iterating over your ResultSet, and once your list is complete you can create the Array of Strings.
ArrayList<String> list= new ArrayList<String>();
while (rs.next()) {
list.add(rs.getString("exercise_id"));
}
String[] result = new String[list.size()];
result = list.toArray(result);
for(int i =0; i<result.length; i++){
System.out.println(result[i]);
}
BTW: your finally block is unsafe. If rs.close() fails you won't close your connection.
Poor code in every way. Catch blocks should never be empty. You close your resources incorrectly. If something goes wrong, how will you know? Pass the connection in, don't make the method responsible for getting it. Use PreparedStatement. This code should be thrown away so you can start again.
This should work - You were creating Array on each iteration which was the reason of your problem
while (rs.next()) {
list.add(rs.getString("exercise_id"));
}
String[] result = new String[list.size()];
result = list.toArray(result);
for(int i =0; i<result.length; i++){
System.out.println(result[i]);
}
Some of your code should be refactored
ArrayList<String> list= new ArrayList<String>();
while (rs.next()) {
list.add(rs.getString("exercise_id"));
}
String[] result = new String[list.size()];
result = list.toArray(result);
for(int i =0; i<result.length; i++){
System.out.println(result[i]);
}

Java ResultSet SQL with GUI

I'm having a strange problem with the below code, it works fine when its run without the if else statements, but displays no results in the jtable when if else is used. Is there something stupid I'm missing here?
try {
Class.forName(dbClass);
Connection con = DriverManager.getConnection (dbUrl,dbUsername, dbPassword);
Statement stmt = con.createStatement();
String userQuery = "SELECT p_id AS 'Patient ID', forename AS 'Forename', surname AS 'Surname', address AS 'Address' FROM Patient WHERE surname LIKE '%"+s+"%'";
ResultSet userResult = stmt.executeQuery(userQuery);
if(!userResult.next())
{
JOptionPane.showMessageDialog(null, "No Results.");
{
else{
ResultSetMetaData rsMetaData =userResult.getMetaData();
DefaultTableModel dtm = new DefaultTableModel();
int cols = rsMetaData.getColumnCount();
Vector colName = new Vector();
Vector dataRows = new Vector();
for (int i=1; i<cols; i++){
colName.addElement(rsMetaData.getColumnName(i));
}
dtm.setColumnIdentifiers(colName);
while(userResult.next()){
dataRows = new Vector();
for(int j = 1; j<cols; j++){
dataRows.addElement(userResult.getString(j));
}
dtm.addRow(dataRows);
}
searchTable.setModel(dtm);
con.close();
}
} //end try
catch(ClassNotFoundException e) {
JOptionPane.showMessageDialog(null, "Database Error.");
e.printStackTrace();
}
catch(SQLException e) {
JOptionPane.showMessageDialog(null, "Database Error.");
e.printStackTrace();
}
I'm using netbeans for the GUI.
Thanks
The connection object (con) should be closed outside if/else block.
Beside, the userResult.next() was called twice in the else statement block..
You may fix it by replacing while() by do while loop:
do {
dataRows = new Vector();
for (int j = 1; j < cols; j++) {
dataRows.addElement(userResult.getString(j));
}
dtm.addRow(dataRows);
}
while (userResult.next());
Please include finally to handle closing the connection and removing the other resources.

Updating a large Resultset with JDBC and MySQL

I am trying update a large set of rows (around 5M). I first came across the heap overflow issue of having so many rows fetched in a resultset. Since I don't want to raise my heap size on this machine I was wondering if there is an effective way of doing this.
I tried setting the setFetchSize(Integer.MIN_VALUE) but then when I call the update function I get this error:
Streaming result set com.mysql.jdbc.RowDataDynamic#2087c268 is still active. No statements may be issued when any streaming result sets are open and in use on a given connection. Ensure that you have called .close() on any active streaming result sets before attempting more queries.
If I call close() on the result set I cannot update it of course. Here is my code
public void getRows()
{
Statement stmt = null;
ResultSet rs = null;
int countSpecialChars = 0;
int upper = 0, lower = 0, digits =0;
String pass = null;
int id = 0;
char thisChar;
String query = "select id,pass from datatable";
try {
this.conn.setAutoCommit(false);
stmt = this.conn.createStatement();
stmt.setFetchSize(Integer.MIN_VALUE);
rs = stmt.executeQuery(query);
while (rs.next()) {
pass = rs.getString(2).trim();
id = rs.getInt(1);
for (int i=0; i<=pass.length()-1; i++)
{
thisChar= pass.charAt(i);
if (thisChar >= 65 && thisChar <= 90) {
upper++;
} else if (thisChar >= 97 && thisChar <= 122) {
lower++;
} else if( thisChar >= 48 && thisChar <= 57) {
digits++;
}
else
{countSpecialChars++;}
}
Entropy entropy = new Entropy();
double naiveEntropy = entropy.naiveEntropy(pass);
NumberFormat formatter = new DecimalFormat("#0.00");
this.updateRow(id, pass.length(), digits, upper, lower, countSpecialChars, Double.parseDouble(formatter.format(naiveEntropy)));
countSpecialChars = 0;
upper=digits=0;
lower = 0;
}
rs.close();
}
catch (SQLException e)
...
}
public void updateRow(int id, int length, int numbers, int upper,
int lower, int specialChars, double naiveEntropy )
{
PreparedStatement updatePassEntry = null;
String updateString = "update cwlCompatiblePassUnique " +
"set length = ?, numbers = ?, upper = ?, lower = ?, specialChars = ?, ShannonEntropy = ? where id = ?";
try {
this.conn.setAutoCommit(false);
updatePassEntry = this.conn.prepareStatement(updateString);
updatePassEntry.setInt(1, length);
...
updatePassEntry.setInt(7, id);
updatePassEntry.executeUpdate();
this.conn.commit();
}
catch (SQLException e)
...
}
Any ideas on what can be done?
Thanks
you call updateRow() method inside the rs.next() loop; which tries to make a SQL update on a SQL field (id) that is currently being processed inside your while (rs.next()) loop. this will raise the error you get. i suggest you write a method for pulling rs and storing them in java objects vector as a first step. this method will close the rs after exiting. then write another method to do both processing and update data on your cached vector objects .
something like this:
private void Vector<DataSet> getDataSet(){
Vector<DataSet> data=new Vector<DataSet>();
String query = "select id,pass from datatable";
try {
this.conn.setAutoCommit(false);
stmt = this.conn.createStatement();
stmt.setFetchSize(Integer.MIN_VALUE);
rs = stmt.executeQuery(query);
while (rs.next()) {
pass = rs.getString(2).trim();
id = rs.getInt(1);
data.addElement(new DataSet(id,pass));
}
}catch(Exception e){
// here close connection and rs
}
}
private void udpateData(Vector<dataSet> data){
//process data and update her
}
static class DataSet{
int id;
String pass;
//constructor here
}
Connection object should not hold multiple resultset object at a time.
After creation of ResultSet and Statement Objects, each has to close explicitly like,
resultSet.close()
statement.close()

Categories