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

时间:2009-06-24 17:08:14

标签: java swing jdbc jtable

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

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

我保证将你的阅读和答案投票给答案了解整个事情(只要它们不是完全愚蠢的)。


用户需要能够:

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

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

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

  4. 修改属性值

  5. 对所选实体执行操作

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


  7. 系统要求:

    1. 实体数量:需要扩展到100K +唯一实体

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

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

    4. 内存:并非一切都适合,所以不知何故需要从DBMS查询中提取

    5. 性能:应该最小化DBMS所需的查询数量(每个属性一个查询OK,我有一个表格,每个表视图有1个查询,但很糟糕)。

    6. 查询:应该需要一个查询来生成与搜索/过滤器匹配的实体列表。否则大规模的表现太糟糕了。

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


    8. 我看过的事情:

      1. Glazed Lists library

        • 优点:

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

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

        • 优点:
          • 对结果进行分页可避免内存问题
          • 直接在SQL中搜索/过滤
          • 内存友好,不必每行制作一个对象
        • 缺点:
          • 实施自定义列&排序是一种痛苦(表头呈现器,管理排序列和顺序等)!
          • 也可能需要编写自定义JTableColumnModel,这会变得混乱!
          • 必须经常操作SQL,所以如果DB架构发生变化,必须重写多段代码!
          • 难以维护实体ID信息
      3. ORM

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

      4. 我错过了一个更好的选择,还是有一些聪明的方法可以让Glazed Lists或自定义表模型更容易?

        我已经完全放弃了ORM作为选项,因为它与EAV存储有多么匹配。

1 个答案:

答案 0 :(得分:1)

我认为你最好的选择是'使用来自JDBC ResultSet的表单映射数据扩展AbstractTableModel',因为

  • Java 6 JTable内置排序支持,因此您不需要实现它。
  • 如果您仔细设计模型,您可以在一些模式更改中存活下来。明确编码,以便在需要时更容易进行更改。
  • 无论如何,你必须回写更改。使用“保存”按钮,批量更新甚至可以帮助您提高性能。
  • 您可以覆盖TableCellEditor以提供组合框而不是默认文本编辑器。
  • 不要尝试在一个表中进行所有编辑。有分开的创作条件等。
  • 您可以在运行时向JTable添加/删除列。只需fireTableModelChanged()并且新列变为可见

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

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

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

删除非常简单,因为您不显示该列的值。

<强> EDIT3:

DefaultRowSorter不是那么深。它为您的记录维护一个重建索引表。因此,当JTable请求第10行时,rowsorter检查索引表的第10个条目,并从实际模型中检索该indexth元素。

此外,如果模型中有许多相同的字符串,则在查询数据库中的数据时,请使用简单的字符串Map to String缓存。这样,大量的冗余String对象就可以立即生成GC-d。

<强> Edit4:

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