在JTable中显示数据库中的数据

我正在使用jdbc编写一个程序,它将成为数据库的接口(像CRUD应用程序一样)。 我假设我必须编写一个类(例如DBCLass ),它将对数据库执行所有操作( select, update, insert, delete以及可能还原为这些操作的其他一些逻辑)。 用户界面由一组表和几个按钮组成。 要使用Jtable,我需要实现一个类(例如Model ),它是AbstractTableModel的子类。 所以这个类会向用户显示我的数据。 我需要为我的数据库模式中的所有表实现这样的模型。 我不想在向用户显示数据的类中编写逻辑,我认为在这些类中编写逻辑代码并不是一件好事。 但是将db表中的所有数据加载到内存(例如ArrayList)并将其显示在Model也是不正确的。 所以,我想要一个建议,这是解决这个问题的最佳方法。

编辑:一个小例子:

 Statement stmt = ....; ResaultSet rs = stmt.executeQuery("SELECT * FROM table1"); 

javadoc说executeQuery方法返回一个ResultSet对象,该对象包含给定查询生成的数据。 因此,如果我们有大量数据(大小超过我们的虚拟机的大小),我们的程序将失败。 所以我的问题仍然有用

下载SQuirreL SQl的源代码并查看表实现。

有些事情需要注意:

数据库表不是Java JTable。 数据库中的表实际上是一个集合(诅咒使用错误术语的傻瓜)和项目,每个项目都有属性(通常称为“列”,而不是JColumn,它解释了为什么很难映射这两个) 。

一套可以增长到任何尺寸。 它没有内在的秩序。 你可以对它进行很多设置操作,例如:union,difference,sub set。

因此,它不是表,尤其不是UI表。

没有简单的UI范例将“set”映射到“table”。 您可以

  1. 加载N条记录并翻阅结果。

  2. 您可以在用户向下滚动时加载更多内容

  3. 您可以计算集合的大小并相应地调整滚动条。 当用户滚动数据时,它将从DB中获取并显示。

优点+缺点:

解决方案1实现起来最简单,也是用户最讨厌的解决方案。 他们为什么要在倒退时等待再次查看数据呢? 如果每次获取需要15秒,这尤其令人沮丧。 页面…等待…页面…哎呀! 那是它! 该死的! 等待等待……回来……等等…… aaargh。

此外,数据库通常很难分页数据。 对于某些查询,性能可能是灾难性的。

解决方案2易于实现,尤其是如果您可以永久保持ResultSet打开。 但是100%的时间,你不能。 如果你把它打开几个小时或一天,它将开始失败。 在那段时间之后,DB会认为“哦,它已经死了,Jim”并关闭连接,你的用户会得到一个很好的错误信息,你会得到一个愤怒的用户。

所以你也需要在这里寻呼,但不是经常。 从积极的方面来说,用户无需再等待他们已有的数据。 一个重要的观点:如果集合包含数百万行,用户可以直观地了解他们需要在向下滚动时从不同角度解决问题。 最终,他们会感到疲倦并要求更好的解决方案(而不是对你生气,因为你的愚蠢程序不能在不到0.0000000001秒内显示1500万行)。

解决方案3再次比#2差。 如果表增长,UI将变得无法使用:即使查看滚动,也会将您移动到表中的随机位置。 所以它让你的鼠标无用。 而你的用户生气了。

所以我通常会尝试一个解决方案:

  1. 读取1000行,最多 另外,如果读取行超过1秒,我会在100行之后停止(因此用户至少有一些数据)。 通常,查询速度很慢,读取结果集几乎没有时间,但我喜欢在这里采取防御措施。

  2. 在每列的顶部是一个filter和一个“order by”,它可以直接映射到SQL。 这样,我可以确保如果您希望按列排序的数据,它将按所有值排序(而不仅仅是您可以在屏幕上看到的值)。

这允许用户将大量数据切割成有意义的子集。

Table From Database有几个想法。

MAKS,

这是关于通用sql到表实现的另一个例子:

http://www.oreillynet.com/pub/a/oreilly/java/news/javaex_1000.html

这可能是寻找答案的好地方。

此外,这个本地问题/答案可以帮助您使用ResultSet大小: Java JDBC Lazy-Loaded ResultSet

希望这可以帮助,

罗伯特

这篇博客文章解释了如何将数据延迟加载到表模型中: JTable绑定到具有延迟加载的数据库

您想要使用QuickTable项目中的DBTable组件。

使用示例代码用法检查此SO答案 。

这是一个从数据库中提取数据行和列的类。

查看table = new JTable(rows(),columns());

 import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.print.PrinterException; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.JTable; import com.swtdesigner.SwingResourceManager; import java.util.*; import java.sql.*; import javax.swing.*; public class listing extends JDialog { private JTable table; public static Vector rows() { Vector data = new Vector(); String sql= null; Connection C; try { DriverManager.registerDriver(new oracle.jdbc.OracleDriver()); C = (Connection) DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "system", "manager"); Statement stmt = C.createStatement(); ResultSet rset = stmt.executeQuery("SELECT * FROM site "); ResultSetMetaData md = rset.getMetaData(); int columns = md.getColumnCount(); while (rset.next()) { Vector row = new Vector(columns); for (int i = 1; i <= columns; i++) { row.addElement(rset.getObject(i)); } data.addElement(row); } rset.close(); stmt.close(); } catch (Exception e) { System.out.println(e.getMessage()); System.out.println(e.getStackTrace()); } //System.out.println("lignes : "+data); return data; } public static Vector columns() { Connection c ; Vector cols = new Vector (); String sql2=null; try { DriverManager.registerDriver(new oracle.jdbc.OracleDriver()); c = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "system", "manager"); sql2 = "select * from SITE"; Statement stmt = c.createStatement(); ResultSet rs = stmt.executeQuery(sql2); ResultSetMetaData md = rs.getMetaData(); int columns = md.getColumnCount(); //récupération des noms des colonnes dans la table site for (int i = 1; i <= columns; i++) { cols.addElement(md.getColumnName(i)); } } catch (Exception e) { System.out.println(e.getMessage()); System.out.println(e.getStackTrace()); } //System.out.println("colonnes ::: "+cols); return cols; } public static void main(String args[]) { try { listing dialog = new listing(); dialog.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); dialog.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } public listing() { super(); getContentPane().setLayout(null); setTitle("Listing de la table \"SITE\""); setBounds(100, 100, 500, 363); setResizable(false); final JLabel laTablesiteLabel = new JLabel(); laTablesiteLabel.setText("La table \"SITE\" contient . . . "); laTablesiteLabel.setBounds(10, 34, 274, 16); getContentPane().add(laTablesiteLabel); final JLabel label = new JLabel(); label.setIcon(SwingResourceManager.getIcon(listing.class, "/pictures/130.png")); label.setBounds(402, 18, 49, 48); getContentPane().add(label); final JButton okButton = new JButton(); okButton.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent arg0) { dispose(); setVisible(false); } }); okButton.setIcon(SwingResourceManager.getIcon(listing.class, "/pictures/33-32x32.png")); okButton.setText("Ok"); okButton.setBounds(10, 291, 148, 32); getContentPane().add(okButton); final JButton refeshButton_1 = new JButton(); refeshButton_1.setIcon(SwingResourceManager.getIcon(listing.class, "/pictures/48-32x32.png")); refeshButton_1.setText("Actualiser"); refeshButton_1.setBounds(171, 291, 148, 32); getContentPane().add(refeshButton_1); final JScrollPane scrollPane = new JScrollPane(); scrollPane.setBounds(10, 85, 474, 187); getContentPane().add(scrollPane); table = new JTable(rows(), columns()); // chargement de JTable scrollPane.setViewportView(table); final JButton printButton_1_1 = new JButton(); printButton_1_1.addActionListener(new ActionListener() { public void actionPerformed(final ActionEvent arg0) { try { table.print(); } catch (PrinterException e) { e.printStackTrace(); } } }); printButton_1_1.setIcon(SwingResourceManager.getIcon(listing.class, "/pictures/Printer_h.png")); printButton_1_1.setText("Imprimer"); printButton_1_1.setBounds(336, 291, 148, 32); getContentPane().add(printButton_1_1); } }