I have following codes:
-------class------------
private class SystemHealthAlert implements Work {
List<MonitorAlertInstance> systemHealthAlertList;
private String queryString;
// private java.util.Date startDate;
// private java.util.Date endDate;
#Override
public void execute(Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement(queryString);
int index = 1;
ResultSet rs = ps.executeQuery();
int columnCount = rs.getMetaData().getColumnCount();
while(rs.next())
{
//String[] row = new String[columnCount];
//results.set(index, element);
//for (int i=0; i <columnCount ; i++)
// {
// row[i] = rs.getString(i + 1);
// }
systemHealthAlertList.add(row);
}
rs.close();
ps.close();
}
}
---------Method-----------
public List<MonitorAlertInstance> getSystemHealthAlert(Long selectedSensorId) {
List<MonitorAlertInstance> systemHealthAlertList;
try {
// Add SELECT with a nested select to get the 1st row
String queryString = "select min(MONITOR_ALERT_INSTANCE_ID) as MONITOR_ALERT_INSTANCE_ID, description" +
" from ems.monitor_alert_instance " +
" where description in (select description from monitor_alert_instance" +
" where co_mod_asset_id = " + selectedSensorId +
" )" +
" group by description";
SystemHealthAlert work = new SystemHealthAlert();
// work.coModAssetId = coModAssetId;
work.queryString = queryString;
getSession().doWork(work);
systemHealthAlertList = work.systemHealthAlertList;
} catch (RuntimeException re) {
// log.error("getMostRecentObservationId() failed", re);
throw re;
}
//log.info("End");
return systemHealthAlertList;
}
My query returns three rows from DB. How can I return systemHealthAlertList from the class that will have all the three rows of the query.
In method execute, you should fill your List<MonitorAlertInstance> systemHealthAlertList with instances of MonitorAlertInstance. Create a new instance of MonitorAlertInstance inside the while loop where you retrieve the data:
//You don't need this line, remove it
//int columnCount = rs.getMetaData().getColumnCount();
while(rs.next()) {
//create a new instance of MonitorAlertInstance per ResultSet row
MonitorAlertInstance monitor = new MonitorAlertInstance();
//set the fields from the ResultSet in your MonitorAlertInstance fields
//since I don't know the fields of this class, I would use field1 and field2 as examples
monitor.setField1(rs.getInt(1));
monitor.setField2(rs.getString(2));
//and on...
systemHealthAlertList.add(monitor);
}
Apart from this problem, you should initialize your List<MonitorAlertInstance> systemHealthAlertList variable before use it:
systemHealthAlertList = new ArrayList<MonitorAlertInstance>();
while(rs.next()) {
//content from previous code...
}
Define a class/bean to hold the data from one given row. Loop through your rows, and create one instance of that class for each row you have. Add these instances to some List. Return the List of these 3 instances.
Related
I am running a query on ID column but I don't want it to be visible in my frame/pane. How can I achieve this? Shall I make another table, is there a function in sql/mysql which allows to hide columns? I tried to google it but havent found anything yet.
Here is the code:
public void tableChanged(TableModelEvent e) {
int row = e.getFirstRow();
int col = e.getColumn();
model = (MyTableModel) e.getSource();
String stulpPav = model.getColumnName(col);
Object data = model.getValueAt(row, col);
Object studId = model.getValueAt(row, 0);
System.out.println("tableChanded works");
try {
new ImportData(stulpPav, data, studId);
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
public class ImportData {
Connection connection = TableWithBottomLine.getConnection();
public ImportData(String a, Object b, Object c)
throws ClassNotFoundException, SQLException {
Statement stmt = null;
try {
String stulpPav = a;
String duom = b.toString();
String studId = c.toString();
System.out.println(duom);
connection.setAutoCommit(false);
stmt = connection.createStatement();
stmt.addBatch("update finance.fin set " + stulpPav + " = " + duom
+ " where ID = " + studId + ";");
stmt.executeBatch();
connection.commit();
} catch (BatchUpdateException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (stmt != null)
stmt.close();
connection.setAutoCommit(true);
System.out.println("Data was imported to database");
}
}
}
public class MyTableModel extends AbstractTableModel{
int rowCount;
Object data [][];
String columnNames [];
public MyTableModel() throws SQLException{
String query ="SELECT ID, tbl_Date as Date, Flat, Mobile, Food, Alcohol, Transport, Outdoor, Pauls_stuff, Income, Stuff FROM finance.fin";
ResultSet rs ;
Connection connection = TableWithBottomLine.getConnection();
Statement stmt = null;
stmt = connection.createStatement();
rs = stmt.executeQuery(query);
rs.last();
rowCount = rs.getRow();
data = new Object[rowCount][11];
rs = stmt.executeQuery(query);
for (int iEil = 0; iEil < rowCount; iEil++){
rs.next();
data[iEil][0] = rs.getInt("ID");
data[iEil][1] = rs.getDate("Date");
data[iEil][2] = rs.getFloat("Flat");
data[iEil][3] = rs.getFloat("Mobile");
data[iEil][4] = rs.getFloat("Food");
data[iEil][5] = rs.getFloat("Alcohol");
data[iEil][6] = rs.getFloat("Transport");
data[iEil][7] = rs.getFloat("Outdoor");
data[iEil][8] = rs.getFloat("Pauls_stuff");
data[iEil][9] = rs.getFloat("Income");
data[iEil][10] = rs.getFloat("Stuff");
}
String[] columnName = {"ID", "Date","Flat","Mobile"
,"Food","Alcohol","Transport", "Outdoor", "Pauls_stuff", "Income", "Stuff"};
columnNames = columnName;
}
This has solved my problem:
table.removeColumn(table.getColumnModel().getColumn(0));
I placed this in my class contructor. This lets remove the column from the view of the table but column 'ID' is still contained in the TableModel. I found that many people looking for an option to exclude specific column (like autoincrement) from SELECT statement in sql / mysql but the language itself doesn't have that feature. So I hope this solution will help others as well.
Don't put ID in the select part of the query
String query ="SELECT tbl_Date as Date, Flat, Mobile, Food, Alcohol, Transport,
Outdoor, Pauls_stuff, Income, Stuff FROM finance.fin";
at the moment I'm working on a script that reads several values from different tables of one database. Every time I start a request, I have to open a statement and create a new resultset which leads to horrible, repetative code. What would be a good way of generalizing this and how can this be done?
Some elements from my code. At the moment there's just one statement and the closing has to be inserted. One of the primary reasons I ask this question.
public static void main(String[] args) throws Exception
{
Connection c = null;
Statement stmt = null;
try
{
//set up database connection
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:/nfs/home/mals/p/pu2002/workspace/Database2");
c.setAutoCommit(false);
stmt = c.createStatement();
//end
//get task id to work with
String Task_id = null;
if(args.length != 0) //if an argument was passed, Task_id will be the first element of the array args (arguments)
{
Task_id = args[0];
}
else if(args.length == 0) //if no arguments were passed, the highest number in the column id from tasks_task will be selected and set as Task_id
{
ResultSet TTask_id = stmt.executeQuery("SELECT max(id) FROM tasks_task");
int t_id = TTask_id.getInt(1);
Task_id = String.valueOf(t_id);
TTask_id.close();
}
//end
//get solution IDs from taks_ids
ArrayList<Integer> List_solIDs = new ArrayList<Integer>(); //create an empty array list
ResultSet SSolution_task_id = stmt.executeQuery("SELECT id FROM solutions_solution WHERE task_id ="+Task_id + " AND final = 1;"); //Sqlite3-Ausdruck SELECT..., Task IDs verändern pro Aufgabe - "SELECT * FROM solutions_solution where task_id ="+Task_id +";"
while (SSolution_task_id.next()) //loops through all elements of SSolution_task_id
{
List_solIDs.add(SSolution_task_id.getInt("id")); //adds all elements of the resultset SSolution_task_id to the list List_solIDs
}
SSolution_task_id.close();
//end
//get logs according to content type
int count = List_solIDs.size();
String log_javaBuilder = null;
List<String> log_JunitChecker = new ArrayList<String>();
for (int i = 0; i < count; i++)
{
boolean sol_id_valid = false;
String solID = String.valueOf(List_solIDs.get(i));
try
{
ResultSet AAttestation_sol_id = stmt.executeQuery("SELECT * FROM attestation_attestation WHERE solution_id =" +solID+";");
int Returned = AAttestation_sol_id.getInt("final_grade_id");
}
catch(Exception e)
{
sol_id_valid = true;
}
if(sol_id_valid ==true)
{
try
{
ResultSet CCresult_javaBuilder = stmt.executeQuery("SELECT log FROM checker_checkerresult WHERE solution_id = " +solID+ " AND content_type_id = 22;"); //"SELECT id FROM checker_checkerresult where solution_id = " +List_solIDs.get(i)+ ";"
log_javaBuilder = CCresult_javaBuilder.getString("log");
CCresult_javaBuilder.close();
ResultSet CCresult_Junit_checker = stmt.executeQuery("SELECT log FROM checker_checkerresult WHERE solution_id = " +solID+ " AND content_type_id = 24;");
while (CCresult_Junit_checker.next())
{
log_JunitChecker.add(CCresult_Junit_checker.getString("log"));
}
CCresult_Junit_checker.close();
}
catch (Exception e)
{
log_JunitChecker.add(null);
}
//end
All types of potential improvements will be welcome.
P.S.: Tried googling.
Seems you want to look at using some ORM layer e.g. http://hibernate.org/orm/
What you're looking for is probably a higher-level layer which
abstracts you from the underlying lower-level JDBC type of coding.
Better than writing generic method by yourself it is always better to use some framework, There are many JPA implementations out there which solve not only this issue but also takes care of multiple persistence layer boiler plate code. Start JPA from Here. You can also use Spring JDBC template as well to solve problem mentioned above Spring JDBC Documentation.
Now, if you really don't want any framework dependency and finish this code quite fast, You can define your own JDBCTemplate class which takes query and parameter map and return ResultSet. This class can handle open connection, query execution and closing connection etc.
What if you try to use generics on methods? this is a quick example, just for illustration, you must improve all this :)
resource: official docs
public static <T> List<T> getSingleValueList(ResultSet rs, Class<T> clazz, String colName) throws Exception {
ArrayList<T> list = new ArrayList<T>();
while (rs.next()) {//loops through all elements of generic list
list.add((T) rs.getObject(colName)); //adds all elements of the resultset rs to the list
}
rs.close();
return list;
}
public static <T> T getSingleValue(ResultSet rs, Class<T> clazz, String colName) throws Exception {
try {
if (rs.next()) {//loops through all elements of generic list
return (T) rs.getObject(colName);
} else {
throw new Exception("no value found.");
}
} finally {
rs.close();
}
}
public static void main(String[] args) throws Exception {
Connection c = null;
Statement stmt = null;
try {
//set up database connection
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:/nfs/home/mals/p/pu2002/workspace/Database2");
c.setAutoCommit(false);
stmt = c.createStatement();
//end
//get task id to work with
String Task_id = null;
if (args.length != 0) //if an argument was passed, Task_id will be the first element of the array args (arguments)
{
Task_id = args[0];
} else if (args.length == 0) //if no arguments were passed, the highest number in the column id from tasks_task will be selected and set as Task_id
{
ResultSet TTask_id = stmt.executeQuery("SELECT max(id) FROM tasks_task");
int t_id = TTask_id.getInt(1);
Task_id = String.valueOf(t_id);
TTask_id.close();
}
//end
//get solution IDs from taks_ids
ResultSet SSolution_task_id = stmt.executeQuery("SELECT id FROM solutions_solution WHERE task_id =" + Task_id + " AND final = 1;"); //Sqlite3-Ausdruck SELECT..., Task IDs verändern pro Aufgabe - "SELECT * FROM solutions_solution where task_id ="+Task_id +";"
List<Integer> List_solIDs = getSingleValueList(SSolution_task_id, Integer.class, "id"); //create an empty array list
//end
//get logs according to content type
int count = List_solIDs.size();
String log_javaBuilder = null;
List<String> log_JunitChecker = new ArrayList<String>();
List<String> tmplog_JunitChecker;
for (int i = 0; i < count; i++) {
boolean sol_id_valid = false;
String solID = String.valueOf(List_solIDs.get(i));
try {
ResultSet AAttestation_sol_id = stmt.executeQuery("SELECT * FROM attestation_attestation WHERE solution_id =" + solID + ";");
Integer Returned = getSingleValue(AAttestation_sol_id, Integer.class, "final_grade_id");
} catch (Exception e) {
sol_id_valid = true;
}
if (sol_id_valid == true) {
try {
ResultSet CCresult_javaBuilder = stmt.executeQuery("SELECT log FROM checker_checkerresult WHERE solution_id = " + solID + " AND content_type_id = 22;"); //"SELECT id FROM checker_checkerresult where solution_id = " +List_solIDs.get(i)+ ";"
log_javaBuilder = getSingleValue(CCresult_javaBuilder, String.class, "log");
ResultSet CCresult_Junit_checker = stmt.executeQuery("SELECT log FROM checker_checkerresult WHERE solution_id = " + solID + " AND content_type_id = 24;");
tmplog_JunitChecker = getSingleValueList(CCresult_Junit_checker, String.class, "log");
log_JunitChecker.addAll(tmplog_JunitChecker);
} catch (Exception e) {
log_JunitChecker.add(null);
}
//end
}
}
} catch (Exception eeee) {
//handle it
}
}
I hope I gave you a light.
Anyway, frameworks in almost all cases help a lot.
As mentioned in the header I cannot get my JTable to update with a new row unless I restart the program. When I restart, the new row is there and everything is as it should be. I have tried revalidating/repainting the panel and frame, I have tried the fire methods. I'm at a loss. Thanks in advance
ActionListener (in adminGUI class) for 'Add' button:
if(source.equals(add2)){
String c = itb.getText();
int a = main.getResults();
boolean matches = Pattern.matches("[A-Z][a-z]+", c);
if(matches == true){
main.addGenre(a, c);
}
String Method(in main class) to add a row to the database table:
public static void addGenre(int a, String b){
int rowsAdded;
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection connect =DriverManager.getConnection("jdbc:odbc:MovieDB");
Statement stmt = connect.createStatement();
String query = "INSERT INTO Genres (genre_id, genre_name)" + "VALUES(" + a + ", '" + b + "')";
rowsAdded = stmt.executeUpdate(query);
}catch(Exception exc){}
}
Method(also in main class) to increment the auto-increment-key column:
public static int getResults(){
int a = 0;
ResultSet ints = main.getResults("Select genre_id from Genres");
try {
while(ints.next()){
int d = ints.getInt("genre_id");
if(d>a){
a = d;
}
a++;
}
} catch (SQLException ex) {
Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
}
return a;
}
JTable details:
ResultSet rs1 = main.getResults("Select * from Genres");
JTable tab1 = new JTable(DbUtils.resultSetToTableModel(rs1));
DbUtils.resultSetToTableModel details :
public class DbUtils {
public static TableModel resultSetToTableModel(ResultSet rs) {
try {
ResultSetMetaData metaData = rs.getMetaData();
int numberOfColumns = metaData.getColumnCount();
Vector columnNames = new Vector();
// Get the column names
for (int column = 0; column < numberOfColumns; column++) {
columnNames.addElement(metaData.getColumnLabel(column + 1));
}
// Get all rows.
Vector rows = new Vector();
while (rs.next()) {
Vector newRow = new Vector();
for (int i = 1; i <= numberOfColumns; i++) {
newRow.addElement(rs.getObject(i));
}
rows.addElement(newRow);
}
return new DefaultTableModel(rows, columnNames);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
"I cannot get my JTable to update with a new row unless I restart the program."
I think what you're expecting is that when the database table update, so should your JTable. It doesn't really work like that. You need to update the TableModel, and the JTable will be automatically updated
Since resultSetToTableModel returns a DefuaultTableModel, you can use either of the two methods from DefaultTableModel:
public void addRow(Object[] rowData) - Adds a row to the end of the model. The new row will contain null values unless rowData is specified. Notification of the row being added will be generated.
public void addRow(Vector rowData) - Adds a row to the end of the model. The new row will contain null values unless rowData is specified. Notification of the row being added will be generated.
So when your are adding the data to the database, you also want to update the DefaultTableModel like this
public static void addGenre(Integer a, String b){
...
rowsAdded = stmt.executeUpdate(query);
if (rowsAdded > 0) {
DefaultTableModel model = (DefaultTableModel)tab1.getModel();
model.addRow( new Object[] { a, b });
}
}
Also noticed I changed the method signature to Integer instead of int so it will fit with the Object[] passed to addRow. The int you pass to it will get autoboxed to Integer
SIDE NOTES
Don't swallow you exception by putting nothing in the catch block. Put something meaningful that will notify you of any exceptions that may occur, like
catch(Exception ex) {
ex.printStackTrace();
}
You should also close your Connections, Statements, and ResultSets
You should use PreparedStatement instead of Statement, to avoid SQL injection.
private void resetListData() throws ClassNotFoundException, SQLException
{
Connection cne = null;
try {
Class.forName("org.sqlite.JDBC");
cne = DriverManager.getConnection("jdbc:sqlite:table.sqlite");
cne.setAutoCommit(false);
PreparedStatement psd = (PreparedStatement) cne.prepareStatement("Select * from Genres");
psd.execute();
ResultSet r = psd.getResultSet();
ResultSetMetaData rsmd = r.getMetaData();
int count = rsmd.getColumnCount();
String[] meta = new String[count];
for (int i = 0; i < count; i++)
{
String name = rsmd.getColumnName(i + 1);
meta[i] = name;
//System.out.println(name);
}
model = new DefaultTableModel(new Object[][]{}, new String[]{"name", "address"});
jTable1.setModel(model);
while (r.next())
{
Object[] row = new Object[count];
for (int i = 1; i <= count; ++i)
{
row[i - 1] = r.getString(i); // Or even rs.getObject()
}
model.addRow(row);
}
cne.close();
} catch (ClassNotFoundException | SQLException e) {
}
}
Use this code. so you can insert one row at the end of Jtable without restarting application.,
Thanks..
I have a webservice where from the Client-side some parameters are passed to perform a query on the DB, the Server-Side is supposed to carry out the query and return the results.Since the result might be more than one row and i will have to use it on the client-side to show an output this what i did:
1.Perform the query
2.take each row of the result and put it in an array
3.convert the array to String and pass it to the client side(converted array to String, because it was simple)
BUT the problem is that it doesnt pass the the array-turned-string but only the value which was used to initialize the string, here is the code
String ris = "";
String q;
String beta = null;
String one="";
String errore = connetti();
try {
if (errore.equals("")) {
Statement st = conn.createStatement();
//ESECUZIONE QUERY
q = "SELECT DISTINCT nome FROM malattia WHERE eta='" + age + "' AND sesso='" + sexstr + "' AND etnia='" + etniastr + "' AND sintomi IN(" + tes + ")";
ResultSet rs = st.executeQuery(q);
if (!rs.last()) {
ris = "no";
}
//This is the part which i'm talking about
else {
//getRowCount is another class used to find out number of rows,I use it to declare an array which would contain the result of the query
int two=getRowCount(rs);
String[] alpha= new String[two];
//Loop through the resultstatement and put result from the column **nome** in the array **alpha**
while(rs.next()){
alpha[i]=rs.getString("nome");
i++;
}
//The value of ris which is empty, is returned
ris="";
//instead of this one, where i convert the array **alpha** to String
ris=arrayToString(alpha,",");
}
}
else {
ris = errore;
}
conn.close();
} catch (Exception e) {
ris = e.toString();
}
return ris;
}
//returns the number of rows of **ris**
public static int getRowCount(ResultSet set) throws SQLException
{
int rowCount;
int currentRow = set.getRow(); // Get current row
rowCount = set.last() ? set.getRow() : 0; // Determine number of rows
if (currentRow == 0) // If there was no current row
set.beforeFirst(); // We want next() to go to first row
else // If there WAS a current row
set.absolute(currentRow); // Restore it
return rowCount;
}
//converts the array to String
public String arrayToString(String[] array, String delimiter) {
StringBuilder arTostr = new StringBuilder();
if (array.length > 0) {
arTostr.append(array[0]);
for (int i=1; i<array.length; i++) {
arTostr.append(delimiter);
arTostr.append(array[i]);
}
}
return arTostr.toString();
Thanks alot in advance!
After conn.close() you return beta instead of ris. This may be the cause of the behavior you are experiencing. However, I am not sure because I can not properly see how you open and close the curly brackets.
Why do I keep on getting an exception-illegal operation on ResultSet?
Here is the code:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/*
* SearchParts.java
*
* Created on 08-Mar-2010, 12:14:31
*/
package garits;
import java.sql.*;
import javax.swing.*;
/**
*
* #author Deniz
*/
public class SearchParts extends javax.swing.JFrame {
/** Creates new form SearchParts */
public SearchParts() {
initComponents();
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
if (!jTextField1.getText().equals("")) {
String result = "";
int Partnumber = Integer.parseInt(jTextField1.getText());
DB db = new DB();
try {
db.connect();
String query = "Select * from Stock Where Part_no =" + "'" + jTextField1.getText() + "'";
ResultSet rs = db.execSQL(query);
if (rs.equals(null)) {
PartNotFound nf = new PartNotFound();
nf.setVisible(true);
} else {
ResultSetMetaData rsmd = rs.getMetaData();
int numberOfColumns = rsmd.getColumnCount();
int RowCount = 0;
for (int i = 1; i < numberOfColumns; i++) {
rs.getString(i);
result += i + "/n";
}
if (!result.equals("")) {
Receptionist_FranchiseePartFound part = new Receptionist_FranchiseePartFound();
part.setVisible(true);
while (rs.next()) {
RowCount++;
}
part.getTable().addRowSelectionInterval(0, RowCount);
} else {
PartNotFound nf = new PartNotFound();
}
}
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(jButton1, "More information needed for search", "Error Message", JOptionPane.ERROR_MESSAGE);
}
} else if (!jTextField2.getText().equals("")) {
String result = "";
DB db = new DB();
try {
db.connect();
String query = "Select * from Stock Where Part_name =" + "'" + jTextField2.getText() + "'";
ResultSet rs = db.execSQL(query);
if (rs.equals(null)) {
PartNotFound nf = new PartNotFound();
nf.setVisible(true);
} else {
ResultSetMetaData rsmd = rs.getMetaData();
int numberOfColumns = rsmd.getColumnCount();
int RowCount = 0;
for (int i = 1; i < numberOfColumns; i++) {
rs.getString(i);
result += i + "/n";
}
// Receptionist_FranchiseePartFound part = new Receptionist_FranchiseePartFound();
// part.setVisible(true);
if (!result.equals("")) {
Receptionist_FranchiseePartFound part = new Receptionist_FranchiseePartFound();
part.setVisible(true);
while (rs.next()) {
RowCount++;
}
part.getTable().addRowSelectionInterval(0, RowCount);
} else {
PartNotFound nf = new PartNotFound();
nf.setVisible(true);
}
}
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(jButton1, "More information needed for search", "Error Message", JOptionPane.ERROR_MESSAGE);
}
} else if (jTextField1.getText().equals("") && jTextField2.getText().equals("")) {
String result = "";
DB db = new DB();
try {
db.connect();
String query = "Select * from Stock Where Manufacturer =" + "'" + jTextField3.getText() + "'AND Vehicle_type ='" + jTextField4.getText() + "'";
ResultSet rs = db.execSQL(query);
if (rs.equals(null)) {
PartNotFound nf = new PartNotFound();
nf.setVisible(true);
}
else{
ResultSetMetaData rsmd = rs.getMetaData();
int numberOfColumns = rsmd.getColumnCount();
int RowCount = 0;
for (int i = 1; i < numberOfColumns; i++) {
rs.getString(i);
result += i + "/n";
}
// Receptionist_FranchiseePartFound part = new Receptionist_FranchiseePartFound();
// part.setVisible(true);
if (!result.equals("")) {
Receptionist_FranchiseePartFound part = new Receptionist_FranchiseePartFound();
part.setVisible(true);
while (rs.next()) {
RowCount++;
}
part.getTable().addRowSelectionInterval(0, RowCount);
} else {
PartNotFound nf = new PartNotFound();
nf.setVisible(true);
}
}
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(jButton1, "More information needed for search", "Error Message", JOptionPane.ERROR_MESSAGE);
}
} else if (jTextField3.getText().equals("") || jTextField4.getText().equals("")) {
JOptionPane.showMessageDialog(jButton1, "More information needed for search", "Error Message", JOptionPane.ERROR_MESSAGE);
}
}
/**
* #param args the command line arguments
*/
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabel7;
private javax.swing.JLabel jLabel8;
private javax.swing.JTextField jTextField1;
private javax.swing.JTextField jTextField2;
private javax.swing.JTextField jTextField3;
private javax.swing.JTextField jTextField4;
// End of variables declaration
}
I see a few things
First rs is never null. If there are no rows then rs.next() will return false
ResultSet starts position BEFORE the first row. You need to call rs.next() to move to the first row which, as above, will return false if there are no rows.
The typical pattern for ResultSet use is...
while (rs.next())
{
rs.getXXX();
}
ResultSet should ALWAYS be close()d when you are done, otherwise you may leak database resources. This also applies to Connection, Statement, PreparedStatement so check your DB code in other classes.
When looping over the column metadata you need to do..
for (int i = 1; i <= numberOfColumns; i++) {
}
Note the <= rather than <. As you have correctly found that JDBC column indexes start at 1.
It would be worth considering using a library that hides all the JDBC noise. Consider spring which has a basic JDBC abstraction while retaining all the power or all the way up to hibernate which is very powerful but has quite a learning curve. In your case I'd recommend just use the spring stuff.
See: Spring docs
You always need to call next() on the ResultSet, before accessing it. If not, the pointer points to the row before the first. You do this with while-loops in your code, but some places you dont, which generates an error:
for (int i = 1; i < numberOfColumns; i++) {
rs.getString(i);
result += i + "/n";
}
Ohh, and as another poster mentions, you dont assign the result to a variable, so the rs.getString(i) call has no effect. But this is probably your source of error.
if rs is null, then rs.equals(null) will throw a NullPointerException instead of returning false. Nevertheless if that is not the exception you are getting then the problem lies somewhere else.
Also, take a look into the javadoc/code for the DB class' execSQL(query) method. Typically, a ResultSet is never null, e.g. like when you use PreparedStatement.executeQuery. However, check into the that execSQL method to verify whether or not it will ever return a null ResultSet.
Remove the following line, it serves no purpose.
Its trying to the the column value from the ResultSet but you haven't scrolled to the first row yet
rs.getString(i);
Several have pointed out some of your problems in the code. The reason for your exception is because you have not advanced to the first row using rs.next(). If you expect that your SQL statement will only retrieve a single row then you probably should change your rs.equals(null) statement to:
if (!rs.next()) {
...code here to set not found...
} else {
...code here to retrieve the columns...
}
Here are some other tips. In the code to retrieve the columns, your use of rs.getString(i) doesn't do anything, the result variable is just accumulating the column numbers with "/n" (not new-line; probably that should be "\n"). So the loop inside that section should probably become:
for (int i = 1; i <= numberOfColumns; i++) {
result += rs.getString(i) + "\n";
}
But concatenating to a immutable String is not good and can result in slow execution for large numbers of concatenations. Use a StringBuilder instead and initialize it to a reasonable size, something like this:
StringBuilder sb = new StringBuilder(256);
for (int i = 1; i <= numberOfColumns; i++) {
sb.append(rs.getString(i)).append("\n");
}
result = sb.toString();
Later you loop through the results set, so in the loop through the columns are you trying to get column names from the meta data? In that case:
StringBuilder sb = new StringBuilder(256);
for (int i = 1; i <= numberOfColumns; i++) {
sb.append(rsmd.getColumnName(i)).append("\n");
}
result = sb.toString();
But since you need to check for the first row the next loop will not count the number of rows correctly so you will need to adjust for that, perhaps (and there is no need to check result at that point since it is guaranteed to no longer be an empty string since there must be at least one column in the table):
do {
RowCount++; // recommend using rowCount.
} while (rs.next());
In the end, what are you using result for? It seems that this is just used to determine if there were some columns in the result. If that is all then you can eliminate most of this code. For what you actually have (I don't know if this is your intent), this could be reduced to (in the else if where you do the DB interaction):
DB db = new DB();
try {
db.connect();
String query = "select count(1) from Stock where Part_name =" + ...;
ResultSet rs = db.execSQL(query);
if (!rs.next()) {
PartNotFound nf = ...;
nf.setVisible(true);
} else {
Receptionist_FranchiseePartFound part = new Receptionist_FranchiseePartFound();
part.setVisible(true);
rowCount = rs.getInt(1);
part.getTable().addRowSelectionInterval(0, rowCount);
}
} catch (Exception e) {
...error handling with stack trace/JOptionPane...
}
Note that if you are just after the count of rows then it is best to let the database engine do that for you - looping through the result rows just to count them also means that all that data must be sent to your application. Instead, if you just use the aggregate function then the database only needs to send a single row and column to your application.