我想要展示一个JTable,它可以直接展示来自数据库表的数据。
迄今为止,我使用的是从Object[][]展示数据的JTable。
我知道一种方法是先将数据库表转换为Object[][],但是否还有其他更易用、更强大和灵活的方式呢?
Row
类来表示从ResultSet
中读取的一行。这可以是一个简单的Object[]
包装器。List<Row>
集合,并子类化AbstractTableModel
以由此集合支持。SwingWorker
在后台线程(即在doInBackground()
方法内)中从底层ResultSet
中读取以填充List<Row>
。调用SwingWorker
的publish
方法将Row
发布回事件分派线程(例如每100行)。SwingWorker
的process
方法并读取最新的一块Row
时,将它们添加到List<Row>
中,并触发适当的TableEvent
以导致显示更新。ResultSetMetaData
来确定TableModel
定义中每列的Class
。这将使它们正确呈现(如果仅使用2D Object[][]
数组,则不会出现这种情况)。这种方法的优点是在处理大型ResultSet
时,用户界面不会锁定,并且随着结果的处理,显示将逐步更新。
编辑
下面是示例代码:
/**
* 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();
在JTable中展示数据库数据的另一种强大而灵活的方式是将查询结果数据加载到CachedRowSet中,然后使用TableModel适配器将其连接到JTable。
这本由George Reese编写的书籍提供了源代码,用于将RowSet适配为TableModel的RowSetModel类。对我来说,开箱即用。我的唯一更改是更好的类名:RowSetTableModel。
RowSet是ResultSet的子接口,Java 1.4中添加。因此,RowSet 就是 ResultSet。
CachedRowSet实现可以为您完成工作,而无需像本页其他答案中讨论的那样创建Row类、Row对象列表和ResultSetMetaData。
Sun/Oracle提供了CachedRowSet的参考实现。其他供应商或JDBC驱动程序也可能提供实现。 RowSet教程。使用ResultSet填充jTable的最佳方法
1)Result Set“rs”已经包含了您需要的数据。 2)在预先创建JTable“jTable1”。 3)表头已经预先实现。
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);
}
根据您已经完成的工作和愿意做的事情,我一直非常成功地使用Netbeans及其Beans Binding支持来开发数据库驱动的应用程序。您可以将JTable绑定到数据库,它会自动构建JPA查询。
I am giving a small method for display database table data in JTable. You need to pass only the resultset of the database table as parameter.
// 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;
//首先设置表头
for(i = 0; i < count; i++)
{
model.addColumn(header[i]);
}
jt.setModel(model); //表示表格模型
jf.add(jt.getTableHeader(),BorderLayout.NORTH);