I'm building a java application that gets its data from an oracle database and puts it into a JTable.
My problem is I am not able to populate the table, I don't understand how to do it. Javadoc is useless.
I don't understand why the table doesn't get the rows:
if ((report.getMsg()=="selectEventoAll") && (report.getEsito()==1))
{
DefaultTableModel dtm = new DefaultTableModel();
eventi_tb.setModel(dtm);
try
{
ResultSet res_eventi = report.getRes();
i = 0;
Object[][] datiEventi = new Object[report.getRowCount()][5];
while(res_eventi.next())
{
j = 0;
while (j < 5)
{
datiEventi[i][j] = res_eventi.getObject(j+2);
j++;
}
dtm.addRow(datiEventi[i]);
i++;
}
}
You can do this using a custom implementation of AbstractTableModel.
After you get your results back, put them in a list and let this be the backing list for your table model.
See here .. http://download.oracle.com/javase/tutorial/uiswing/components/table.html#data
Table From Database should get you started.
Related
I'm trying to filter a JTable but the results are not as expected.
Below is the JTable with the added elements (I'm using MySQL to store the Data)
JTable with contents - Picture
When I try to filter the list for someone specific, I do not get the data from the table. For example, I search for "Ana" and nothing appears.
Search results for "Ana" - Picture
If I try to search using some "numbers", like the salary, I get the right result but the ID is not right. Pictures to clarify the issue below.
Wrong ID
Right ID
The Code to generate the ArrayList with the employees :
public static ArrayList<Angajat> listaAngajati() {
ArrayList<Angajat> listaAngajati = new ArrayList<>();
try (java.sql.Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/angajati", "root", "***");) {
Statement st = conn.createStatement();
st.executeQuery("select * from angajati");
ResultSet rs = st.getResultSet();
Angajat angajat;
while (rs.next()) {
angajat = new Angajat(rs.getInt("id"), rs.getString("nume"), rs.getString("prenume"), rs.getInt("varsta"), rs.getString("adresa"), rs.getDouble("salariu"));
listaAngajati.add(angajat);
}
} catch (SQLException ex) {
System.out.println("Error in database connection: \n" + ex.getMessage());
}
return listaAngajati;
}
public static void arataAngajati() {
ArrayList<Angajat> arataAngajati = listaAngajati();
DefaultTableModel model = (DefaultTableModel) tabelangajati.getModel();
Object[] rand = new Object[6];
for (int i = 0; i < arataAngajati.size(); i++) {
rand[0] = arataAngajati.get(i).getID();
rand[1] = arataAngajati.get(i).getNume();
rand[2] = arataAngajati.get(i).getPrenume();
rand[3] = arataAngajati.get(i).getVarsta();
rand[4] = arataAngajati.get(i).getAdresa();
rand[5] = arataAngajati.get(i).getSalariu();
model.addRow(rand);
}
}
Code to filter the JTable
private void cautaInTabelKeyReleased(java.awt.event.KeyEvent evt) {
DefaultTableModel tabel = (DefaultTableModel) tabelangajati.getModel();
String query = cautaInTabel.getText().toLowerCase();
TableRowSorter<DefaultTableModel> sort = new TableRowSorter<DefaultTableModel>(tabel);
tabelangajati.setRowSorter(sort);
sort.setRowFilter(RowFilter.regexFilter(query));
}
Question : How can I modify the code so when I try to search for a an employee using his name to get the right result (not like now - no results) and when trying to modify the employee data, to get the right ID as shown in the JTable (example in the pictures above) ?
EDIT
In order to filter the data from the table accordingly I had to use
sort.setRowFilter(RowFilter.regexFilter("(?i)" + query));
When I was filtering the table, only the view modified and not the values from the row (Even if I saw the values from the row 3 and values on the backend where from the row 1). I managed to modify the following row and the table works perfectly.
From :
int row = tabelangajati.getSelectedRow();
To :
int row = tabelangajati.convertRowIndexToModel(tabelangajati.getSelectedRow());
I am having trouble showing my database filled JTable within my GUI application.
My code below runs through and creates a GUI with a panel, I then create my JTable and add it onto my application. I then run through a method that supposedly populates the table. After the populating has finished, nothing shows.
Dissecting my code, I'm led to believe somewhere is causing the data not to parse into my table, for some unknown reason, which is why I have come here.
At the click of a button, this code entails:
JTable tigerTable = new JTable();
JPanel centerPanel = new JPanel();
centerPanel.add(tigerTable, new GridBagConstraints());
FillTable(tigerTable, "SELECT * FROM TIGER_INFO");
The FillTable method as follows:
//Add buildTableModel method
public void FillTable(JTable table, String Query)
{
try
{
Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance();
Connection conn = DriverManager.getConnection("jdbc:derby:STOCK_CONTROL");
Statement stat = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stat.executeQuery(Query);
System.out.println("Connected");
//Remove previously added rows
while (table.getRowCount() > 0)
{
((DefaultTableModel) table.getModel()).removeRow(0);
}
int columns = rs.getMetaData().getColumnCount();
while (rs.next())
{
Object[] row = new Object[columns];
for (int i = 1; i <= columns; i++)
{
row[i - 1] = rs.getObject(i);
}
((DefaultTableModel) table.getModel()).insertRow(rs.getRow() - 1, row);
}
rs.close();
stat.close();
conn.close();
}
catch (InstantiationException |
IllegalAccessException |
ClassNotFoundException |
SQLException e)
{
System.out.println(e);
e.printStackTrace();
}
}
Doing so creates the application, but does not show any table with data. My database contains 3 columns and 3 rows, but I do not see my data displayed inside a JTable.
My question is, how can I populate my JTable with my database and display it correctly on my GUI application?
If you need anything else, please let me know and I will provide as much as I can.
Thank you in advance.
I think you mix the operation, i suggest to use this instruction :
Create a Bean, or Entity to store the information of your Object
Get the List of your data,
Display your data in your JTable,
So you can use this to display your data in your JTable :
....
List<TIGER_INFO> list = new ArrayList<>();//create a List of data
while (rs.next()){
//fill data in your List
list.add(new TIGER_INFO(rs.getTYPExxx("att1"), rs.getTYPExxx("att2"), rs.getTYPExxx("att3"));
}
//when you finish call your function which display your data :
fillData(list);
....
Fill date method can look like this :
private void fillData(List<TIGER_INFO> list) {
DefaultTableModel model = (DefaultTableModel) jTableName.getModel();
while (model.getRowCount() > 0) {
for (int i = 0; i < model.getRowCount(); i++) {
model.removeRow(i);
}
}
for (TIGER_INFO obj : list) {
model.addRow(new Object[]{
obj.getAttribute1(),
obj.getAttribute2,
obj.getAttribute3
});
}
}
I recommend to write a class extending AbstractTableModel. Add a function to this class filling the content based on a SQL-Statement. Then it will look something like:
TigerTableModel tigerModel = new TigerTableModel(dbConnection);
tigerModel.executeQuery("select * FROM TIGER_INFO");
JTable tigerTable = new JTable(tigerModel);
or you create a generic TableModel that is able to run every SQL-statement, so you are very flexible in your project.
I have found the solution - I've been trying to wrap my head around the problem for way too long, and I finally fixed it.
Try setting the table model manually first.
JTable tigerTable = new JTable();
tigerTable.setModel(new DefaultTableModel(0, numberOfColumns));
When you don't specify a model, the JTable creates an anonymous inner class and generally doesn't behave how you want it to.
I am running a query against a database, and it works fine, but building the data to place into a table takes a while. I am retrieving 500,000 rows of data, and I don't think that it should take very long to display that, but my Application stops responding because of how long it takes. I have tried the same query in different applications and they load the really fast. Is there anything I can do to speed mine up?
public ArrayList<HashMap<String, ArrayList>> runQueries(String query){
ArrayList<HashMap<String, ArrayList>> arrayList = new ArrayList<>();
try{
Statement stmt = conn.createStatement();
stmt.execute(query);
while(true){
HashMap<String, ArrayList> hm = new HashMap<>();
// Get next resultset if no resultset was returned.
// The query was either an insert, update or delete
if(stmt.getUpdateCount() > -1){
stmt.getMoreResults();
continue;
}
// If the resultset is null exit
if(stmt.getResultSet() == null){
break;
}
// We have a resultset!
// Save the columns to an array
// We can then display them later
ResultSet rs = stmt.getResultSet();
int numColumns = rs.getMetaData().getColumnCount();
ArrayList<String> columns = new ArrayList();
for(int i = 0; i < numColumns; i++){
columns.add(rs.getMetaData().getColumnName(i + 1));
}
// Save the columns to the hashmap
hm.put("columns", columns);
// We now need to save the rows to an array as well
// We can then display them later as well
ObservableList<ObservableList<String>> oblist = FXCollections.observableArrayList();
while(rs.next()){
ObservableList<String> row = FXCollections.observableArrayList();
for(int i = 1; i <= numColumns; i++){
row.add(rs.getString(i));
}
oblist.add(row);
}
ArrayList<ObservableList> rows = new ArrayList<>();
rows.add(oblist);
rs.close();
// Save the rows to the hashmap
hm.put("rows", rows);
// Save the hashmap to the final array
arrayList.add(hm);
stmt.getMoreResults();
}
}catch(SQLException ex){
Logger.getLogger(Mysql.class.getName()).log(Level.SEVERE, null, ex);
}
return arrayList;
}
Edit:
I have narrowed it down to the section that takes a while to run:
ObservableList<ObservableList<String>> oblist = FXCollections.observableArrayList();
while(rs.next()){
ObservableList<String> row = FXCollections.observableArrayList();
for(int i = 1; i <= numColumns; i++){
row.add(rs.getString(i));
}
oblist.add(row);
}
First: Do not load all records. Why would you even do that? You could implement some kind of pagination in your application.
I.e. Add two simple buttons below your table "Previous" and "Next" and "Search" field above. In beginning, load i.e. 100 records. Upon each click, load next 100 records etc. If user is looking for specific record, he could use "Search" field.
Second: Load your records in background thread to keep your application UI always responsive and prevent freezing. Read more about concurrency in JavaFX.
Try replacing
if(stmt.getUpdateCount() > -1){
stmt.getMoreResults();
continue;
}
if(stmt.getResultSet() == null){
break;
}
with
if(stmt.getUpdateCount() > -1){
if (!stmt.getMoreResults()) {
break ;
}
}
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.
I have a JTable and I populte the table as follows:
jTable_Std_info.setModel(DBControler.getALLStudents());
And the following is a static method in a class named DBControler which retrieves all the data from the database(Oracle).
public static DefaultTableModel getALLStudents() throws SQLException, Exception {
DefaultTableModel tableModel = new DefaultTableModel();
Vector rows = new Vector();
Vector columns = new Vector();
try {
conn = geConnection();
cst = conn.prepareCall("{? = call std_getInfoFunc}");
cst.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);
cst.execute();
res = (ResultSet) cst.getObject(1);
System.out.print(res);
ResultSetMetaData rsm = res.getMetaData();
for (int i = 1; i <= rsm.getColumnCount(); i++) {
columns.addElement(rsm.getColumnName(i));
}
int row = 0;
while (res.next()) {
Vector vRow = new Vector(); //to store the current row
//System.out.println("Row " +row+"\n");
for (int i = 1; i <= rsm.getColumnCount(); i++) {
String columnValue = res.getString(i);
vRow.addElement(columnValue);
}
row += 1;
rows.addElement(vRow);
}
tableModel.setDataVector(rows, columns);
} catch (SQLException e) {
e.printStackTrace();
} finally {
res.close();
conn.close();
}
return tableModel;
}
So far everything works fine, but the problem is that if I insert a new record in the database, the JTable doesn't get the newly inserted row/data. Why is that and how can I fix this problem?
UPDATE:
It's retrieving the data when I commit my new insertion. So do I have to commit each time I update? Or is there any other ways to do this?
I think that you looking for Oracle Built-In Database Change Notification, not sure if is accesible for Oracle's in free-versions, if not then never mind, for MySQL is there two or three similair API for Java JDBC
But the problem is that if I insert a new record in the database, the JTable doesn't get the newly inserted row/data. Why is that?
The TableModel doesn't know when the database is updated.
and how can I fix this problem?
If your application is adding the row to the database then it also needs to add a row to the TableModel at the same time.