ResultSet not open. Operation GetMetaData is not allowed - java

I got some problem with a database class, I have got 2 methods there. That supposed to fill JTable with data from database.
The problem is Im reciving errors (tittle). Here is my code:
public class QueryModel {
private Connection connection = null;
private ResultSet resultSet = null;
private Statement statement = null;
private ResultSetMetaData metaData = null;
public void sendStatement(CreateDataBase database,String query)
{
try
{
connection = database.getConnection();
}
catch (SQLException | ClassNotFoundException e)
{
System.err.println(e);
}
if (!query.equals(""))
{
try
{
statement = connection.createStatement();
resultSet = statement.executeQuery(query);
metaData = resultSet.getMetaData();
if (statement.execute(query))
{
System.out.println("Result:");
JTable table = new JTable(buildTableModel());
JOptionPane.showMessageDialog(null, new JScrollPane(table));
}
else
{
System.out.println("Executed!");
}
statement.close();
}
catch (SQLException e)
{
System.err.println(e);
}
}
}
public DefaultTableModel buildTableModel() throws SQLException
{
// names of columns
Vector<String> columnNames = new Vector<String>();
int columnCount = metaData.getColumnCount();
for (int column = 1; column <= columnCount; column++)
columnNames.add(metaData.getColumnName(column));
// data of the table
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
while (resultSet.next())
{
Vector<Object> vector = new Vector<Object>();
for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++)
vector.add(resultSet.getObject(columnIndex));
data.add(vector);
}
return new DefaultTableModel(data, columnNames);
}
}
The problem seems to be getMetaData function in my opinion, without this every query goes smoothly. Problems started when I added this. I haven't been using this yet, so I do not know how to handle this, don't know if there is any sence to trying fixing it instead of doing this other way. Like more manually.

You are implicitly closing the first resultset when you execute the query for the second time in the "if" clause.
I mean, resultset is a pointer to an object defined in the executeQuery() and then you're redefining implicitly the resultset in the execute(query).
That's because you're querying twice.
Try defining metadata from inside your if block and see if it works (probably will)

Leo is right. The MetaData object comes from the first ResultSet which is closed when you re-execute the query. Don't execute the query twice, or if you have to, make sure you get a "fresh" MetaData object from the result set which you are actually navigating.

Related

Java UI - doesn't create and populate table

I am trying to pull data from a table in a mysql database and populate the results in a JTable. There are currently 3 tabs in the UI, the first two being input screens, which work fine. The 3rd tab, I am trying to run a query (after button is pushed) and display the results in a JTable. I am getting no error messages, but the screen does not display the table. Below is my code. Any assistance would be greatly appreciated. Note, user name and password have been replaced with generic. The query has also been simplified until I can get it to work. The system.out.print was just to check and see if it was pulling any data.
private void salePropertyActionPerformed(java.awt.event.ActionEvent evt) {
String sSelectQuery = "";
Statement statement=null;
Connection conn = null;
//PreparedStatement pStatement =null;
JPanel panel= spPanel;
TableColumn column;
JTable spTable = jTable1;
Vector columnNames = new Vector();
Vector data = new Vector();
spTable = new JTable(data,columnNames);
JScrollPane scrollPane = new JScrollPane(spTable);
panel.add(scrollPane);
try {
String myDriver = "com.mysql.jdbc.Driver";
String myURL = "jdbc:mysql://localhost:3306/realestate?autoReconnect=true&useSSL=false";
Class.forName(myDriver);
conn=DriverManager.getConnection(myURL,"root","jul1664bd");
/*Storing SQL statement*/
sSelectQuery ="SELECT propertyID, propertyPrice FROM property";
statement = conn.createStatement();
try (ResultSet rs = statement.executeQuery(sSelectQuery) //executes the query
) {
ResultSetMetaData metaData = rs.getMetaData();
int columns = metaData.getColumnCount();
for(int i = 1; i<=columns; i++){
columnNames.addElement(metaData.getColumnName(i));
}
while (rs.next()){
Vector row = new Vector(columns);
for (int i=1; i<=columns; i++){
row.addElement(rs.getObject(i));
}
data.addElement(row);
System.out.println(data);
}
rs.close();
for (int i=0; i<spTable.getColumnCount(); i++){
column=spTable.getColumnModel().getColumn(i);
//column.setMaxWidth(250);
}
}
statement.close();
} catch (SQLException e) {
System.err.println("An exception ocurred");
System.err.println(e.getMessage());
} catch (ClassNotFoundException ex) {
Logger.getLogger(realEstateUI.class.getName()).log(Level.SEVERE, null, ex);
}
JOptionPane.showMessageDialog(this,"Query Complete");
}
/**
You are attempting to add the JTable after the UI is visible. For the addition to take affect you must call revalidate followed by repaint. As an alternative, add your JTable upon UI construction (before it is visible) and populate the model of the JTable in salePropertyActionPerformed

More than one jTable with the same ResultSet in Java

Can you populate more than one jTable with the same resultSet?
public void tableDisplay() {
String tableQuery = "SELECT foodQuantity,foodName FROM food ORDER BY RAND() LIMIT 3";
ResultSet rs;
PreparedStatement statement;
try {
statement = con.prepareStatement(tableQuery);
rs = statement.executeQuery();
jTable1.setModel(DbUtils.resultSetToTableModel(rs));
jTable2.setModel(DbUtils.resultSetToTableModel(rs));
} catch (SQLException ex) {
System.out.println(ex.toString());
}
}
The code compiles but the second table doesn't get any records from DB.
The point is that I need to select random items from mySql table and I want to display them in few jTables.
Without knowing too much about your code, I'd say that you need to call DbUtils.resultSetToTableModel(rs) once, and store the resulting table model in a local variable. Then, pass that local variable to the two setModel(...) methods
How I populate a JTable with resultSet
try{
playerTableModel = (DefaultTableModel)playerTable.getModel();
rs = controller.getPlayer();
while (playerTableModel.getRowCount() > 0);
int columns = playerTableModel.getColumnCount();
Object[] rows = new Object[columns];
while(rs.next()){
rows[0] = rs.getString(1);
rows[1] = rs.getString(2);
rows[2] = rs.getString(3);
rows[3] = rs.getString(4);
playerTableModel.addRow(rows);
}catch(Exception e){
e.printStackTrace();
}
Can't you just call same method for the second table too?

Populating a JTable from Access Database

I am trying to populate a JTable with data from a database. I've tried so many different ways and it just doesn't want to work. Currently I have a class which returns a resultset with the entire database to my UIClass which then uses the resultset to populate the JTable. Bellow is my method that retrieves the resultset and then populates the JTable.
private void SetJTable()
{
int count = 0;
String boatclass, senior, under23, junior;
try
{
ResultSet results = object.AllWorldBestTimes();
DefaultTableModel model = (DefaultTableModel) Times.getModel();
model.addColumn("Boat Class");
model.addColumn("Senior");
model.addColumn("Under 23");
model.addColumn("Junior");
while(count<24)
{
boatclass = results.getString(1);
senior = results.getString(2);
under23 = results.getString(3);
junior = results.getString(4);
System.out.println(boatclass + senior + under23 + junior);
model.insertRow(Times.getRowCount(), new Object[]{boatclass, senior, under23, junior});
count++;
}
Times = new JTable(model);
}
catch (SQLException e)
{
System.out.println("Ef");
}
}
Here is the method of retrieving data from the database:
public ResultSet AllWorldBestTimes() throws SQLException
{
DatabaseConnection connection = new DatabaseConnection();
ResultSet result = connection.SelectStatements("SELECT * FROM WorldBestTimes");
return result;
}
there is no crash so i cannot give the stack trace, nor does it go into the catch statement.
any help would be appreciated!
model.insertRow(Times.getRowCount(), ...
Times.getRowCount() is always going to return zero, since it's empty.
Times = new JTable(model);
Reassigns the reference Times, but it doesn't take the old table out of the form or add the new one into the form.
Try this...
model = new DefaultTableModel();
...and this...
model.insertRow(model.getRowCount(), ...
...and this...
Times.setModel(model);
Hard to say if that will do it or not. The code sample isn't exactly SCCE.

JTable doesn't show the newly inserted row/data

I have a JTable and I populte the table as follows:
jTable_Std_info.setModel(DBControler.getALLStudents());
And the following is a static method in a class named DBControler which retrieves all the data from the database(Oracle).
public static DefaultTableModel getALLStudents() throws SQLException, Exception {
DefaultTableModel tableModel = new DefaultTableModel();
Vector rows = new Vector();
Vector columns = new Vector();
try {
conn = geConnection();
cst = conn.prepareCall("{? = call std_getInfoFunc}");
cst.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);
cst.execute();
res = (ResultSet) cst.getObject(1);
System.out.print(res);
ResultSetMetaData rsm = res.getMetaData();
for (int i = 1; i <= rsm.getColumnCount(); i++) {
columns.addElement(rsm.getColumnName(i));
}
int row = 0;
while (res.next()) {
Vector vRow = new Vector(); //to store the current row
//System.out.println("Row " +row+"\n");
for (int i = 1; i <= rsm.getColumnCount(); i++) {
String columnValue = res.getString(i);
vRow.addElement(columnValue);
}
row += 1;
rows.addElement(vRow);
}
tableModel.setDataVector(rows, columns);
} catch (SQLException e) {
e.printStackTrace();
} finally {
res.close();
conn.close();
}
return tableModel;
}
So far everything works fine, but the problem is that if I insert a new record in the database, the JTable doesn't get the newly inserted row/data. Why is that and how can I fix this problem?
UPDATE:
It's retrieving the data when I commit my new insertion. So do I have to commit each time I update? Or is there any other ways to do this?
I think that you looking for Oracle Built-In Database Change Notification, not sure if is accesible for Oracle's in free-versions, if not then never mind, for MySQL is there two or three similair API for Java JDBC
But the problem is that if I insert a new record in the database, the JTable doesn't get the newly inserted row/data. Why is that?
The TableModel doesn't know when the database is updated.
and how can I fix this problem?
If your application is adding the row to the database then it also needs to add a row to the TableModel at the same time.

SQL data and JTable

I'm trying one sample program for practice and i want to display results of database in JTable. The problem is i have no idea how to do that. I know how to get data from database and display it on text field or console but never tried with JTable. How to do that ?
Consider that i've table which is holding information like person name, age, city and date. i want it to be displayed via JTable. Also is it possible to update the JTable display if i add the option of adding more details in program(i mean adding entries to db then that will show immediately in JTable )?
Any suggestions, pointers on how to proceed is appreciated. Thanks in advance.
JDBC + JTable # google:
Hacking Swing: A JDBC Table Model
Mastering the JTable
Making SQL Queries with JDBC and Displaying Results with Swing
here is the code
public static TableModel resultSetToTableModel(ResultSet rs) {
try {
ResultSetMetaData metaData = rs.getMetaData();
int numberOfColumns = metaData.getColumnCount();
Vector<String> columnNames = new Vector<String>();
// Get the column names
for (int column = 0; column < numberOfColumns; column++) {
columnNames.addElement(metaData.getColumnLabel(column + 1).toUpperCase());
}
// Get all rows.
Vector<Vector<Object>> rows = new Vector<Vector<Object>>();
while (rs.next()) {
Vector<Object> newRow = new Vector<Object>();
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;
}
}
you can call this method such that way
void update_Table() throws ParseException
{
// we used this try catch so that values in table automatically show(without clicking on any button) when the dialog box open
try
{
Connection con=MSUTIL.getMSConnection();
PreparedStatement pst=con.prepareStatement("select payment_mode from PaymentMode");
ResultSet rs=pst.executeQuery();
//here i call that method
table.setModel(resultSetToTableModel(rs));
table.getTableHeader().setFont(new Font("SansSerif", Font.BOLD, 14));
while(rs.next())
{
mp.paymentmode_ComboBox.addItem(rs.getString("payment_mode"));
}
}
catch(SQLException e)
{
e.printStackTrace();
}
finally
{
//this method is for closing the connection
MSUTIL.cleanUp(con, pst, rs);
}
}

Categories

Resources