Java 如何使用数据库在JTable中填充数据?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2192764/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to fill data in a JTable with database?
提问by Yatendra Goel
I want to display a JTable that display the data from a DataBase table as it is.
我想显示一个 JTable,它按原样显示来自 DataBase 表的数据。
Up till now, I have used JTable that displays data from Object [ ][ ].
到目前为止,我一直使用 JTable 来显示来自 Object [ ][ ] 的数据。
I know one way to display the data is to first convert the database table into Object [ ][ ] but Is there any other which is easy yet more powerful and flexible.
我知道显示数据的一种方法是首先将数据库表转换为 Object [ ][ ] 但是有没有其他更简单但更强大和灵活的方法。
采纳答案by Adamski
I would recommend taking the following approach:
我建议采用以下方法:
- Create a
Row
class to represent a row read from yourResultSet
. This could be a simple wrapper around anObject[]
. - Create a
List<Row>
collection, and subclassAbstractTableModel
to be backed by this collection. - Use a
SwingWorker
to populate yourList<Row>
by reading from the underlyingResultSet
on a background thread(i.e. within thedoInBackground()
method). CallSwingWorker
'spublish
method to publishRow
s back to the Event Dispatch thread (e.g. every 100 rows). - When the
SwingWorker
'sprocess
method is called with the latest chunk of Rows read, add them to yourList<Row>
and fire appropriateTableEvent
s to cause the display to update. - Also, use the
ResultSetMetaData
to determine theClass
of each column within theTableModel
definition. This will cause them to be rendered correctly (which won't be the case if you simply use a 2DObject[][]
array).
- 创建一个
Row
类来表示从您的ResultSet
. 这可能是一个围绕Object[]
. - 创建一个
List<Row>
集合,以及AbstractTableModel
由该集合支持的子类。 - 使用 a通过从后台线程上的底层读取(即在方法内)
SwingWorker
来填充您List<Row>
的。调用的方法将s发布回 Event Dispatch 线程(例如每 100 行)。ResultSet
doInBackground()
SwingWorker
publish
Row
- 当使用最新的 Rows 块调用
SwingWorker
'sprocess
方法时,将它们添加到您的List<Row>
并触发适当的TableEvent
s 以更新显示。 - 此外,使用
ResultSetMetaData
来确定定义Class
中每一列的TableModel
。这将导致它们被正确渲染(如果您只是使用 2DObject[][]
数组,则不会出现这种情况)。
The advantage of this approach is that the UI will not lock up when processing large ResultSet
s, and that the display will update incrementally as results are processed.
这种方法的优点是 UI 在处理大ResultSet
s时不会锁定,并且显示会随着结果的处理而增量更新。
EDIT
编辑
Added example code below:
在下面添加了示例代码:
/**
* 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();
回答by Jon
Depending on what you've done already and what you're willing to do, I've been using Netbeans with its Beans Binding support for a database-driven app very successfully. You bind your JTable to a database and it automatically builds the JPA queries.
根据您已经完成的工作以及您愿意做的事情,我一直在非常成功地使用 Netbeans 及其对数据库驱动应用程序的 Beans Binding 支持。您将 JTable 绑定到数据库,它会自动构建 JPA 查询。
回答by OscarRyz
You have to create a custom TableModelThere you can specify where and how the data is coming from.
您必须创建一个自定义TableModel在那里您可以指定数据的来源和方式。
You really have to fully understand first how JTable+ TableModelworks and then follow one of the previously posted answers.
您确实必须首先完全了解JTable+ TableModel 的工作原理,然后按照之前发布的答案之一进行操作。
回答by Ram
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.
我给出了一个在 JTable 中显示数据库表数据的小方法。您只需将数据库表的结果集作为参数传递。
// 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);
}
}
回答by Basil Bourque
Another powerful and flexible way to display database data in a JTable is to load your query's resulting data into a CachedRowSet, then connect it to the JTablewith TableModeladapter.
在 JTable 中显示数据库数据的另一种强大而灵活的方法是将查询的结果数据加载到CachedRowSet 中,然后使用TableModel适配器将其连接到JTable。
- Query ---> Database data ---> RowSet
- RowSet <--> TableModel adapter <--> JTable
- 查询 ---> 数据库数据 ---> RowSet
- RowSet <--> TableModel 适配器 <--> JTable
This bookby George Reese gives the source codefor his class RowSetModelto adapt a RowSetas a TableModel. Worked for me out-of-the-box. My only change was a better name for the class: RowSetTableModel.
George Reese 的这本书给出了他的类RowSetModel的源代码,用于将RowSet改编为 TableModel。为我开箱即用。我唯一的改变是为这个类取了一个更好的名字:RowSetTableModel。
A RowSet is a subinterface of ResultSet, added in Java 1.4. So a RowSet isa ResultSet.
RowSet 是 ResultSet 的子接口,是在 Java 1.4 中添加的。所以 RowSet是一个 ResultSet。
A CachedRowSet implementation does the work for you, instead of you creating a Row class, a List of Row objects, and ResultSetMetaData as discussed in other answers on this page.
CachedRowSet 实现会为您完成这项工作,而不是像本页上的其他答案中所讨论的那样,您创建一个 Row 类、一个 Row 对象列表和 ResultSetMetaData。
Sun/Oracle provides a reference implementationof CachedRowSet. Other vendors or JDBC drivers may provide implementations as well.
Sun/Oracle 提供了CachedRowSet的参考实现。其他供应商或 JDBC 驱动程序也可能提供实现。
回答by Yogesh
Best way to fill jTable with ResultSet
用 ResultSet 填充 jTable 的最佳方法
Prerequisites
先决条件
1) Result Set "rs" is populated with data you need. 2) JTable "jTable1" is created before hand 3) Table Header is implemented before hand
1) 结果集“rs”填充了您需要的数据。2) JTable "jTable1" 是事先创建的 3) Table Header 是事先实现的
Implementation
执行
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);
}
回答by Yogesh
I know the question is old but for anyone following Adamski's solution, care should be taken while sharing the ResultSet
and ResultSetMetadata
between gui and SwingWorker
threads. I got an inconsistent internal state exception while using this approach with SQLite. The solution is to load any metadata to private fields before executing the SwingWorker
and have the getter functions (getColumnName etc.) to return the fields instead.
我知道这个问题很老,但是对于任何遵循 Adamski 解决方案的人来说,在 gui 和线程之间共享ResultSet
和 时应该小心。在 SQLite 中使用这种方法时,我遇到了不一致的内部状态异常。解决方案是在执行之前将任何元数据加载到私有字段,并使用 getter 函数(getColumnName 等)来返回字段。ResultSetMetadata
SwingWorker
SwingWorker