How can I add an ArrayList to a jtable? - java

I've been working on a web-service that returns an arraylist. How can I add the returning arraylist to jtable and display?
ArrayList customerDetails = new ArrayList();
try {
String sqlQuery = "SELECT * FROM customer WHERE AccountNumber="+accountNumber;
PreparedStatement stmt = DatabaseConnection.dBconn().prepareStatement(sqlQuery);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
customerDetails.add(rs.getString("Name"));
customerDetails.add(rs.getString("DoB"));
customerDetails.add(rs.getString("Address"));
customerDetails.add(rs.getString("Mobile"));
customerDetails.add(rs.getString("Email"));
customerDetails.add(rs.getString("AccountType"));
customerDetails.add(rs.getString("AccountNumber"));
customerDetails.add(rs.getString("SortCode"));
customerDetails.add(rs.getString("Balance"));
customerDetails.add(rs.getString("Card"));
}
return customerDetails;
} catch (SQLException err) {
System.out.println(err.getMessage());
}
return customerDetails;

Let's start with the fact that your ArrayList is not structured as a row/columns grouping, you will need a List within a List, where the outer list is the rows and the inner list are the column values
While we're at it, let's also make use of the PreparedStatement properly and manage the resources so they are closed properly while we're at it
ArrayList<List<String>> customerDetails = new ArrayList<>(25);
String sqlQuery = "SELECT * FROM customer WHERE AccountNumber=?";
try (PreparedStatement stmt = DatabaseConnection.dBconn().prepareStatement(sqlQuery)) {
stmt.setString(1, accountNumber);
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
List<String> rowDetails = new ArrayList<>(10);
rowDetails.add(rs.getString("Name"));
rowDetails.add(rs.getString("DoB"));
rowDetails.add(rs.getString("Address"));
rowDetails.add(rs.getString("Mobile"));
rowDetails.add(rs.getString("Email"));
rowDetails.add(rs.getString("AccountType"));
rowDetails.add(rs.getString("AccountNumber"));
rowDetails.add(rs.getString("SortCode"));
rowDetails.add(rs.getString("Balance"));
rowDetails.add(rs.getString("Card"));
customerDetails.add(rowDetails);
}
}
} catch (SQLException err) {
System.out.println(err.getMessage());
}
return customerDetails;
Have a look at Using Prepared Statements and The try-with-resources Statement for more details
Now, we need a TableModel which can support it, at very basic level...
public class ListTableModel extends AbstractTableModel {
private List<List<String>> rows;
private List<String> columnNames;
public ListTableModel(List<String> columnNames, List<List<String>> rows) {
this.rows = new ArrayList<>(rows);
this.columnNames = columnNames;
}
#Override
public int getRowCount() {
return rows.size();
}
#Override
public int getColumnCount() {
return columnNames.size();
}
#Override
public String getColumnName(int column) {
return columnNames.get(column);
}
#Override
public Class<?> getColumnClass(int columnIndex) {
Class type = String.class;
return type;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
List<String> rowData = rows.get(rowIndex);
return rowData.get(columnIndex);
}
}
This takes a List for the column names and a List<List> for the row data.
Personally, I'd prefer to wrap the data into some kind of Plain Old Java Object (POJO) as it encapsulates the data and provides greater flexibility when displaying it (ie, I need to display all the properties of the object if I don't want to)
Take a look at How to Use Tables for more details

Related

How to map CURSOR to Map in iBatis

I'm wondering if is there possibility to map first row from Oracle Cursor to java.util.Map (using column names as keys) in iBatis version 2.3.4.726. I came up to with TypeHandlerCallback:
public class MapResultTypeHandler implements TypeHandlerCallback {
#Override
public void setParameter(final ParameterSetter parameterSetter, final Object o) throws SQLException {
throw new UnsupportedOperationException();
}
#Override
public Map<String, Object> getResult(final ResultGetter resultGetter) throws SQLException {
ResultSet resultSet = resultGetter.getResultSet();
ResultSetMetaData metaData = resultSet.getMetaData();
int columnsNumber = metaData.getColumnCount();
Map<String, Object> result = new HashMap<>(columnsNumber);
do {
for(int i=1; i <= columnsNumber; ++i) {
result.put(metaData.getColumnName(i), resultSet.getObject(i));
}
} while (resultSet.next());
return result;
}
#Override
public Object valueOf(final String s) {
return null;
}
}
Unfortunately method getMetaData throws:
UnsupportedOperationException("CallableStatement does not support this method.");
Is there other possibility to achieve this goal?
I finally managed to map Oracle Cursor to Map! I had to modify first row of getResult method. It should look like:
ResultSet resultSet = (ResultSet) resultGetter.getObject();

Why does JTable only present 1st row of data?

I'm starting to learn how to use databases and was trying to export the data from my h2 database into a JTable. The table comes up with the correct number of rows, however, only the first row is filled with data. The rest is a blank grid. I posted some code below for the JTable. If someone needs to see more code, I'll post it.
public class Table extends JTable{
public static int rows;
public static String[][] data;
public static String[] columns = {"Author", "Customer", "Date"};
public static void populateTable() throws ClassNotFoundException, SQLException{
//Server is name of the database class
Server server = new Server();
Statement stat = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stat.executeQuery("SELECT * FROM data");
rs.last();
rows = rs.getRow();
rs.beforeFirst();
data = new String[3][rows];
while(rs.next()){
int i = 0;
data[0][i] = rs.getString("Author");
data[1][i] = rs.getString("Customer");
data[2][i] = rs.getString("Date");
System.out.println(rs.getString("Author"));
i = i++;
}
rs.close();
}
}
class MyTableModel extends DefaultTableModel{
String[] columnNames = {"Author", "Customer", "Date"};
MyTableModel() throws ClassNotFoundException, SQLException{
addColumn(columnNames[0]);
addColumn(columnNames[1]);
addColumn(columnNames[2]);
}
#Override
public int getRowCount() {
return rows;
}
#Override
public int getColumnCount() {
return 3;
}
#Override
public String getColumnName(int columnIndex) {
return columnNames[columnIndex];
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return data[columnIndex][rowIndex];
}
I'm also able to print to the console all the data, but it just won't show up in the JTable. I have been stuck on this problem for hours but I don't know what I'm doing wrong. Thanks in advance
This statement is a no-op since i is assigned before it is incremented
i = i++;
just use
i++;
Also initialize i before entering the loop
You should either use a for loop or declare i outside of your loop. As it stands, you are setting all data to row 0 (int i = 0);
while(rs.next()){
int i = 0; // this will run for every row
data[0][i] = rs.getString("Author");
data[1][i] = rs.getString("Customer");
data[2][i] = rs.getString("Date");
System.out.println(rs.getString("Author"));
i = i++;
}

how to list an items to a JTable

I am trying to create a checkout simulation for my coursework. So every time I search for an item I can retrieve it from the database and display it on the JTable. However, once I add an item to the list and try to add another item the old item get replaced by the new item.
I am trying to list all the item in the JTable, this is my code:
DBConnection db = new DBConnection();
try {
ResultSet rs = DBConnection.stmt.executeQuery("SELECT ID, MESSAGE FROM STOCK WHERE ID = '"+ id + "'");
jTable1.setModel(DbUtils.resultSetToTableModel(rs));
}
catch (Exception e){
System.out.println(e);
}`
The main problem is DbUtils.resultSetToTableModel(rs), which is creating a brand new TableModel, filled with the contents of the ResultSet, this, when applied to the JTable is replacing the view with the contents of the TableModel.
In order to be able to update the table, you need to update the existing TableModel...
There are a few ways this might be achieved, by the simplest might be to use a DefaultTableModel...
Start by creating a class instance field of a DefaultTableModel...
public class ... {
//...
private DefaultTableModel stockTableModel;
//...
Then, when you want to load the stock items, you will need to initialise the model, if it's not already initialised, and then add the new results to it...
DBConnection db = new DBConnection();
try (ResultSet rs = DBConnection.stmt.executeQuery("SELECT ID, MESSAGE FROM STOCK WHERE ID = '" + id + "'")) {
if (stockTableModel == null) {
stockTableModel = new DefaultTableModel();
for (int col = 0; col < metaData.getColumnCount(); col++) {
stockTableModel.addColumn(metaData.getColumnName(col + 1));
}
jTable.setModel(model);
}
while (rs.next()) {
Vector rowData = new Vector(metaData.getColumnCount());
for (int col = 0; col < metaData.getColumnCount(); col++) {
rowData.add(rs.getObject(col + 1));
}
stockTableModel.addRow(rowData);
}
} catch (SQLException exp) {
exp.printStackTrace();
}
Take a look at How to Use Tables and JDBC Database Access for more details
You can create a custom data model that allows you to insert new rows to table.
lets say that you have class, that can hold your query result fields.
public class Item implements Comparable<Item> {
private Long id;
private String message;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
public String getMessage() {
return message;
}
public void setMessage(String value) {
this.message= value;
}
#Override
public int compareTo(Item o) {
return id.compareTo(o.id);
}
}
and it needs to go to table, which has been defined somewhere like:
JTable table =new JTable();
this is a data model to your table
public class Model extends AbstractTableModel {
private List<Item> items;
public Model() {
items = new ArrayList<>();
}
#Override
public int getRowCount() {
return items.size();
}
#Override
public int getColumnCount() {
return 3;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (rowIndex > items.size() - 1 || rowIndex < 0) {
return "";
}
final Item get = items.get(rowIndex);
switch (columnIndex) {
case 0:
return get.getId();
case 1:
return get.getMessage();
}
return "";
}
#Override
public String getColumnName(int column) {
switch (column) {
case 0:
return "id";
case 1:
return "message";
}
return "";
}
public void addItem(Item i) {
items.add(i);
fireTableDataChanged();
}
public void addItem(ResultSet rs) {
try {
Item item = new Item();
item.setId(rs.getLong("ID"));
item.setMessage(rs.getString("MESSAGE"));
items.add(item);
fireTableDataChanged();
} catch (SQLException ex) {
Logger.getLogger(Model.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
now create field
Model myModel=new Model();
and set it as a table model
table.setModel(myModel);
now every time you need to add something to table, just use our table model (i created two methods to insert data public void addItem(Item i) and public void addItem(ResultSet rs).
this should work. If you need to clear table sometimes, just add pubic method public void clear() to your model, in which you will clear items list and call fireTableDataChanged();. It is necessary, otherwise GUI will not refresh.
EDIT
Your code should be like
DBConnection db = new DBConnection();
try {
ResultSet rs = DBConnection.stmt.executeQuery("SELECT ID, MESSAGE FROM STOCK WHERE ID = '" + id + "'");
myModel.add(rs);
} catch (Exception e) {
System.out.println(e);
}
Just add a row to your JTable Model every time you have your result...
refer to this SO question
DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
model.addRow(new Object[]{"Column 1", "Column 2", "Column 3"});
or in your case
DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
model.addRow(new Object[]{searchResultData});

Definition TableModel removeRow() method [duplicate]

This question already has an answer here:
TableModel removeRow() definition [closed]
(1 answer)
Closed 9 years ago.
This is my tableModel:
public class d9 extends AbstractTableModel {
ArrayList<String> cols = new ArrayList<>();
ArrayList<ArrayList<String>> data = new ArrayList<>();
public d9() {
...
int c = resultSet.getMetaData().getColumnCount();
while (resultSet.next()) {
ArrayList<String> eachRow = new ArrayList<>();
for (int i = 1; i <= c; i++) {
eachRow.add(resultSet.getString(i));
}
data.add(eachRow);
}
...
}
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
return cols.size();
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
ArrayList<String> selectedRow = data.get(rowIndex);
return selectedRow.get(columnIndex);
}
#Override
public String getColumnName(int column) {
return cols.get(column);
}
public void removeRow(int rowNumber) {
data.remove(rowNumber);
fireTableRowsDeleted(rowNumber, rowNumber);
}
}
Now, after passing a convertRowIndexToModel line number to removeRow method
Row remove from table, But after re-run program, It come back!
When you call removeRow you need to try and remove the row from the database.
Now because I have no idea what the structure of your database is, you will need to fill in the details, but this a simple outline of what you need to do
public void removeRow(int rowNumber) throws SQLException {
Connection con = ...;
PreparedStatement ps = null;
String keyValue = ...; // Get key value from the ArrayList
try {
ps = con.prepareStatement("DELETE from youDatabaseTabe where key=?");
ps.setObject(1, keyValue);
if (ps.executeUpdate() == 1) {
data.remove(rowNumber);
fireTableRowsDeleted(rowNumber, rowNumber);
} else {
throw new SQLException("Failed to remove row from database");
}
} finally {
try {
ps.close();
} catch (Exception e) {
}
}
}
You may want to spend some time having a read through JDBC Database Access

Java- How to initialize rows dynamically on JTable?

I want to bind mysql table content with JTable. I have connected sucessfully. I set table row and width as 500. It will shows 500 rows including data and empty. Now I want to view only data. I don't want to view empty rows.
Please help me
My application get slow after insert a method getRowCountFromDB()..
class AbstractTableEmployee extends AbstractTableModel {
int row2;
private String[] columnNames = { "ID", "Name", "Company", "Department", "Location", "Mobile NO" , "Shift" };
private Object[][] data = new Object[500][500];
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
int row = 0;
try {
row = this.count();
} catch (SQLException ex) {
Logger.getLogger(AbstractTableEmployee.class.getName()).log(Level.SEVERE, null, ex);
}
return row;
}
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}
private int getRowCountFromDB() throws SQLException {
Connection con = (Connection) DBConnection.getDBConnection();
int row = 0;
Statement st = null;
ResultSet rs = null;
String Sql = "Select * from Employee_Master where status = 'Active'";
try {
st = (Statement) con.createStatement();
rs = st.executeQuery(Sql);
while (rs.next())
{
row++;
}
}
finally {
con.close();
rs.close();
st.close();
}
return row;
}
private int count() throws SQLException {
return this.getRowCountFromDB();
}
}
Thanks in advance.
The documentation for JTable gives the following example for how to use a table with a custom table model.
TableModel dataModel = new AbstractTableModel() {
public int getColumnCount() { return 10; }
public int getRowCount() { return 10;}
public Object getValueAt(int row, int col) { return new Integer(row*col); }
};
JTable table = new JTable(dataModel);
JScrollPane scrollpane = new JScrollPane(table);
This is the minimal implementation that you'd have to provide.
Edit:
See 3.3.4.8 Counting Rows in the MySQL Reference for information on how to get a row count efficiently. It seems to me that you're fetching an entire table, when all you want is a number.
You'd want something along the lines of
Select COUNT(*) from Employee_Master where status = 'Active'
and then just reading that value.
As for your data, I see no reason for it to have 500 columns, given that your table seems to have only 7.
Anyway, depending on the size of your table, you might not want to have all the data in there at once. If that's the case, you can always fetch and cache chunks of rows, according to where in the JTable your user is scrolling. You could use LIMIT for that.
For some other ideas and tips, you should also take a look at this question which covers a similar problem.
as mentioned by another posters better would be read JTable tutorial before, since little bit crypted in the text, your method is JTable#setValueAt(Object aValue, int row, int column),

Categories