I'm new to java. I'm following a tutorial to retrieve images and other data from db to a jTable. Data will retrieve to an ArrayList first, and I get this error saying array required but object found. I have added all my code. The error is in the TheModel.java file. Any help would be appreciated.
Course.java
package my.welcomescreen;
public class Course {
private int id;
private String name;
private byte[] imag;
private String desc;
public Course(){}
public Course(int Id, String Name, byte[] image, String description){
this.id = Id;
this.name = Name;
this.imag = image;
this.desc = description;
}
public int getID(){
return id;
}
public void setID(int ID){
this.id = ID;
}
public String getName(){
return name;
}
public void setName(String Name){
this.name = Name;
}
public byte[] getImage(){
return imag;
}
public String getDesc(){
return desc;
}
public void setDesc(String Description){
this.desc = Description;
}
}
MainQuery.java
package my.welcomescreen;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
public class MainQuery {
public ArrayList<Course> BindTable(){
ArrayList<Course> list = new ArrayList<Course>();
db databaseCon = new db();
Connection dbconnect = db.dbconnect();
Connection con = databaseCon.dbconnect();
Statement st;
ResultSet rs;
try{
st = con.createStatement();
String sql = "select id,name,img,description from courses";
rs = st.executeQuery(sql);
Course c;
while(rs.next()){
c = new Course(
rs.getInt("id"),
rs.getString("name"),
rs.getBytes("img"),
rs.getString("description")
);
}
} catch (SQLException ex) {
Logger.getLogger(Admin_Panel.class.getName()).log(Level.SEVERE, null, ex);
}
return list;
}
}
TheModel.java
package my.welcomescreen;
import javax.swing.Icon;
import javax.swing.table.AbstractTableModel;
public class TheModel extends AbstractTableModel {
private String[] columns;
private Object[] rows;
public TheModel(){}
public TheModel(Object[][] data, String[] columnName){
this.rows = data;
this.columns = columnName;
}
public Class getColumnClass(int Column){
if(Column == 2){
return Icon.class;
} else {
return getValueAt(0,Column).getClass();
}
}
public int getRowCount() {
return this.rows.length;
}
public int getColumnCount() {
return this.columns.length;
}
public Object getValueAt(int rowIndex, int columnIndex) {
return this.rows[rowIndex][columnIndex]; //this is the error line : array required but object found
}
public String getColumnName(int col){
return this.columns[col];
}
}
Main Method
public void displayJTable(){
MainQuery mq = new MainQuery();
ArrayList<Course> list = mq.BindTable();
String[] columnName = {"Id","Course Name","Image","Description"};
Object[][] rows = new Object[list.size()][3];
for(int i = 0; i < list.size(); i++){
rows[i][0] = list.get(i).getID();
rows[i][1] = list.get(i).getName();
if(list.get(i).getImage() != null){
ImageIcon image = new ImageIcon(new ImageIcon(list.get(i).getImage()).getImage()
.getScaledInstance(150, 120, Image.SCALE_SMOOTH) );
rows[i][2] = image;
}
rows[i][3] = list.get(i).getDesc();
}
TheModel model = new TheModel(rows, columnName);
jTable1.setModel(model);
jTable1.setRowHeight(120);
jTable1.getColumnModel().getColumn(3).setPreferredWidth(150);
}
In TheModel, it should be
public class TheModel extends AbstractTableModel {
private String[] columns;
private Object[][] rows; //since data is 2 dimensional array
..//rest of code
}
rows is an Object array in your case, but you need an array of arrays of Objects
Object[] -> Object[][]
Your TableModel is wrong. Don't:
Use an Array to hold the Course objects, because you don't know how big to make the Array to hold all the objects.
Use a 2D Array as a parameter to construct the class.
Instead:
Use an ArrayList to hold the Course objects. The ArrayList size will increase automatically as more space is needed to hold all the objects.
Pass in the ArrayList as a parameter when you create the model.
See Row Table Model for a step by step example on how to create a custom TableModel for a custom Object.
Related
I'm making an java simple app for better code learning that combine some gui on intellji.
I already have a main page and I'm just trying to make a popup Table That have all the data on my product this is my tableView CODE:
public class ProductTable extends JFrame
{
private Model.product product;
private List<product> list;
public ProductTable() {
list = product.ProductList();
// headers for the table
String[] columns = {"Product Name",
"Quantity",
"Expiration day",
"Need fridge"};
Object[][] data = new Object[][] {
};
// create table with data
JTable table = new JTable(data, columns);
// add the table to the frame
this.add(new JScrollPane(table));
this.setTitle("ProductList");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ProductTable();
}
});
}
}
In the Product class I have:
product.name = String
product.quantity = int
Product.Expiration_day = String
product.fridge = boolean
I want to load into the String Object
Data={ {product.name, product.quantity, Product.Expiration_day, Product.fridge} ,{.....,....,....,...}{..............}};
till i put in all off my data now i know how to know the size but i need load it one by one into the data object please can anyone guide through it?!
My Product code:
package Model;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class product
{
private String product_name;
private Integer product_quantity;
private String experation_day;
private boolean fridge = false;
private boolean matched= false;
private Connection connection;
public product()
{
this.product_name = "";
this.product_quantity = 0;
this.experation_day = "";
}
public product(String product_name, Integer product_quantity, String experation_day) {
this.product_name = product_name;
this.product_quantity = product_quantity;
this.experation_day = experation_day;
}
public Integer getProduct_quantity() {
return product_quantity;
}
public String getExperation_day() {
return experation_day;
}
public String getProduct_name()
{
return product_name;
}
public void setProduct_quantity(Integer product_quantity) {
this.product_quantity = product_quantity;
}
public void setExperation_day(String experation_day) {
this.experation_day = experation_day;
}
public void setProduct_name(String product_name)
{
this.product_name = product_name;
}
public List<product> ProductList() {
String windownsUserName = System.getProperty("user.name");
try
{
System.out.println("Connecting to a selected database...");
Connection connection = DriverManager.getConnection("jdbc:sqlite:C:\\Users\\"+windownsUserName+"\\IdeaProjects\\Software-engineer-final-project\\untitled\\src\\DButills\\account.db");
System.out.println("Connected database successfully...");
String sqlQuery = "SELECT product_name, product_amount, product_expration_date FROM products";
PreparedStatement ps = connection.prepareStatement(sqlQuery);
ResultSet rs = ps.executeQuery();
{
}
List<product> products = new ArrayList<>();
while (rs.next()) {
product product = new product();
product.setProduct_quantity(rs.getInt("product_amount"));
product.setProduct_name(rs.getString("product_name"));
product.setExperation_day(rs.getString("product_expration_date"));
products.add(product);
}
return products;
} catch (SQLException e) {
System.out.println("Query failed: " + e.getMessage());
return null;
}
}
}
'package viewer;
import Model.product;
import javax.swing.*;
import java.awt.*;
import java.util.List;
public class ProductTable extends JFrame
{
private Model.product product;
private Container c;
private JTable table;
Object[] mdata;
private List<product> list;
String[] columns = {"Product Name", "Quantity", "Expiration day"}; //headers for the table
int i=1;
private Object[][] data = new Object[][] { };
public ProductTable()
{
list=product.ProductList();
while(i<=list.size()) {
mdata = new Object[]{list.get(i).getProduct_name(), list.get(i).getExperation_day(), list.get(i).getProduct_quantity().toString()};
data[0][i]=mdata[0];
data[1][i]=mdata[1];
data[2][i]=mdata[2];
i++;
}
//create table with data
JTable table = new JTable(data, columns);
//add the table to the frame
this.setTitle("ProductList");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
}'
Why do you need String? According to code you provided - what you need is an array Object[][], but filled with values, so simply loop over your product list and fill your data in correct order.
EDIT:
Look at this pseudocode, it should look somehow like this:
String[] columns = {"Product Name",
"Quantity",
"Expiration day",
"Need fridge"};
Object[][] data = new Object[list.size()][columns.length];
int columnCounter = 0;
for(Product product : list) {
data[columnCounter][0] = product.getName();
data[columnCounter][1] = product.getQuantity();
data[columnCounter][2] = product.getExpDay();
data[columnCounter][3] = product.getNeedFridge();
columnCounter++;
}
There is a database (northwind) on my machine and I have to write a code in java so as to extract the data from the table (Customers) stored in the database.
If this was only specific to Customers table then I would have done it but I want to make my code generic so that I can extract data from other tables also by simply giving the name of the table in a string variable.
Please have a look to my code.
Main class
package main;
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import model.TableModel;
import service.DBConnection;
import service.WriteExcel;
public class Main {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
double start = System.nanoTime();
String tableName = "Customers";
Class<?> c = Class.forName(tableName);
Connection conn = new DBConnection().getConnection();
System.out.println("Connection Established");
QueryRunner run = new QueryRunner();
ResultSetHandler<List<TableModel>> resultHandler = new BeanListHandler<TableModel>(c.getClass())
List<TableModel> data = run.query(conn, "SELECT * FROM `" + tableName + "`;",
resultHandler);
WriteExcel we = new WriteExcel(tableName+"_sheet", new File(tableName+".xlsx"));
we.writeMultipleRows(data);
we.writeWorkbookToFile();
System.out.println("File Written Succesfully");
conn.close();
System.out.println("Time Taken: " + (System.nanoTime()-start)/1000000+" ms");
}
}
In the above code, at line 27, If the statement would have been as follows
ResultSetHandler<List<TableModel>> resultHandler = new BeanListHandler<TableModel>(Customers.class);
This is running perfectly, as I said I want this statement to be independent of the table name, making my code more general.
TableModel
package model;
import java.util.List;
public interface TableModel {
public List<String> getObjectAsList();
}
Customers
package model;
import java.util.ArrayList;
import java.util.List;
public class Customers implements TableModel {
private String customerId;
private String companyName;
private String contactName;
private String contactTitle;
private String address;
private String city;
private String region;
private String postalCode;
private String country;
private String phone;
private String fax;
public String getCustomerId() {
return customerId;
}
public void setCustomerId(String customerId) {
this.customerId = customerId;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getContactName() {
return contactName;
}
public void setContactName(String contactName) {
this.contactName = contactName;
}
public String getContactTitle() {
return contactTitle;
}
public void setContactTitle(String contactTitle) {
this.contactTitle = contactTitle;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getFax() {
return fax;
}
public void setFax(String fax) {
this.fax = fax;
}
public List<String> getObjectAsList(){
List<String> fields = new ArrayList<>();
fields.add(customerId);
fields.add(companyName);
fields.add(contactName);
fields.add(contactTitle);
fields.add(address);
fields.add(city);
fields.add(region);
fields.add(postalCode);
fields.add(country);
fields.add(phone);
fields.add(fax);
return fields;
}
#Override
public String toString() {
return "{ CustomerID = "+getCustomerId()+","
+ " CompanyName = "+getCompanyName()+","
+ " ContactName = "+getContactName()+","
+ " ContactTitle = "+getContactTitle()+","
+ " Address = "+getAddress()+","
+ " City = "+getCity()+","
+ " Region = "+getRegion()+","
+ " PostalCode = "+getPostalCode()+","
+ " Country = "+getCountry()+","
+ " Phone = "+getPhone()+","
+ " Fax = "+getFax()+"}";
}
}
I have used DbUtils library for extracting database.
Any further suggestion for enhancing my code is welcomed.
If I understand your question right, you could try something like below.
To query the table, you can use run.query(SQL, ResultHandler).
ResultSetHandler<List<Map<String, Object>>> resultHandler = genericResultHandler();
List<Map<String, Object>> result = null;
// Execute the SQL statement and return the results in a List of
// T objects generated by the BeanListHandler.
try
{
result = run.query(sqlQuery, resultHandler, varargs);
}
catch (SQLException e)
{
e.printStackTrace();
}
result.stream().forEach(System.out::println);
The interesting part here is the private method genericResultHandler. For demonstration purposes, I used a HashMap to store the values and the corresponding cloumn names.
private ResultSetHandler<List<Map<String, Object>>> genericResultHandler()
{
return new ResultSetHandler<List<Map<String, Object>>>()
{
#Override
public List<Map<String, Object>> handle(java.sql.ResultSet rs) throws SQLException
{
List<Map<String, Object>> result = new ArrayList<>();
// Query all rows of the table.
while (rs.next())
{
// Get metadata of the table.
java.sql.ResultSetMetaData meta = rs.getMetaData();
int cols = meta.getColumnCount();
Map<String, Object> data = new HashMap<>();
// For each column store column name and value of the cell into the hashmap.
for (int i = 1; i < cols; i++)
{
String colName = meta.getColumnName(i);
Object value = rs.getObject(colName);
data.put(colName, value);
}
// Add the row to the result list.
result.add(data);
}
return result;
}
};
}
Afterwards some imports I have used:
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
Output would be something like this (for my test table):
{month=JANUARY, temperature=1.6, globalradiation=0.0, monthid=1}
{month=FEBRUARY, temperature=-0.9, globalradiation=0.0, monthid=2}
{month=MARCH, temperature=0.9, globalradiation=0.0, monthid=3}
{month=APRIL, temperature=7.2, globalradiation=0.0, monthid=4}
{month=MAY, temperature=14.1, globalradiation=0.0, monthid=5}
i want to update my database using jtable, table r disply but not update please provide mi solution for it
i am doing following code but it cant update my database and how can fire query for that my database contain id,name,password,email,phone_no
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
public class JtExample extends JFrame {
JTable tbldetails;
DefaultTableModel dtm ;
public int editcol1;
public int editrow;
public JtExample() {
setVisible(true);
setSize(500,500);
setTitle("login Frame");
setLocationRelativeTo(null);
setLayout(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
dtm = new DefaultTableModel(); //dtm consiste row and clonum
String rowheader[] = {"ID","Name" ,"Password", "Email","phn_no"};
dtm.addColumn("ID");
dtm.addColumn("Name");
dtm.addColumn("address");
dtm.addColumn("Email");
dtm.addColumn("phn_no");
dtm.addRow(rowheader);
add();
dtm.addTableModelListener(new TableModelListener ()
{
#Override
public void tableChanged(TableModelEvent arg0) {
int editcol1 =tbldetails.getEditingColumn();
int editrow =tbldetails.getEditingRow();
TableCellEditor tce = tbldetails.getCellEditor(editrow , editcol1);
System.out.println(tce.getCellEditorValue());
}
});
tbldetails = new JTable(dtm);
tbldetails.setBounds(100,100,500,200);
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://Localhost:3306/mydata","root","root");
PreparedStatement ps=con.prepareStatement(" update employee set editcol1=? where editrow=?");
int editcol1 = 0;
String tce = null;
ps.setString(editcol1, tce);
int i=ps.executeUpdate();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
add(tbldetails);
}
public void add()
{
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://Localhost:3306/mydata","root","root");
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select *from employee");
while(rs.next())
{
dtm.addRow(new Object[]{rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5)});
}
con.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void main(String args[])
{
new JtExample();
}
}
public static void main(String args[])
{
new JtExample();
}
}
Note: There is more then one way to skin this cat
My first thought is, don't use a DefaultTableModel, instead, use a AbstractTableModel, this will give you greater control of the model and changes to its state.
Start by defining a Plain Old Java Object (POJO) which represents your data. Personally I prefer to start with an interface, this allows me to define mutable and non-mutable versions depending on my requirements
Something like...
public class Employee {
private String id; //??
private String name;
private String password; // Probably should be a char[]
private String email;
private String phoneNumber;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public Employee(String id, String name, String password, String email, String phoneNumber) {
this.id = id;
this.name = name;
this.password = password;
this.email = email;
this.phoneNumber = phoneNumber;
}
}
...for example
Next, you need to define a TableModel which is capable of supporting this data...
public class EmployeeTableModel extends AbstractTableModel {
private String columnNames[] = {"ID","Name" ,"Password", "Email","phn_no"};
private List<Employee> employees;
public EmployeeTableModel() {
employees = new ArrayList<Employee>(25);
}
public EmployeeTableModel(List<Employee> employees) {
this.employees = employees;
}
public void add(Employee employee) {
employees.add(employee);
fireTableRowsInserted(employees.size() - 1, employees.size() - 1);
}
public void remove(Employee employee) {
int index = employees.indexOf(employee);
employees.remove(employee);
fireTableRowsDeleted(index, index);
}
#Override
public int getRowCount() {
return employees.size();
}
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public String getColumnName(int column) {
return columnNames[column];
}
public Employee getEmployeeAt(int row) {
return employees.get(row);
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return String.class;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Employee emp = getEmployeeAt(rowIndex);
Object value = null;
switch (columnIndex) {
case 0:
value = emp.getId();
break;
case 1:
value = emp.getName();
break;
case 2:
value = emp.getPassword();
break;
case 3:
value = emp.getEmail();
break;
case 4:
value = emp.getPhoneNumber();
break;
}
return value;
}
}
We're going to add to this later, but for now, this gives us the basics we need...
When you load the data from the database, you could use something like...
EmployeeTableModel model = new EmployeeTableModel();
try (ResultSet rs = st.executeQuery("select *from employee")) {
while(rs.next())
{
model.add(new Employee(
rs.getString(1),
rs.getString(2),
rs.getString(3),
rs.getString(4),
rs.getString(5)));
}
} finally {
tbldetails.setModel(model);
}
So, now we have a self contained unit of work, in our Employee class, a TabelModel which can support it and a means by which you can load the data, now, you need some way to intercept the changes to the data and update the database.
To this end, we're going to update the EmployeeTableModel
public class EmployeeTableModel extends AbstractTableModel {
//...
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex > 0; // id should not be editable here...
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
Employee emp = getEmployeeAt(rowIndex);
switch (columnIndex) {
case 1:
emp.setName(aValue.toString());
break;
case 2:
emp.setPassword(aValue.toString());
break;
case 3:
emp.setEmail(aValue.toString());
break;
case 4:
emp.setPhoneNumber(aValue.toString());
break;
}
update(emp);
fireTableCellUpdated(rowIndex, columnIndex);
}
This will call the update method every time a cell is updated. To this, we pass the Employee object. Based on the value of the id property, you will either need to update or insert a new record.
This is a very simple example, because of the nature of JDBC, the JDBC call could take a period of time to execute. I might be tempted to have some kind of (blocking) queue, onto which I could add Employee objects.
This queue would be processed by another Thread (or SwingWorker or some such), which would pop off the next object and process it, triggering an event callback (to which the TableModel would be listening) with the updated data. The TableModel would then be able to update itself accordingly...
Another idea is to simply have a "save" button, which the user can click. You would then simply iterate through the list of Employees and update them. For this, I would have a simple boolean flag for each object, which would be set to true whenever any of the set methods are called
public class Employee {
private boolean changed = false;
public boolean hasChanged() {
return changed;
}
public void setName(String name) {
this.name = name;
changed = true;
}
Take a closer look at How to Use Tables for moe details
I want to create a JTable which "Analysis","Date" and "Price" the names of columns.
The value of Analysis and Price are recovered from the data base in my Database and the Date get the value of the current day.
I have created a class MyModel as the following :
package com.pack.classes;
import java.util.LinkedList;
import javax.swing.table.AbstractTableModel;
import com.pack.beans.MyElement;
#SuppressWarnings("serial")
public class MyModel extends AbstractTableModel {
public static final String[] columnNames = {"Analyse", "Date d'analyse","Prix"};
private final LinkedList<MyElement> list;
public MyModel() {
list = new LinkedList<MyElement>();
}
public void addElement(MyElement e) {
// Adds the element in the last position in the list
list.add(e);
fireTableRowsInserted(list.size()-1, list.size()-1);
}
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public int getRowCount() {
return list.size();
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
switch(columnIndex) {
case 0: return list.get(rowIndex).getAnalysis();
case 1: return list.get(rowIndex).getDate();
case 2: return list.get(rowIndex).getPrice();
}
return null;
}
}
And i create a Bean MyElement as the following :
package com.pack.beans;
import java.util.Date;
public class MyElement {
String analysis;
Date date;
Double price;
public String getAnalysis() {
return analysis;
}
public void setAnalysis(String analysis) {
this.analysis = analysis;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}
Here is a piece of my code which this class is used :
String sql = "Select name,number_b from analysis_tab where name ='" + idclicked + "'";
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
Date date = new Date();
System.out.println(dateFormat.format(date));
PreparedStatement preparestate = database.con.prepareStatement(sql);
ResultSet rs = preparestate.executeQuery();
MyModel mymodel = new MyModel();
String [] value = mymodel.columnNames;
MyElement e = new MyElement();
//e.setAnalysis(name);
e.setDate(date);
//e.setPrice("number_b");
As a result i obtain a Table with 3 coloumn "A","B" and "C".I don't know hence these name comes!!!
Should you tell me how can i put my columns names "Analyse", "Date d'analyse","Prix" as a header in my Table?Am I on the right path??
Why don't you use the DefaultTableModel?
It is powerful than using only jtable.
// insert column name
defaultTableModel.setColumnIdentifiers(new String[]{"Analyse", "Date d'analyse","Prix"});
And.. Your sql is statement type! If you can, change sql style like below.
String sql = "Select name,number_b from analysis_tab where name ='" + idclicked + "'";
=>
String sql = "Select name,number_b from analysis_tab where name = ?"
PreparedStatement preparestate = database.con.prepareStatement(sql);
pstmt.setString(1, idclicked);
rs = pstmt.executeQuery();
Check the "PreparedStatement" and "Statement"! :)
What is the proper relationship, in code, between a table model and the actual database queries?
Inside the addRow() method in the table model, should I place a further call to my database class, which in turn inserts the row into the database? I've illustrated this in the below code snippets.
public class MainPanel extends JPanel
{
...
public MainPanel()
{
personTableModel = new PersonTableModel();
personTable = new JTable(personTableModel);
...
insertButton = new JButton("Insert");
insertButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
String name = nameTextBox.getText();
String address = addressTextBox.getText();
Object[] row = { name, address };
personTableModel.addRow(row); // <--- Add row to model
}
});
}
}
public class PersonTableModel extends AbstractTableModel
{
private List<Object[]> data;
private List<String> columnNames;
PersonDB personDB = new PersonDB();
...
public void addRow(Object[] row)
{
// insert row into 'data'
personDB.addPerson(row); // <---- Call the personDB database class
}
...
}
public class PersonDB
{
public PersonDB()
{
// establish database connection
}
public addPerson(Object[] row)
{
// code that creates a SQL statement based on row data
// and inserts new row into database.
}
...
}
Whether or not you should directly make an insert call depends on some aspects:
Do you want other processes to access the data immediately?
Do you fear that your program crashes and you lose important information?
Can you ensure that any data persisted during addRow is meaningful (the program could terminate directly after the insert)?
Than of course it may be a good idea to directly insert the data into the backing Database.
You should however watch out, that there are two variants of addRow and two variants of insertRow. DefaultTableModel directs calls internally through insertRow(int, Vector), which would probably be the only function to overwrite, if you want to immediately persist data.
If you like the proposed idea of DTOs the examples below may help you.
The Idea is to represent "Entities" or table rows as classes in Java. A DTO is the simplest representation and normally only contains fields with respective getter and setter.
Entities can generically be persisted and loaded through ORM libraries like EclipseLink or Hibernate. Additionally for this table-application the use of DTOs provide a way of storing data not shown to the user in a clean and typed way.
DTO:
public class PersonDto {
private Long id;
private String name;
private String street;
public PersonDto() {
}
public PersonDto(Long id, String name, String street) {
this.id = id;
this.name = name;
this.street = street;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public static class NameColumn extends DtoTableModel.ColumnProvider<PersonDto, String> {
public NameColumn() {
super("Name", String.class);
}
#Override
public String getValue(PersonDto dto) {
return dto.getName();
}
#Override
public void setValue(PersonDto dto, Object value) {
dto.setName((String) value);
}
}
public static class StreetColumn extends DtoTableModel.ColumnProvider<PersonDto, String> {
public StreetColumn() {
super("Street", String.class);
}
#Override
public String getValue(PersonDto dto) {
return dto.getStreet();
}
#Override
public void setValue(PersonDto dto, Object value) {
dto.setStreet((String) value);
}
}
}
DTO based TableModel:
import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
public class DtoTableModel<T> extends AbstractTableModel {
private final ArrayList<T> rows;
private final ArrayList<ColumnProvider<T, ?>> columns;
protected DtoTableModel() {
rows = new ArrayList<T>();
columns = new ArrayList<ColumnProvider<T, ?>>();
}
#Override
public int getRowCount() {
return rows.size();
}
#Override
public int getColumnCount() {
return columns.size();
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return columns.get(columnIndex).getValue(rows.get(rowIndex));
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
final ColumnProvider<T, ?> column = columns.get(columnIndex);
column.setValue(rows.get(rowIndex), aValue);
this.fireTableCellUpdated(rowIndex, columnIndex);
}
#Override
public String getColumnName(int column) {
return columns.get(column).getTitle();
}
public void addColumn(ColumnProvider<T, ?> column) {
this.columns.add(column);
this.fireTableStructureChanged();
}
public void addRow(T row) {
this.rows.add(row);
this.fireTableRowsInserted(this.rows.size() - 1, this.rows.size() - 1);
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return this.columns.get(columnIndex).getValueClass();
}
public static abstract class ColumnProvider<T, V> {
private String title;
private final Class<V> valueClass;
protected ColumnProvider(String title, Class<V> valueClass) {
this.title = title;
this.valueClass = valueClass;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Class<V> getValueClass() {
return valueClass;
}
public abstract V getValue(T dto);
public abstract void setValue(T dto, Object value);
}
}
Example-"Application":
import javax.swing.*;
import java.awt.*;
public class JTableTest extends JFrame {
private final JTable jTable;
public JTableTest() throws HeadlessException {
super("JFrame test");
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
final GridBagLayout layout = new GridBagLayout();
final Container contentPane = this.getContentPane();
contentPane.setLayout(layout);
final GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.fill = GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
final DtoTableModel<PersonDto> dm = new DtoTableModel<PersonDto>();
jTable = new JTable(dm);
dm.addColumn(new PersonDto.NameColumn());
dm.addColumn(new PersonDto.StreetColumn());
dm.addRow(new PersonDto(1L, "Paul", "Mayfairy Street"));
dm.addRow(new PersonDto(2L, "Peter", "Ferdinand Street"));
JScrollPane scrollpane = new JScrollPane(jTable);
contentPane.add(scrollpane, gridBagConstraints);
this.pack();
}
public static void main(String[] args) {
final JTableTest jTableTest = new JTableTest();
jTableTest.setVisible(true);
}
}