java - 在 JTable 中显示实体属性值数据?

标签 java swing jdbc jtable

如何使用 JTable 显示和编辑从实体、属性、值 (EAV) 存储(关系 DBMS)检索的实体的属性属性?

我知道这个问题有很多可能的答案,所以请在回答之前先看看我下面的要求。

我保证会对那些表明您已阅读并理解整件事的答案进行投票(只要它们不是完全愚蠢的)。

<小时/>

用户需要能够:

  1. 按属性过滤/搜索实体

  2. 选择要显示的属性(作为列)

  3. 按所选属性对实体进行排序

  4. 编辑属性值

  5. 对选定实体进行操作

  6. (可选)能够保存 View 以供以后使用。

<小时/>

系统要求:

  1. 实体数量:需要扩展到 10 万多个唯一实体

  2. 属性:用户可以添加和定义新属性,系统应该能够处理这个

  3. 底层存储:H2数据库(已设计),通过JDBC通信

  4. 内存:并非所有内容都适合,因此需要以某种方式从 DBMS 查询中提取

  5. 性能:应该最大限度地减少 DBMS 所需的查询数量(每个属性一个查询还可以,我有一个表单,每个 TableView 有 1 个查询,但这很糟糕)。

  6. 查询:应需要一个查询来生成与搜索/过滤器匹配的实体列表。否则巨大的性能会很糟糕。

  7. 重用数据:添加列时不必重新查询或重新排序整个列表。

<小时/>

我看过的东西:

  1. Glazed Lists 库

    • 优点:

      • 灵活的列处理
      • 易于实现实体排序/过滤
      • 灵活的列显示格式和编辑
    • 缺点:

      • 每个实体一个对象(如果对象很复杂,内存开销就会成为严重的内存问题!)
      • 负责所有功能的对象...但由于内存原因,对象应该很简单
      • 如何在每个实体对象没有 HashMap 的情况下支持用户可选择的列?
  2. 扩展 AbstractTableModel 以将数据从 JDBC 结果集映射到行、列

    • 优点:
      • 结果分页可避免内存问题
      • 直接在 SQL 中进行搜索/过滤
      • 内存友好,不必每行创建一个对象
    • 缺点:
      • 实现自定义列和排序很麻烦(表头渲染器、管理排序列和顺序等)!
      • 可能还必须编写自定义 JTableColumnModel,这会变得很困惑!
      • 需要大量操作SQL,因此如果数据库架构发生变化,就必须重写多段代码!
      • 难以维护实体 ID 信息
  3. ORM

    • 优点:
      • 旨在将数据库行映射到对象
      • 提供对象管理
    • 缺点:
      • 实体属性值模型最糟糕的解决方案
      • 除了 DBMS 和 Java 代码之外,还必须学习和编写 ORM 代码!
      • 实体可以拥有任意数量的属性,ORM 仅适用于静态、有限的对象属性
      • 失去自定义 SQL 的灵 active /速度
<小时/>

是否有我错过的更好的选择,或者一些巧妙的方法来使玻璃列表或自定义表格模型更容易?

我已经完全放弃了 ORM 作为一个选项,因为它与 EAV 存储的匹配程度非常差。

最佳答案

我认为最好的选择是“使用来自 JDBC 结果集的表单映射数据扩展 AbstractTableModel”,因为

  • Java 6 JTable 内置了排序支持,因此您实际上不需要实现它。
  • 如果您仔细设计模型,您就可以承受一些架构更改。清晰的代码可以让您在需要时更轻松地进行更改。
  • 无论如何,您都必须写回更改。使用“保存”按钮和批量更新甚至可能会提高您的性能。
  • 您可以重写 TableCellEditor 以提供组合框而不是默认文本编辑器。
  • 不要尝试在一张表中进行所有编辑。具有独立的条目创建方式等。
  • 您可以在运行时向 JTable 添加/删除列。只需 fireTableModelChanged() 即可看到新列

编辑:我会做一件疯狂的事情来创建一个自定义组件并自己完成所有渲染并使用放置良好的 JTextField 和 JComboBox 执行编辑操作。

编辑2:根据您的评论。 在执行 fire...() 调用之前保存所选项目的位置。顺便说一句,我不认为调用会重置排序或选择 - 没有问题。

如果添加列,您只需获取新列的关键字段和值。将它们显示在列中。然后在后台执行隐藏的完全重新加载,并在完成后将模型交换到该模型。这实际上是在一个表中同时处理多个结果集。

删除很容易,因为您不显示该列的值。

编辑3:

DefaultRowSorter 并没有那么深。它为您的记录维护一个重新索引表。因此,当 JTable 请求第 10 行时,行排序器会检查索引表的第 10 个条目,并从实际模型中检索该索引元素。

此外,如果模型中有大量相同的字符串,则在从数据库查询数据时使用简单的字符串到字符串缓存映射。这样大量的冗余 String 对象就可以立即被 GC 回收。

编辑4:

我会将新字段查询到键到值的映射中,并让我的主模型包含键到值的映射列表。然后,我将使用 getValue() 实现,它根据需要从主数据源或这些附加 map 返回值。我将从主模型中查找行的键,并使用它从附加映射中检索实际值。 (顺便说一句,通过接受的答案获得的声誉不受每日限制。)

关于java - 在 JTable 中显示实体属性值数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1039694/

相关文章:

java.lang.ClassNotFoundException : com. mysql.jdbc.Driver(jar 文件已链接并放置在 WEB-INF/lib 中)

java - 我的 SpringAOP 演示代码中出现了 null 错误

Java:截图后获取照片点击效果

java - jar文件被执行

java - 使用文本框更改 Java 中的字体大小

java - 无状态 session bean 中的高效 JDBC 连接管理

java - HikariCP - 在连接 checkin 和从连接池 checkout 时动态设置连接的数据库

c# - C# 中的等效 JVM 是什么?

java - 没有存储库类型的合格 bean

java - 在构造函数中无效