Updatable ResultSet row count - java

I want to bind a database table to a swing JTable, and make that JTable editable by using APIs in a updatable ResultSet(#insertRow,#deleteRow(),#updateRow()).
so I need to create a TableModel implementation by wrapping a ResultSet.
public class MyTableModel implements TableModel {
private ResultSet rs;
private ResultSetMetaData rsmd;
#Override
public int getRowCount() {
return 0;
}
#Override
public int getColumnCount() {
return 0;
}
#Override
public String getColumnName(int columnIndex) {
return null;
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return null;
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return null;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
}
#Override
public void addTableModelListener(TableModelListener l) {
}
#Override
public void removeTableModelListener(TableModelListener l) {
}
}
then, how Can I implement the getRowCount() method ?
how to determine the numbers of rows in a updatable result set ?
for example, if user click a button "add row", then I call such methods :
rs.moveToInsertRow();
rs.updateString(1, "yqwang");
rs.insertRow();
how to sync the JTable UI and the underlying ResultSet?

You should not do that. A ResultSet needs an open connection to the database, and the changes done to the result set won't be committed to the database until you commit the connection.
This means that if the database decides to close the connection because it hasn't seen any activity for some time, or if your app crashes after three hours, you'll lose all the modifications done during these 3 hours.
This also means that you might lock some rows for a whole lot of time, and thus make other transactions wait for a whole lot of time before being able to do anything.
Copy the data from the result set into your table model, and start a new transaction each time you need to insert or update a row.

To bind JTable to database you need to refresh your JTable and relode JTable. To get no. of rows in result set just call these two methods-
rs.last();
int count = rs.getRow();
here count gives you no. of records in your ResultSet.

When you do insertRow() on the ResultSet "You cannot see INSERT result on the ResultSet". To see rows that where inserted you have to re-run your query and get new resultset.
For reference on "No result set type can see a row inserted by a result set INSERT operation." see http://docs.oracle.com/cd/B28359_01/java.111/b31224/resltset.htm#i1024719

Related

How to make columns editable in special abstract model JTable

Hey guys i doing my assignment and now i have the problem with non editable cells, actually it became editable, but the result of editing didn't set at arraylist, I tried many solution from internet, but it doesn't work.
So my work like registration system which get information about guest, and then stored it into csv file. In additional function the program must let display, update, delete and searching function.
I finished all, without update,delete and searching. Can you please looking my code and help me or give the advice, link or something useful.
this is my abstract model:
public class ddispmodel extends AbstractTableModel {
private final String[] columnNames = { "FirstName", "SecondName", "Date of
birth", "Gender", "Email", "Address", "Number", "Attending","ID" };
private ArrayList<String[]> Data = new ArrayList<String[]>();
private boolean editable;
public void AddCSVData(ArrayList<String[]> DataIn) {
this.Data = DataIn;
this.fireTableDataChanged();
}
#Override
public int getColumnCount() {
return columnNames.length;// length;
}
#Override
public int getRowCount() {
return Data.size();
}
#Override
public String getColumnName(int col) {
return columnNames[col];
}
#Override
public Object getValueAt(int row, int col) {
return Data.get(row)[col];
}
public boolean isCellEditable(int row, int col) {
setValueAt(Data, row, col);
this.fireTableCellUpdated(row, col);
return true;
}
}
This is part of my main class
It is action Listener of menu item witch activate displaying function
(I didn't copy all class, because it nearly 1000 lines, but if it necessary, i can submit all code )
dlog.addActionListener(new ActionListener (){
public void actionPerformed(ActionEvent e){
CSVFileDomestic Rd = new CSVFileDomestic();
ddispmodel ddispm = new ddispmodel();
ddisp.setModel(ddispm);
File DataFile = new File("D:\\cdne4\\WorkPlace\\Domestic.csv");
ArrayList<String[]> Rs2 = Rd.ReadCSVfile(DataFile);
ddispm.AddCSVData(Rs2);
System.out.println("Rows: " + ddispm.getRowCount());
System.out.println("Cols: " + ddispm.getColumnCount());
cl.show(cp, "dispDomPanel");
}
});
and File class which convert date from csv to arraylist
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
public class CSVFileDomestic {
private final ArrayList<String[]> Rs = new ArrayList<String[]>();
private String[] OneRow;
public ArrayList<String[]> ReadCSVfile(File DataFile) {
try {
BufferedReader brd = new BufferedReader(new
FileReader(DataFile));
while (brd.ready()) {
String st = brd.readLine();
OneRow = st.split(",");
Rs.add(OneRow);
System.out.println(Arrays.toString(OneRow));
}
}
catch (Exception e) {
String errmsg = e.getMessage();
System.out.println("File not found:" + errmsg);
}
return Rs;
I am new at Java and this is my first program , please can you explain more easily
but the result of editing didn't set at arraylist,
You need to override the setValueAt(...) method of the TableModel to save the data.
It would be something like:
String[] row = data.get(row);
row[column] = value;
this.fireTableCellUpdated(row, col);
Also, the isCellEditable(...) method should NOT do any processing. It simply returns true/false for the given column. If you want all columns editable then it should just be:
public boolean isCellEditable(int row, int col) {
//setValueAt(Data, row, col);
//this.fireTableCellUpdated(row, col);
return true;
}
I finish this)) and go to do others options.
camickr thank you for help, you give me the way, which bring me to answer))
I spend nearly 6 hours for trying to do it and finally I got it.
If someone interesting, answer is
public boolean isCellEditable(int row, int col) {
return true;
}
#Override
public void setValueAt(Object aValue, int row, int col){
Data.get(row)[col]= (String) aValue;
fireTableCellUpdated(row,col);
so I just make new method setValueAT which said me camickr.
than I went to Oracle site and read about it, and after try it to do, but
it doesn't, because aValue can't be converted from object to String, and finally I initiate aValue as a String, so now it works.However it is not all, it only change arraylist. Needs new method to convert arraylist to csv file. I am working about it now, maybe after I will show it. Sorry for my theory, I am new at java, just learn how it works))

Why we extends AbstractTabelModel when set values into JTabel?

Im developing a app for ordeing system and i have to set data into JTabels.
And this code is successfully working.I wanted to know what the importance of and whats happen in this class?
Why we need to import AbstractTabelModel.class?
OrderTabelModel Class:-
public class OrderTableModel extends AbstractTableModel{
protected static final String[] COLUMN_NAMES={"Item","Qty","Amount"};
private List<Order> rows;
public OrderTableModel(List<Order> rows){
this.rows = new ArrayList<>(rows);
}
#Override
public int getRowCount() {
return rows.size();
}
#Override
public int getColumnCount() {
return COLUMN_NAMES.length;
}
#Override
public String getColumnName(int column) {
return COLUMN_NAMES[column];
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Object value = null;
Order row = rows.get(rowIndex);
switch (columnIndex) {
case 0:
value = row.getItem();
break;
case 1:
value = row.getQty();
break;
case 2:
value = row.getAmount();
break;
}
return value;
}
}
this is other class
private void tblOrderListMouseClicked(java.awt.event.MouseEvent evt) {
int raw = tblOrderList.getSelectedRow();
Order or;
String item;
Double qty,amount,total;
ArrayList<Order> arrOrder = new ArrayList<Order>();
String selectedRaw = tblOrderList.getModel().getValueAt(raw, 0).toString();
System.out.println("order id : "+selectedRaw);
String sql = "select item,qty,amount from orderdetails where orderid='"+selectedRaw+"'";
con = new DBconnector().connect();
try {
Statement ps =con.createStatement();
ResultSet rs2 = ps.executeQuery(sql);
while(rs2.next()){
or = new Order();
or.setItem(rs2.getString("item"));
System.out.println("Item :" +rs2.getString("item"));
or.setQty(rs2.getDouble("qty"));
or.setAmount(rs2.getDouble("amount"));
arrOrder.add(or);
}
rs2.close();
ps.close();
OrderTableModel tblModel = new OrderTableModel(arrOrder);
tblOrderItems.setModel(tblModel);
} catch (Exception e) {
e.printStackTrace();
}
}
Can some one explain me the process of this please?
It is not always mandatory to extend the AbstractTableModel. You can simply extend the DefaultTableModel and only override the getValueAt() method if you have to.
But most of the time for simple usages it is not even needed to override the getValueAt() method either.
By using the DefaultTableModel, you have a limitation for the converting you data (imported from DB) to an object[][] or Vector types which may be a little boring.
But you asked what is the importance of using AbstractTabelModel?
In this case I can say when JTable is started to being rendered, it needs to determine the number of rows and number of the columns and also it needs to know which data should be renedered in each cell and so on. Based on this, JTable ask for this Information from the underlying TableModel. So it is needed for your TableModel(any child or implementation of TableModel) to have those methods which are used by JTable to retrieve the needed information.
Hope this would be helpful.
Good Luck.

Make Jtable Noneditable without using setModel()

I want to make my JTable Non-editable
As I use following code to set rows using SetModel():
jTable1.setModel(DbUtils.resultSetToTableModel(rs)); //Resultset is added as each row using r2xml JAR file
I cant use follwing code:
jTable1.setModel(new DefaultTableModel() {
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
});
Because we cannot use two setModel() for jTable.
How to overcome this problem?
I want to setresult and make jTable Noneditable.
Here are 2 ways to achieve that:
Create and use your own TableModel implementation which forwards all calls to the table model returned by DbUtils except for isCellEditable() in which you can return always false hence disabling editing. Your own table model could get the model returned by DbUtils as a constructor argument for example.
You can extend JTable and override its isCellEditable() method to return false (by default it calls the model's isCellEditable() method). Maybe other Swing enthusiasts will see this as an evil hack, but it is the simplest solution to your problem here.
Elaborating method #1
This is how you can create your model:
class MyModel implements TableModel {
private final TableModel m;
public MyModel(TableModel m) {
this.m = m;
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
// This is how we disable editing:
return false;
}
// The rest of the methods just forward to the other model:
#Override
public int getRowCount() {
return m.getRowCount();
}
#Override
public int getColumnCount() {
return m.getColumnCount();
}
// ...and all other methods which I omit here...
}
And this is how you can use it:
jTable1.setModel(new MyModel(DbUtils.resultSetToTableModel(rs)));
Elaboration of method #2
Extending JTable can even be an anonymous class:
JTable jtable1 = new JTable() {
#Override
public boolean isCellEditable(int row, int column) {
// This is how we disable editing:
return false;
}
};
And using it:
// You can set any model, the table will not be editable because we overrode
// JTable.isCellEditable() to return false therefore the model will not be asked
// if editable.
jTable1.setModel(DbUtils.resultSetToTableModel(rs));
you can use this code for make non editable jTable
simply you write one line in your program
jTable.disable();

Refreshing JTable after changing data

I want to refresh and display my JTable after a user pressed a button. Before that the button generates an Object[][] in which the filtered data from the table is held.
The filtered data is different only in the number of rows.
I'm using the netbeans UI creator and the only way I could populate the table with data is by defining the abstractTableModel.
Here is the code of my abstractTableModel:
class myTable extends AbstractTableModel{
private String[] stolpci = {"Kategorija","Podkategorija","Opis","Cena","Datum","Boni"};
private Object[][] data = PregledovalnikGUI.vrniTabelo(); /*PregledovalnikGUI.vrniTabelo() returns a value in form of Object[][] in which the data is held*/
public int getColumnCount() {
return stolpci.length;
}
public int getRowCount() {
return vrstice.length;
}
public String getColumnName(int col) {
return stolpci[col];
}
public Object getValueAt(int row, int col) {
return vrstice[row][col];
}
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
public void setValueAt(Object value, int row, int col) {
vrstice[row][col] = value;
fireTableCellUpdated(row, col);
}
The jTable is set like:
Tabela.setModel(new myTable());
Which methods do I need to define to get the table to refresh at runtime?
inside myTable you could have a method called refresh() something like this
public void refresh(Object[][] objects){
//make the changes to the table, then call fireTableChanged
fireTableChanged(null);
}
Then in the button listener, call the above method:
Tablea.refresh(objects);//objects stores your filtered data
If you create a new TableModel, then nothing, the table will automatically update itself.
If the underlying data of the model is changed, then from within the model (seen as you extending from AbstractTableModl), you could call fireTableDataChanged, which lets the table know that the contents of the table have changed and it should redraw itself.
This may require that the model either have a refresh method of its own or that it has the capability to listen to changes from the data it is modelling

AbstractTableModel won't update JTable

i'm trying to make my JTable show changes made to my TableModel extending AbstractTableModel. I made a Heap to insert all the documents and then I apply a heapSort on my heap array, so this ordered array should be my TableModel data. It looks like this:
public class ModeloTabla extends AbstractTableModel {
private Heap heap;
private Nodo[] datos;
#Override
public int getRowCount() {
return heap.getNumNodos();
}
#Override
public int getColumnCount() {
return 4;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
if ( !heap.empty() ) {
datos = heap.heapSort();
}
Documento doc = datos[rowIndex].getDocumento();
switch ( columnIndex ) {
case 0:
return doc.getNombre();
case 1:
return doc.getHojas();
case 2:
return doc.getPrioridad();
default:
return null;
}
}
}
Inside the getValueAt method when I call heap.heapSort() the heap internal array is destroyed and it returns a Nodo[] with the ordered nodes. So when datos has an ordered array with nodes, my JTable won't show the data. Now, if I don't execute the heap.heapSort() and instead just call for the unordered array from the heap, my JTable shows everything.
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
datos = heap.getDatos();
Documento doc = datos[rowIndex].getDocumento();
... //This works but datos is unordered
}
}
I've tried replacing the Heap unordered array with the ordered one inside heapSort() and returning it using getDatos() but then the JTable again won't show up, also I've checked for the returning array from heapSort() and it's working well, the data is the same as the one from getDatos() but ordered. Any help with this would be very appreciated, thanks.
In the getValueAt() method you are retrieving the data from the datos object.
Documento doc = datos[rowIndex].getDocumento();
So the row count should be based on the number of rows in the datos object.
public int getRowCount() {
//return heap.getNumNodos();
return datos.length;
}
The getValueAt() method should NOT be sorting the data. The data in the model should already be sorted. Either sort it externally or sort it when you create the model. That is the getValueAt() method should not be changing the structure of the data. Also every time you change the data you would need to resort.

Categories