I'm working on a Java database application, where the user has one side to insert data and another to show in a JTable (in a JScrollPane) the content of the linked HSQLDB database. Everthing works so far so good, but I searched for a very long time without finding how to update my JTable dynamically when a change is made to the database (add, update or delete) for each instance of my program because several persons can work on it simultaneously.
It actually works by replacing my table model for local update, but for other instances, i have set a Timer which is not very clean.
Could you help me resolving this please ?
Here is my code (I have an Interface.java for "visible" part and a SQL.java to manage my db) :
My timer
JTable table = new JTable(sql.showTable("SELECT * FROM suivi_flotte"));
Timer timer = new Timer(900000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
sql.updateTable();
nbLinesOrRefresh.setText("Actualisation...");
Timer timer2 = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
nbLinesOrRefresh.setText("");
}
});
timer2.start();
timer2.setRepeats(false);
}
});
timer.setDelay(900000);
timer.start();
formatTable(table);
My updateTable() method (called each time there is an insert, update or delete)
protected void updateTable() {
Interface.f.table.setModel(showTable("SELECT * FROM suivi_flotte"));
Interface.f.formatTable(Interface.f.table); // a method to custom JTable appearance
}
My showTable(String query) method
protected DefaultTableModel showTable(String query) {
String[] columnsTitles = {"N°", "Propriétaire", "Service", "Grade", "Nom", "Prénom", "Mail", "N° SIM", "N° Tél", "Modèle", "N° Série", "IMEI", "N° Crypto", "Date début", "Date fin", "DS", "Commentaire", "Date de création"};
ArrayList<String> columnNames = new ArrayList<>();
ArrayList<Object> data = new ArrayList<>();
connectDB(); // only to connect to db
try (ResultSet rs = stmt.executeQuery(query)) {
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
for (int i = 1; i <= columns; i++) {
columnNames.add(columnsTitles[i - 1]);
}
while (rs.next()) {
ArrayList<Object> row = new ArrayList<>(columns);
for (int i = 1; i <= columns; i++) {
row.add(rs.getObject(i));
}
data.add(row);
}
shutdownDB(); // to fully disconnect from db
} catch (SQLException e) {
System.out.println(e.getMessage());
}
Vector<Vector<?>> dataVector = new Vector<>();
Vector<String> columnNamesVector = new Vector<>();
for (int i = 0; i < data.size(); i++) {
ArrayList<?> subArray = (ArrayList<?>) data.get(i);
Vector<Object> subVector = new Vector<>();
for (int j = 0; j < subArray.size(); j++) {
subVector.add(subArray.get(j));
}
dataVector.add(subVector);
}
for (int i = 0; i < columnNames.size(); i++) {
columnNamesVector.add(columnNames.get(i));
}
DefaultTableModel tModel = new DefaultTableModel(dataVector, columnNamesVector) {
private static final long serialVersionUID = 1L;
public Class<?> getColumnClass(int column) {
for (int row = 0; row < getRowCount(); row++) {
Object o = getValueAt(row, column);
if (o != null) {
return o.getClass();
}
}
return Object.class;
}
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
// tModel.fireTableDataChanged(); // <-- does not work
return tModel;
}
Thank you for your help.
UPDATE 1 :
All my connection/disconnection code :
private void connectDB() {
JFrame op = new JFrame();
op.setAlwaysOnTop(true);
try {
Class.forName("org.hsqldb.jdbcDriver");
co = DriverManager.getConnection("jdbc:hsqldb:file:db;shutdown=true");
stmt = co.createStatement();
} catch (SQLException | ClassNotFoundException e) {
JOptionPane.showMessageDialog(op, "Erreur de connexion à la base de données :\n" + e.getMessage(), Interface.windowTitle, JOptionPane.ERROR_MESSAGE);
}
}
private void openDB() throws IOException {
try {
BufferedReader br = new BufferedReader(new FileReader("db.sql"));
String line;
StringBuffer sb = new StringBuffer();
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
stmt.executeUpdate(sb.toString());
} catch (SQLException e) {}
}
private void shutdownDB() throws SQLException {
stmt.close();
co.close();
}
UPDATE 2 :
I changed everything in SQL.java to non-static. Each SQL.[...] has been changed to sql.[...] with private SQL sql = new SQL(); on top of the class and public SQL() {} in the class. I also changed it in the above code.
Related
I have successfully fetched data from database into JTable. But I'm having a little trouble to populate in JComboBox and then add it to JTable. Like I have stored ArrayList in String format in Documents Column. Now, I want a JComboBox in each row of Documents Column using that ArrayList in JTable.
Basically, replacing ArrayList String to JComboBox with that Array items.
In the documents column, the data is in form of array string:
Jtable Code:
private static final DatabaseConnections databaseConnections = new DatabaseConnections();
private Thread thread;
Vector<Object> columnNames = new Vector<Object>();
Vector<Object> data = new Vector<Object>();
public ConnectionRecordsPanel() {
initComponents();
SetData();
}
private void SetData(){
columnNames.addElement("Customer Id");
columnNames.addElement("Name");
columnNames.addElement("DOB");
columnNames.addElement("Gender");
columnNames.addElement("Current Address");
columnNames.addElement("Permanent Address");
columnNames.addElement("Mobile Number");
columnNames.addElement("Email Id");
columnNames.addElement("Documents");
columnNames.addElement("Gas Type");
columnNames.addElement("Status");
thread = new Thread(new Runnable() {
#Override
public void run() {
try {
System.out.println("Inside run");
data = databaseConnections.getData(data);
System.out.println("Inside run");
DefaultTableModel model = new DefaultTableModel(data, columnNames)
{
#Override
public Class getColumnClass(int column)
{
for (int row = 0; row < getRowCount(); row++)
{
Object o = getValueAt(row, column);
if (o != null)
{
return o.getClass();
}
}
return Object.class;
}
};
jTable1.setModel(model);
JComboBox jcb = new JComboBox();
jTable1.getColumnModel().getColumn(9).setCellEditor(new DefaultCellEditor(jcb));
} catch (ParseException ex) {
Logger.getLogger(ConnectionRecordsPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
thread.start();
}
Reading from Database
public Vector getData(Vector data) throws ParseException{
try {
resultSet = statement.executeQuery("select * from connection_records");
while (resultSet.next()){
Vector<Object> row = new Vector<Object>();
for (int i = 1; i <= 11 ; i++)
{
row.addElement(resultSet.getString(i));
}
data.addElement( row );
}
} catch (SQLException ex) {
Logger.getLogger(DatabaseConnections.class.getName()).log(Level.SEVERE, null, ex);
}
return data;
}
I wnat to fill my Table with new Datas which i get by my DataBase(MySQL). I get all datas and create a new Model with them, but if i want to refresh the specific panel, then it wont be repainted.
public class PanelWest extends JPanel implements ActionListener {
private JButton but_selectBP;
private JButton but_selectBPAdr;
private JButton but_selectGerichte;
private GroupLayout layoutGroup;
private Connector stmtExecuter = new Connector();
// private PanelCenter tableViewer = new PanelCenter();
public PanelWest() {
layoutGroup = createLayout();
this.setLayout(layoutGroup);
createButtons();
}
private GroupLayout createLayout() {
GroupLayout layout = new GroupLayout(this);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
return layout;
}
void createButtons() {
this.but_selectBP = new JButton("Kunden anzeigen");
this.but_selectBP.addActionListener(this);
this.but_selectBPAdr = new JButton("Gerichte anzeigen");
this.but_selectBPAdr.addActionListener(this);
this.but_selectGerichte = new JButton("Lieferanten anzeigen");
this.but_selectGerichte.addActionListener(this);
this.layoutGroup.setHorizontalGroup(layoutGroup.createParallelGroup().addComponent(but_selectBP).addComponent(but_selectBPAdr).addComponent(but_selectGerichte));
this.layoutGroup.setVerticalGroup(layoutGroup.createSequentialGroup().addComponent(but_selectBP).addComponent(but_selectBPAdr).addComponent(but_selectGerichte));
}
#Override
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
if (src.equals(this.but_selectBP)) {
String query = "SELECT * FROM Kunde";
ResultSet rst = this.stmtExecuter.getResultDBData(query);
// this.tableViewer.setTableName("Kunde");
new PanelCenter().createTable(fillHeader(rst), fillData(rst));
}
if (src.equals(this.but_selectBPAdr)) {
String query = "SELECT * FROM Gericht";
ResultSet rst = this.stmtExecuter.getResultDBData(query);
// this.tableViewer.createTable(fillHeader(rst), fillData(rst));
}
if (src.equals(this.but_selectGerichte)) {
String query = "SELECT * FROM Lieferant";
ResultSet rst = this.stmtExecuter.getResultDBData(query);
// this.tableViewer.createTable(fillHeader(rst), fillData(rst));
}
}
private String[] fillHeader(ResultSet rst) {
try {
ResultSetMetaData rstMetaData = rst.getMetaData();
String[] header = new String[rstMetaData.getColumnCount()];
ArrayList<String> headerDetails = new ArrayList<>();
for (int i = 1; i <= rstMetaData.getColumnCount(); i++) {
headerDetails.add(rstMetaData.getColumnName(i));
}
int j = 0;
for(String head : headerDetails){
header[j] = head;
j++;
}
return header;
} catch (SQLException se) {
se.printStackTrace();
}
return null;
}
private Object[][] fillData(ResultSet rst) {
try {
ResultSetMetaData rstMetaData = rst.getMetaData();
int rowCount = 0;
rst.last();
rowCount = rst.getRow();
System.out.println(rowCount + " Rows");
rst.beforeFirst();
Object[][] data = new Object[rowCount][rstMetaData.getColumnCount()];
int row = 0;
while (rst.next()) {
for (int i = 0; i < rstMetaData.getColumnCount(); i++) {
data[row][i] = rst.getObject(i + 1);
}
row++;
}
return data;
} catch (SQLException se) {
System.out.println("Hier bei Fill");
}
return null;
}
}
I use remove, add revalidate and repaint on my jpanel.
void createTable(String[] header, Object[][] data) {
this.tableData = new JTable();
this.tableData.setModel(new MyTableModel(header, data));
this.tableData.setFillsViewportHeight(true);
this.tableData.addKeyListener(this);
this.scrollPaneTable = new JScrollPane(tableData);
this.scrollPaneTable.setSize(500, 500);
this.remove(this.scrollPaneTable);
this.add(this.scrollPaneTable);
this.revalidate();
this.repaint();
}
You don't need to reinitialize the table, table model.
Put some global variables on the top
private MyTableModel tableModel; //Your own table model
private JTable table;
Initialize them on init
public PanelWest() {
layoutGroup = createLayout();
this.setLayout(layoutGroup);
createButtons();
tableModel = new MyTableModel(header, data); //Your own tablemodel
table = new JTable(tableModel); //Hook the model to your table
this.add(table)
//...Do other things else to your table
}
Once you want to update the table, simply clear the rows from the table model and fill with new rows.
And ask JTable to update its data by calling
void createTable(String[] header, Object[][] data){
int cols = header.length;
int rows = data.length;
//Remove all rows from model
tableModel.setRowCount(0); //(As said by HovercraftFullOfEels)
Object[] row = new Object[cols];
for (int j = 0; j < data.length; j++){
for (int i = 0; i < cols; i++){
row[i] = data[j][i];
}
tableModel.addRow(row);
}
tableModel.fireTableDataChanged();
}
Hope it will help.
Thanks for your help.
I add a small test to my createTable method. I create a new window to show the new table datas and it works. i think my jpanel doesn't repaint correctly cause my grouplayout.
this.tableData = new JTable();
this.tableData.setModel(new MyTableModel(header, data));
this.tableData.setFillsViewportHeight(true);
this.tableData.addKeyListener(this);
this.scrollPaneTable = new JScrollPane(tableData);
this.scrollPaneTable.setSize(500, 500);
this.layoutGroup.setVerticalGroup(layoutGroup.createSequentialGroup().addComponent(this.scrollPaneTable, 400, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(this.scrollPaneChanges).addComponent(this.but_user).addComponent(this.but_dataChange));
// JFrame fr = new JFrame("Hello");
// fr.setLayout(null);
// fr.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// fr.setVisible(true);
// fr.add(this.scrollPaneTable);
I'm making a simple program that show the teams, the matches and racking goal of Euro2016 in France.
I have some problem with JTable when changing query.
Here is what happens:
when I change from a Table of (for example) 10 rows to another one that contains only 5 rows it works. But if I change from a table that contains 5 rows to another of 10, the table doesn't change, it displays only 5 rows.
Here the code:
public class Euro2016GUI extends JFrame {
private Container container;
private Sfondo pnlSfondo;
JTable table;
JPanel panel;
static Vector<Vector<String>> data = new Vector<Vector<String>>();
static Vector<String> headers = new Vector<String>();
public Euro2016GUI() {
data.removeAll(data);
headers.removeAll(headers);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(600, 400);
this.setTitle("Euro2016");
this.setLocationRelativeTo(null);
pnlSfondo = new Sfondo();
container = this.getContentPane();
container.add(pnlSfondo);
}
public void createTable(String pQuery) {
data.removeAll(data);
headers.removeAll(headers);
Control control = new Control();
panel = new JPanel(new BorderLayout());
panel.setSize(300, 300);
panel.setBackground(Color.red);
control.getData(pQuery);
data = control.getData();
headers = control.getHeaders();
//this is the model which contain actual body of JTable
DefaultTableModel model = new DefaultTableModel(data, headers);
table = new JTable(model);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setEnabled(false);
table.setMaximumSize(new Dimension(100, 300));
header_size();
JScrollPane scroll = new JScrollPane(table);
//scroll.setSize(600, 400);
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
this.getContentPane().add(panel);
panel.add(scroll, BorderLayout.CENTER);
}
public void header_size() {
int colonne = table.getColumnModel().getColumnCount();
TableColumn column;
for (int i = 0; i < colonne; i++) {
column = table.getColumnModel().getColumn(i);
column.setPreferredWidth(200);
}
}
public void cleanData() {
if (table != null) {
DefaultTableModel dm = (DefaultTableModel) table.getModel();
dm.setRowCount(0);
table.revalidate();
}
data.removeAll(data);
headers.removeAll(headers);
}
}
CLASS CONTROL
public class Control {
private static Vector<Vector<String>> data = new Vector<Vector<String>>();
private static Vector<String> headers = new Vector<String>();
public void getData(String pQuery) {
// Enter Your MySQL Database Table name in below Select Query.
String query = pQuery;
Connection con = null;
ResultSet rs;
Statement st = null;
int colonne = 0;
data.removeAll(data);
headers.removeAll(headers);
try {
con = DBConnectionPool.getConnection();
st = con.createStatement();
rs = st.executeQuery(query);
ResultSetMetaData rsmd = rs.getMetaData();
colonne = rsmd.getColumnCount();
for (int i = 1; i <= colonne; i++) {
headers.add(rsmd.getColumnName(i));
}
while (rs.next()) {
Vector<String> d = new Vector<String>();
for (int i = 1; i <= colonne; i++) {
d.add(rs.getString(i));
}
data.add(d);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (st != null) {
try {
st.close();
} catch (SQLException ex) {
Logger.getLogger(DataInJTable.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (con != null) {
DBConnectionPool.releaseConnection(con);
}
}
}
public Vector<Vector<String>> getData() {
return this.data;
}
public Vector<String> getHeaders() {
return this.headers;
}
}
HERE THE ACTION LISTENER IN THE MENU:
...
//----ROSE---//
private class OnClickRose implements ActionListener {
Sfondo sfondo;
#Override
public void actionPerformed(ActionEvent e) {
String str = e.getActionCommand();
str = str.replace("[", "");
str = str.replace("]", "");
String sx = "'";
String dx = "'";
String query = query2.concat(sx.concat(str.concat(dx)));
//frame.cleanData();
sfondo = frame.getPnlSfondo();
if (sfondo.isVisible() && sfondo.getParent().isVisible()) {
sfondo.setVisible(false);
}
frame.createTable(query);
}
}
//----CALENDARIO----//
private class OnClickCalendario implements ActionListener {
Sfondo sfondo;
#Override
public void actionPerformed(ActionEvent e) {
frame.cleanData();
sfondo = frame.getPnlSfondo();
if (sfondo.isVisible() && sfondo.getParent().isVisible()) {
sfondo.setVisible(false);
}
frame.createTable(query4);
}
}
//----CLASSIFICA MARCATORI----//
private class OnClickMarcatori implements ActionListener {
Sfondo sfondo;
#Override
public void actionPerformed(ActionEvent e) {
frame.cleanData();
sfondo = frame.getPnlSfondo();
if (sfondo.isVisible() && sfondo.getParent().isVisible()) {
sfondo.setVisible(false);
}
frame.createTable(query3);
}
}
...
Could anybody tell me where I wrong?
Basically to tell the table to refresh itself, you just call the method fireTableDataChanged() of it's table model.
So in your example, after you run the query, you could just call:
((DefaultTableModel)yourTable.getModel()).fireTableDataChanged();
But I suggest you to stop using default table model, and implement your own table model. It's a lot easier to work.
I have the following cod!
when i call the fruitsTable() from refreshButton() it refreshes the JTable! but when i call it from another class it does not refresh the Table! bellow is the simplified code
public ResultSet sqlCommand(String sqlStatement) throws SQLException
{
this.sqlStatement = sqlStatement;
ConnectingToMysql fruitsConnection = new ConnectingToMysql();
Connection myConnection = fruitsConnection.ConnectingToMysql();
Statement st = myConnection.createStatement();
ResultSet result = st.executeQuery(sqlStatement);
return result;
}
public Vector<String> getColumnData() throws SQLException
{
ResultSetMetaData metaData = sqlCommand(sqlStatement).getMetaData();
int columnCount = metaData.getColumnCount();
Vector<String> allColumn = new Vector<String>();
for(int i = 1; i <= columnCount; i++)
{
allColumn.add(metaData.getColumnName(i));
}
return allColumn;
}
public Vector<Vector<String>> getData() throws SQLException
{
ResultSet result = sqlCommand(sqlStatement);
ResultSetMetaData metaData = result.getMetaData();
int columnCount = metaData.getColumnCount();
Vector<Vector<String>> allRow = new Vector<Vector<String>>(columnCount);
while(result.next())
{
Vector<String> eachRow = new Vector<String>();
for(int i = 1; i <= columnCount; i++)
{
eachRow.add(result.getString(i));
}
allRow.add(eachRow);
}
return allRow;
}
public JScrollPane fruitsTable() throws SQLException
{
Vector<String> columnData = getColumnData();
Vector<Vector<String>> rowData = getData();
fruitsTableModel.setDataVector(rowData,columnData);
Font font = new Font("Courier", Font.PLAIN,16);
fruitsTable = new JTable();
fruitsTable.setModel(fruitsTableModel);
fruitsTable.setPreferredScrollableViewportSize(new Dimension(850,310));
fruitsTable.setRowHeight(30);
fruitsTable.setFont(font);
JScrollPane fruitsScrollPane = new JScrollPane(fruitsTable);
dataValue();
return fruitsScrollPane;
}
private JButton refreshButton() throws SQLException
{
JButton refreshButton = new JButton("Refresh Record");
refreshButton.setPreferredSize(new Dimension(100,40));
refreshButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
fruitsTable();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
return refreshButton;
}
and this is the only code from the other class that calls the fruitsTable().
saveButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
try
{
String number = numberTextField.getText();
int ID = Integer.parseInt(number);
String fruit = fruitTextField.getText();
String color = colorTextField.getText();
String taste = tasteTextField.getText();
System.out.println("The value is: " + number + " " + fruit + " " + color + " " + taste);
String sqlText = "Insert into fruits(ID,Fruit,Color,Tast) values(?,?,?,?)";
ConnectingToMysql connectingToMysql = new ConnectingToMysql();
Connection makeConnection = connectingToMysql.ConnectingToMysql();
PreparedStatement pdt = makeConnection.prepareStatement(sqlText);
pdt.setInt(1,ID);
if(fruit.isEmpty())
{
pdt.setNull(2,java.sql.Types.VARCHAR);
}
else
{
pdt.setString(2,fruit);
}
if(color.isEmpty())
{
pdt.setNull(3,java.sql.Types.VARCHAR);
}
else
{
pdt.setString(3,color);
}
if(taste.isEmpty())
{
pdt.setNull(4,java.sql.Types.VARCHAR);
}
else
{
pdt.setString(4,taste);
}
pdt.executeUpdate();
GetFruits getFruits = new GetFruits();
getFruits.fruitsTable();
}
catch(SQLIntegrityConstraintViolationException e)
{
JOptionPane.showMessageDialog(null, "The 'Number' you entered already exist!", "Error", JOptionPane.ERROR_MESSAGE);
System.out.println(e);
}
GetFruits getFruits = new GetFruits();
getFruits.fruitsTable();
You're creating a new GetFruits object and refreshing it's table instead of updating the existing one. Try creating a class variable of GetFruits so you're using the same instance instead of creating a new one each time. Just guessing since I can't see all the code that contains the action listener.
Reworded this question as it wasn't very clear. My issue is that whenever the generateReport method trys to use model.getColumnCount() its returning zero and giving a ResultSet is Closed error.
However if I remove that finally block, everything works as expected. How do I do this correctly with closing off the connection?
Am I right in thinking that the model only lives within the createTable method as I've used
model = new ResultSetTableModel(rs);
Even though I declared the model as a class variable?
Method that creates the JTable
private void createTable() {
databaseName = (txtQueryDatabase.getText());
String sql = txtQueryString.getText();
openDatabase();
try {
ResultSet rs = stmt.executeQuery(sql);
model = new ResultSetTableModel(rs);
tblEmployee.setModel(model);
txtQueryCount.setText(Integer.toString(model.getRowCount()));
} catch (SQLException e) {
errorMessage(e);
} catch (Exception e) {
errorMessage(e);
} finally {
closeDatabase();
}
The method that writes the file
private void generateReport(File file) throws IOException {
file.createNewFile();
BufferedWriter bfw = new BufferedWriter(new FileWriter(file));
for (int i = 0; i < model.getColumnCount(); i++) {
bfw.write(model.getColumnName(i));
bfw.write(" | ");
}
for (int i = 0; i < model.getRowCount(); i++) {
bfw.newLine();
for (int j = 0; j < model.getColumnCount(); j++) {
bfw.write(model.getValueAt(i, j).toString());
bfw.write(" | ");
}
}
bfw.close();
}
ResultSetTableModel class
public ResultSetTableModel(ResultSet aResultSet) {
try {
rs = aResultSet;
rsmd = rs.getMetaData();
data = new ArrayList<Object>();
while (rs.next()) {
Object[] row = new Object[rsmd.getColumnCount()];
for (int i = 0; i < row.length; i++) {
row[i] = rs.getObject(i + 1);
}
data.add(row);
}
} catch (SQLException e) {
message.errorMessage(e);
}
}
#Override
public Object getValueAt(int row, int col) {
if (row < data.size()) {
return ((Object[]) data.get(row))[col];
} else {
return null;
}
}
#Override
public int getRowCount() {
return data.size();
}
#Override
public String getColumnName(int count) {
try {
return rsmd.getColumnName(++count);
} catch (SQLException e) {
message.errorMessage(e);
return "";
}
}
#Override
public int getColumnCount() {
try {
return rsmd.getColumnCount();
} catch (SQLException e) {
message.errorMessage(e);
return 0;
}
}
}