JAVA update database on JTable cell change - java

He I am noob to Java (Thats not new) and I can't find a good tutorial for this. I use jTable to display a table filled with data from a MySQL database.
So far so good, I get the table:
Standard you can click a table cell and it changes to a text-field with can be filled with something new. You all know that, but how can I use this to also update the value in my database?
My code:
import [...];
public class table extends JPanel {
public String table;
private Database db;
public table(String tablename, Database db){
try {
table = tablename;
this.db = db;
//Get table with and height
ResultSet res = db.query("SELECT COUNT( * ) FROM `"+table+"`");
ResultSet res2 = db.query("SELECT COUNT( * ) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '"+table+"'");
int rows = 0;
int collums = 0;
res.next();
res2.next();
rows = res.getInt(1);
collums = res2.getInt(1);
//Get table column names and set then in array
ResultSet clom = db.query("DESCRIBE `"+table+"`");
String[] columnNames = new String[collums];
int s = 0;
while(clom.next()){
columnNames[s] = clom.getString(1);
s++;
}
//get table data and put in array
Object[][] data = new Object[rows][collums];
ResultSet result = db.query("SELECT * FROM `"+table+"`");
int q = 0;
while(result.next()){
for(int a=0; a<= (collums - 1); a++){
data[q][a] = result.getString(a + 1);
//System.out.println(q + " - " + a);
}
q++;
}
//Make Jtable of the db result form the two array's
final JTable table = new JTable(data, columnNames);
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
table.setFillsViewportHeight(true);
// do some event listening for cell change
JScrollPane scrollPane = new JScrollPane(table);
JFrame frame = new JFrame("table editor");
scrollPane.setOpaque(true);
frame.setContentPane(scrollPane);
frame.pack();
frame.setSize(600, 800);
frame.setVisible(true);
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
I guess I need to bind some kind of table listener and when something changes I take all the values of the table and update them with a query.
How can I do this?
This is my pseudo code:
table.bindCellEventListner(callback(t){
Array row = t.getAllValuesAsArrayOfRow();
String data = "";
int f = 0
while(row.next()){
data .= "`"+clom[f]+"` = '"+row[f]+"',"
f++;
}
data.delLastChar();
db.query("UPDATE `"+table+"` SET "+data+" WHERE `id` ="+row[0]+";");
});

A deleted answer plagiarised Rachel Swailes' answer from 14 years ago, found here. For completeness and because the answer is correct and useful, I have quoted the relevant text here:
Step 1: It's going to be way easier for the whole thing if you make your table extend a TableModel from now (if you haven't already). So if you need help with that just ask.
Step 2: In the table model you need to enable the cells to be editable. In the TableModel class that you make, you need to add these methods
public boolean isCellEditable(int row, int col) {
return true;
}
public void setValueAt(Object value, int row, int col) {
rowData[row][col] = value;
fireTableCellUpdated(row, col);
}
Step 3: You will see in the second method that we fire a method called fireTableCellUpdated. So here we can catch what the use it changing. You need to add a TableModelListener to your table to catch this.
mytable.getModel().addTableModelListener(yourClass);
And in the class that you decide will implement the TableModelListener you need this
public void tableChanged(TableModelEvent e) {
int row = e.getFirstRow();
int column = e.getColumn();
TableModel model = (TableModel)e.getSource();
Object data = model.getValueAt(row, column);
...
}
now you have the data in the cell and the place in the grid where the
cell is so you can use the data as you want

Related

Get Multiple columns in Result Set from sparql in Netbeans JTable

I am trying to select multiple columns in Jena result set and then binding the same to Java table.
When I select only one column, the result set is working fine but when I select two columns then the result set does not have any row although it has only columns:
Here is my Java code:
private void btnExecuteSPARQLActionPerformed(java.awt.event.ActionEvent evt) {
try
{
System.out.println("Executing SPARQL..."); // get the name list query
String queryString;
queryString = "PREFIX ssuet:<http://www.semanticweb.org/alinaanjum2/ontologies/2021/6/untitled-ontology-4#> "
+ txtQuery.getText();
com.hp.hpl.jena.query.ResultSet results = OpenOWL.ExecSparQl(queryString); //all method ExecSparQl from OpenOWL class
ResultSetFormatter.out(results);
// It creates and displays the table
JTable table = new JTable(buildTableModel(results));
JOptionPane.showMessageDialog(null, new JScrollPane(table));
}
catch (Exception ex)
{
System.out.println(ex);
}
}
//CODE ADDITION BY ALINA ANJUM STARTED ON 03-AUGUST-2021
public static DefaultTableModel buildTableModel(com.hp.hpl.jena.query.ResultSet rs)
throws SQLException {
List<String> metaData = rs.getResultVars();
// names of columns
Vector<String> columnNames = new Vector<String>();
int columnCount = metaData.size();
System.out.println(columnCount);
for (int column = 0; column <columnCount; column++)
{
columnNames.add(metaData.get(column));
}
// data of the table
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
while (rs.hasNext())
{
QuerySolution sol = rs.nextSolution();
Vector<Object> vector = new Vector<Object>();
for (int columnIndex = 0; columnIndex < columnCount; columnIndex++)
{
//vector.add(rs.getObject(columnIndex));
String columnName = columnNames.get(columnIndex);
vector.add(sol.getLiteral(columnName).getString());
}
data.add(vector);
}
return new DefaultTableModel(data, columnNames);
}
The following Query is Perfectly returning values:
SELECT (str(?x) as ?name)
WHERE {
?Person ssuet:hasname ?x.
}
The following Query is working fine in Protege but not returning values in Result Set in Java:
SELECT (str(?x) as ?name)
(str(?y) as ?phone)
WHERE {
?Person ssuet:hasname ?x.
?Person ssuet:hasPhoneNumber ?y.
}
Screen shot of the OutPut in Netbeans:
Results for 2nd Query in protege:
ResultSets are iterators.
Calling ResultSetFormatter.out(results) exhausts the iterator (no more rows).
If you want to use the result twice, use ResultSetFactory.makeRewindable to get a result set that can be reset to the start.

JTable does not refresh with fireTableDataChanged()

I have a JTable with DefaultTableModel. I want to refresh the JTable whenever I click on the JTable. Below is my code using modelTarget.fireTableDataChanged(); to refresh the JTable.
but the values shown within the JTable does not change when click action is performed.
Initializing component and inserting values into table:
final TestClass test = new TestClass();
String sql = "SELECT * FROM student";
ResultSet rs = test.stmt.executeQuery(sql);
JTable table = new JTable();
DefaultTableModel model = new DefaultTableModel(0, 0);
String header[] = new String[] { "ID", "Name"};
model.setColumnIdentifiers(header);
table.setModel(model); //set model into table object
while (rs.next())
{
int id = rs.getInt("id");
String name = rs.getString("name");
//Add rows into table
model.addRow(new Object[] { id, name});
}
Listener for JTable:
table.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e) {
String sql = "UPDATE student " + "SET name='Alice' " + "WHERE id=7";
JTable target = (JTable)e.getSource();
int row = target.getSelectedRow();
try{test.stmt.executeUpdate(sql);}
catch(SQLException err){System.out.println("SQL Error!");};
System.out.println(target.getModel().getValueAt(row, 0)); //get row value
DefaultTableModel modelTarget = (DefaultTableModel) target.getModel();
modelTarget.fireTableDataChanged(); //JTable did not refresh with this code
}
});
Que: Do I need to do anything else to the table model before using .fireTableDataChanged() ? If not, what else can I do to let the JTable refresh?
EDIT: I am suspecting that the table model did not receive the changes which I made to the sql tables. So is there any way I can "refresh" or "update" the table model?
EDIT: I managed to let it work now by writing a method to empty all rows in current model and re-add all the rows according to the updated database. I did not use fireTableDataChanged() at all. Anyone in human history managed to let fireTableDataChanged() work?

Modifying column headers of JTable with MySQL data

I have a JTable that retrieves information from a MySQL database table. The column headers are named just like how they are in the database.
Here is the code to create the JTable:
JScrollPane spBlockViewSchedule = new JScrollPane();
spBlockViewSchedule.setBounds(10, 285, 763, 185);
pnlBlockSched.add(spBlockViewSchedule);
tblBlockViewSchedule = new JTable();
spBlockViewSchedule.setViewportView(tblBlockViewSchedule);
Here is the code that populates the JTable:
private void populateTable(String sql, JTable table) {
try {
pst = DbConnection.conn.prepareStatement(sql);
rs = pst.executeQuery();
} catch(Exception ex) {
ex.printStackTrace();
}
table.setModel(DbUtils.resultSetToTableModel(rs));
}
How do I change the column names displayed in the JTable without changing the column names of the database table itself?
Create an empty DefaultTableModel with code like:
String[] columnNames = {"Course Code", "Subject Code", "Year Level", ...};
DefaultTableModel model = new DefaultTableModel(columnNames, 0);
Then in the code where you read the data from the ResultSet you add the data to the TableMOdel using the addRow(....) method. Something like:
while (rs.next())
{
Vector row = new Vector();
for (int i = 1; i <= columns; i++)
{
row.addElement( rs.getObject(i) );
}
model.addRow( row );
}
Finaly you create the table using:
JTable table = new JTable( model );
Edit:
Since you are using 3rd party code you either need to change the way you add data to the model. I gave you basic code above. You can see the Table From Database Example source code from Table From Database for a complete example.
Or, you can modify the column headers after the table is created with code like:
table.getColumn("course_code").setHeaderValue("Course Code");
...
table.repaint();
Edit 2:
You can get the TableColumn from the TableColumnModel:
TableColumnModel tcm = table.getTableColumnModel();
tcm.getColumn(0).setHeaderValue("Course Code");
...
table.repaint();
I am currently facing the same problem as you did.
This line:
table.setModel(DbUtils.resultSetToTableModel(rs));
provided by r2xml.jar is pretty handy :)
I overcame the problem by setting alias to my sql SELECT statement.
For example,
SELECT
EngagementMethodID AS [ID],
EngagementMethodDescription AS [Engagement Method Description]
FROM [STUDENT].[EngagementMethod]
This will populate the column header as ID and Engagement Method Description as wanted.
Hope it helps.. Despite the age of this question? haha... Just sharing
try this
int colCount = 0;
ResultSetMetaData rsMetaData = null;
colCount = rsMetaData.getColumnCount();
for (int k = 1; k <= colCount; k++) {
{ String columnName = null;
columnName = rsMetaData.getColumnName(k);
System.out.println(columnName);
}
use this code simultaneously with your fetching code.
Each JTable has a TableModel. This TableModel defines the columns(Names and data types)
so find your table model and change it accordingly.

Cant display rows in a JTable (Values from Database)

Hello dear programmers,
it's my first post and i hope i'm able to describe which kind of problem i have.
I'm German, thats why my classnames are in german. I tried to put in some helpfull comments.
I'm trying to put the values of a database (called "buchungen") into a JTable inside a JPanel.
My JTable shows up but only the headers and no rows..
Here is my class with the JTable inside:
public class Verlauf extends SQL{
JTable table = new JTable();
DefaultTableModel model = new DefaultTableModel();
Verlauf(){
removeAll();
try {
rs = stmt.executeQuery("SELECT * FROM buchungen WHERE Ausführer = '" + kontoNr + "'"); // kontoNr equals to Ausführer in the database
} catch (Exception e) {
e.printStackTrace();
}
displayData(rs);
repaint();
}
public void displayData(ResultSet rs)
{
int i;
int count;
String a[];
String header[] = {"BuchungsNr","Ausführer","Betrag","Aktion","Empfänger"}; //Table Header Values, change, as your wish
count = header.length;
//First set the Table header
for(i = 0; i < count; i++)
{
model.addColumn(header[i]);
}
table.setModel(model); //Represents table Model
add(table.getTableHeader(),BorderLayout.NORTH);
a = new String[count];
// Adding Database table Data in the JTable
try
{
while (rs.next())
{
for(i = 0; i < count; i++)
{
a[i] = rs.getString(i+1);
}
model.addRow(a); //Adding the row in table model
table.setModel(model); // set the model in jtable
}
}
catch (Exception e)
{
JOptionPane.showMessageDialog(null, "Exception : "+e, "Error", JOptionPane.ERROR_MESSAGE);
}
}
I got the method for the jtable from a other post which i cant find anymore...
I hope someone can help me :)
Edit: The connection to my database is made in another class (called SQL) which works fine because i can use it from other classes perfectly in the same way i did here.
Greetings Lukas Warsitz
While the JTable header has been added to the container, the table itself has not
add(table);

create jtable from database using codes and displaying database table records in it

Yow, I am trying to add a jTable in my jFrame and I wanna display records from my database table to the jTable.
I was able to create a jTable(I put the code in the constructor) and manually inputted in the code the values to be displayed. It worked. But then when I try to call a method that retrieves data from the database, and try to display them inside the jtable. It gives me an error "NullPointerException".
CODE in my constructor that creates the table:
String[] columnname = {"Subject Code", "Prelim", "Midterm", "SemiFinal", "Finals"};
setTable();
Object[][] data = {};
gradetable = new JTable(data, columnname){
public boolean isCellEditable(int data, int columns){
return false;
}
public Component prepareRenderer(TableCellRenderer r, int data, int columns){
Component c = super.prepareRenderer(r, data, columns);
if (data % 2 == 0){
c.setBackground(Color.GRAY);
}
else{
c.setBackground(Color.WHITE);
}
if (isCellSelected(data, columns)){
c.setBackground(Color.ORANGE);
}
return c;
}
};
gradetable.setPreferredScrollableViewportSize(new Dimension (400, 150));
gradetable.setFillsViewportHeight(true);
jsp = new JScrollPane(gradetable);
Method I used to retrieve the data from the database and add them to the table:
private void setTable(){
DefaultTableModel model = (DefaultTableModel)gradetable.getModel();
try
{
Class.forName("com.mysql.jdbc.Driver");
Connection con = (Connection)DriverManager.getConnection("jdbc:mysql://localhost:3306/grading","root","");
Statement st = con.createStatement();
String sql = "SELECT * FROM student INNER JOIN grade ON student.idnumber = grade.idnumber WHERE student.idnumber = '2010-00125'";
ResultSet rs = st.executeQuery(sql);
model.setRowCount(0);
while (rs.next()){
//this.setName(rs.getString("name"));
//this.setCourse(rs.getString("course"));
//this.setYear(rs.getString("year"));
String d1, d2, d4, d3, d5;
d1 = rs.getString("subjectcode");
d2 = rs.getString("prelim");
d3 = rs.getString("midterm");
d4 = rs.getString("semifinal");
d5 = rs.getString("finals");
model.addRow(new Object[]{d1,d2,d3,d4,d5});
}
rs.close();
con.close();
}catch(ClassNotFoundException | SQLException ex){
JOptionPane.showMessageDialog(null, ex);
}
}
The reason for the NPE is that you are calling setTable which tries to get the JTable model here:
DefaultTableModel model = (DefaultTableModel)gradetable.getModel();
This is before you have actually instantiated gradetable, so the NPE is thrown.
Aside from this, you need to use DefaultTableModel when setting the model of the JTable, otherwise you will get a ClassCastException on this line.

Categories

Resources