Ich möchte eine JTable anzeigen, die die Daten aus einer DataBase-Tabelle so anzeigt, wie sie ist.
Bis jetzt habe ich JTable verwendet, das Daten von Object [] [] anzeigt.
Ich weiß, eine Möglichkeit, die Daten anzuzeigen, besteht darin, zuerst die Datenbanktabelle in Object [] [] zu konvertieren. Gibt es eine andere, die einfach und dennoch leistungsfähiger und flexibler ist.
Ich würde den folgenden Ansatz empfehlen:
Row
-Klasse, um eine Zeile darzustellen, die von Ihrer ResultSet
gelesen wird. Dies könnte ein einfacher Wrapper für einen Object[]
sein.List<Row>
-Sammlung und eine Unterklasse AbstractTableModel
, die von dieser Sammlung unterstützt werden soll.SwingWorker
, um Ihren List<Row>
zu füllen, indem Sie aus der zugrunde liegenden ResultSet
in einem background-Thread lesen (d. H. Innerhalb der doInBackground()
-Methode). Rufen Sie die SwingWorker
-Methode von publish
auf, um Row
s wieder im Event Dispatch-Thread zu veröffentlichen (z. B. alle 100 Zeilen).SwingWorker
-Methode der process
mit dem letzten gelesenen Teil der Zeilen aufgerufen wird, fügen Sie sie zu Ihrem List<Row>
hinzu und lösen die entsprechenden TableEvent
s aus, um die Anzeige zu aktualisieren.ResultSetMetaData
, um die Variable Class
jeder Spalte in der Definition von TableModel
zu bestimmen. Dies führt dazu, dass sie korrekt gerendert werden (was bei einer einfachen Verwendung eines 2D Object[][]
-Arrays nicht der Fall ist).Der Vorteil dieses Ansatzes besteht darin, dass die Benutzeroberfläche bei der Verarbeitung großer ResultSet
s nicht blockiert und die Anzeige bei der Verarbeitung der Ergebnisse inkrementell aktualisiert wird.
EDIT
Beispielcode hinzugefügt:
/**
* Simple wrapper around Object[] representing a row from the ResultSet.
*/
private class Row {
private final Object[] values;
public Row(Object[] values) {
this.values = values;
}
public int getSize() {
return values.length;
}
public Object getValue(int i) {
return values[i];
}
}
// TableModel implementation that will be populated by SwingWorker.
public class ResultSetTableModel extends AbstractTableModel {
private final ResultSetMetaData rsmd;
private final List<Row> rows;
public ResultSetTableModel(ResultSetMetaData rsmd) {
this.rsmd = rsmd;
this.rows = new ArrayList<Row>();
}
public int getRowCount() {
return rows.size();
}
public int getColumnCount() {
return rsmd.getColumnCount();
}
public Object getValue(int row, int column) {
return rows.get(row).getValue(column);
}
public String getColumnName(int col) {
return rsmd.getColumnName(col - 1); // ResultSetMetaData columns indexed from 1, not 0.
}
public Class<?> getColumnClass(int col) {
// TODO: Convert SQL type (int) returned by ResultSetMetaData.getType(col) to Java Class.
}
}
// SwingWorker implementation
new SwingWorker<Void, Row>() {
public Void doInBackground() {
// TODO: Process ResultSet and create Rows. Call publish() for every N rows created.
}
protected void process(Row... chunks) {
// TODO: Add to ResultSetTableModel List and fire TableEvent.
}
}.execute();
Eine weitere leistungsstarke und flexible Möglichkeit, Datenbankdaten in einer JTable anzuzeigen, besteht darin, die Ergebnisdaten Ihrer Abfrage in einen CachedRowSet zu laden und sie dann mit JTable mit TableModel - Adapter zu verbinden.
Dieses book von George Reese gibt den Quellcode für seine Klasse RowSetModel, um ein RowSet als TableModel anzupassen. Arbeitete für mich out-of-the-box. Meine einzige Änderung war ein besserer Name für die Klasse: RowSetTableModel.
Ein RowSet ist eine in Java 1.4 hinzugefügte Subschnittstelle von ResultSet. Also ein RowSet is ein ResultSet.
Eine CachedRowSet-Implementierung erledigt die Arbeit für Sie, anstatt eine Row-Klasse, eine Liste von Row-Objekten und ResultSetMetaData zu erstellen, wie in den anderen Antworten auf dieser Seite beschrieben.
Sun/Oracle bietet eine Referenzimplementierung von CachedRowSet. Andere Hersteller oder JDBC-Treiber können ebenfalls Implementierungen bereitstellen.
Je nachdem, was Sie bereits getan haben und was Sie tun möchten, habe ich Netbeans mit Beans Binding-Unterstützung für eine datenbankgesteuerte Anwendung sehr erfolgreich verwendet. Sie binden Ihre JTable an eine Datenbank und die JPA-Abfragen werden automatisch erstellt.
Bester Weg, um jTable mit ResultSet zu füllen
1) Ergebnismenge "rs" wird mit Daten gefüllt, die Sie benötigen . 2) Die JTabelle "jTable1" wird vor dem Handblatt erstellt
Java.sql.ResultSet rs = datacn.executeSelectQuery(query);
//Filling JTable with Result set
// Removing Previous Data
while (jTable1.getRowCount() > 0) {
((DefaultTableModel) jTable1.getModel()).removeRow(0);
}
//Creating Object []rowData for jTable's Table Model
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); // 1
}
((DefaultTableModel) jTable1.getModel()).insertRow(rs.getRow() - 1,row);
}
Sie müssen ein benutzerdefiniertes TableModel erstellen. Dort können Sie angeben, woher und wie die Daten stammen.
Sie müssen erst wirklich verstehen, wie JTable + TableModel funktioniert und dann einer der zuvor veröffentlichten Antworten folgen.
Ich weiß, dass die Frage alt ist, aber für jeden, der der Lösung von Adamski folgt, ist Vorsicht geboten, wenn die ResultSet
und ResultSetMetadata
zwischen gui und SwingWorker
geteilt werden. Ich habe eine inkonsistente Ausnahmebedingung für den internen Status erhalten, als ich diesen Ansatz mit SQLite verwendete. Die Lösung besteht darin, alle Metadaten in private Felder zu laden, bevor SwingWorker
ausgeführt wird, und die Getter-Funktionen (getColumnName usw.) verwenden, um stattdessen die Felder zurückzugeben.
Ich gebe eine kleine Methode zum Anzeigen von Datenbanktabellendaten in JTable. Sie müssen nur das Resultset der Datenbanktabelle als Parameter ..__ übergeben.
// rs is the ResultSet of the Database table
public void displayData(ResultSet rs)
{
//jt Represents JTable
//jf represents JFrame
int i;
int count;
String a[];
String header[] = {"1","2","3","4","5"}; //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]);
}
jt.setModel(model); //Represents table Model
jf.add(jt.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
jt.setModel(model); // set the model in jtable
}
}
catch (Exception e)
{
JOptionPane.showMessageDialog(null, "Exception : "+e, "Error", JOptionPane.ERROR_MESSAGE);
}
}