【问题标题】:Comparing beans with multiple properties, depending on two beans each比较具有多个属性的 bean,每个属性取决于两个 bean
【发布时间】:2012-01-17 18:41:22
【问题描述】:

我有问题。首先让我向您展示我希望能够比较的 bean 的结构:

ItemDTO 包含:

  • 姓名
  • 项目ID
  • 类型
  • 亚型
  • 身体部位
  • 价格

ItemOnCharacterDTO 包含:

  • 所有者ID
  • 项目ID
  • 计数
  • 位置

ItemDTO 是从 XML 文件中静态读取的。有成千上万的人并且他们没有改变(至少我不在乎他们现在是否这样做)。 ItemOnCharacterDTO 是通过查询数据库创建的。 ownerID、itemID、count 和 location 因字符而异,因此保存在数据库中。这里的 itemID 对应一个有效的 ItemDTO。

我有一个 ItemOnCharacterDTO 对象的数组(或 ArrayList),我想按多个条件排序,例如通过“itemOnCharacterDTO.ownerID”、“itemDTO.name”、“itemDTO.type”。

如果我将 ItemDTO 和 ItemOnCharacterDTO 合并为一个类(例如 ItemAllDTO),我可以轻松使用 apache BeanComparator。然而:我不是。 原因是:用户可以在不同的字符上拥有多个项目。基本项目数据 (ItemDTO-data) 是相同的,而用户特定数据 (ItemOnCharacterDTO-data) 会发生变化。因此,我只加载前者一次,而每次遇到不同的 ItemOnCharacterDTO 时都会加载用户特定的数据。

由于我都是在 GWT 中编写的,所以我决定在服务器上进行排序,因为这是所有信息所在的位置(与前端相比,与项目相关的信息是通过分页加载的)。我在服务器端使用 Java。我编写了一个映射器来从与项目相关的 XML 文件中正确检索静态 XML 数据。但是基于字符的项目相关信息存储在mysql数据库中

我希望能够通过 ItemOnCharacterDTO- 或 ItemDTO-object 中存在的属性对 ItemOnCharacterDTO 的数组或 ArrayList 进行排序(我有办法区分给定属性属于哪个 DTO - 意思:我知道用户是否按“计数”排序,我将不得不检查 ItemOnCharacterDTO-object 的这个属性,而不是 ItemDTO-object)。

每个用户可能有几千个对象。每个 ItemOnCharacterDTO 大约有 5 个属性,但每个 ItemDTO 大约有 25 个左右。因此,将它们组合到一个对象中(即使只是为了比较)也不是一个真正的选择,因为它会非常缓慢且消耗内存。

有人有更好的方法吗?我很高兴得到任何帮助——即使你只是给出一个原始的想法。我会解决的。

提前非常感谢您!非常感谢您的帮助!

伊戈尔。

P.s.:如果您还有任何问题,请随时提问 - 我会尽快回复! P.s.2:Java 是否有类似“LINQ”的东西?也许它会帮助我解决我的问题?

【问题讨论】:

  • 我刚刚看到有一个JXPath,它可以查询对象。有没有办法使用它来基于两个 bean 进行比较?

标签: java mysql xml sorting comparator


【解决方案1】:

创建两个哈希映射并在两个映射中保持相同的键,而对象将来自不同的列表。这意味着您可以轻松访问它们并轻松匹配它们。

您还可以在两个对象中覆盖 equals 和 hashcode 方法。

您也可以将两者包装在一个对象中并使用它进行排序。

【讨论】:

  • 恐怕将对象包装成一个对象会使我创建对象数据的深层副本。这是我想避免的,因为复制数据只是为了对项目进行排序然后丢弃它是荒谬的——并且不确定垃圾收集器是否表现得足够好。这就是为什么我想将数据保存在两个不同的 DTO 中。我的意思是:我没有更改 ItemDTO 中的数据。它只包含额外的排序标准(例如名称、类型、价格等)。所以我必须在排序时以某种方式考虑这些信息。但我很可能不必复制 ItemDTO。
  • 不,你不需要深拷贝。您可以将引用存储在包装对象中。并在包装器中覆盖 equals。
【解决方案2】:

您可以实现自己的比较器,将两个类的数据都考虑在内。作为一个帮助结构,您可以保存 2 个映射,其中 key 是两个 DTO 的 DTO id。这样您就可以通过 ID 找到第二个 DTO 进行比较。

【讨论】:

  • 我找到 DTO 没有问题 - 我可能只是将它们粘贴到比较器方法中。我不确定的是如何实际编写 Comparator 或 CompareTo 方法,它考虑的不仅仅是相同类型的另一个对象(例如,采用参数:thisItemDTO、thisItemOnCharacterDTO、anotherItemDTO、anotherItemonCharacterDTO)。你有什么提示吗?您的方法是我想遵循的方法,因为我不想创建一个包含来自两个 DTO 的数据的对象。
【解决方案3】:

我相信你已经在做正确的事了。通过BeanCompartor 进行比较或您的自定义比较器应该让您能够通过导航对象层次结构进行比较。所以,我相信这是正确的方式。

【讨论】:

  • 这就是我的想法.. 但似乎 BeanComparator 应该能够比较相同类型的两个 bean。我不知道如何让它考虑更多信息......除了实际将 ItemDTO 对象分配给 ItemOnCharacterDTO-“itemID” 并像这样连接它以便稍后使用点访问它。但这会使我将对象数据包装到一个对象中-出于性能原因,我想避免这种情况(我在其他任何地方都不需要此对象数据-仅用于排序..因此仅为此复制数据是一种可笑的性能下降imo)。
  • 好的,您可以将自定义 caopmartor 传递给 BeanComparator。那将是一个实现 Compartor 接口的匿名类。以及在 compare 方法中正确实现的内部逻辑。看看这里的第二个例子。如果您确定可以轻松地从 ItemCharacterDAO 中的 itemId 获取 ItemDAO,那么这应该不是问题。
  • 抱歉错过了链接这里给出的第二个例子:discursive.com/books/cjcook/reference/beans-sect-comparing
  • 性能优化可以是使用那些适当的类而不是匿名类,如果这些类再次重复并再次出现。但基本上上面应该解决了比较的第一个问题。
【解决方案4】:

当时(Java 8 之前)我最终使用了JoSQL,因为我最终想要以大多数人(包括我自己)可以轻松理解的方式进行动态查询。它让我能够以各种方式选择、比较、排序和限制我的结果集——这正是我当时想做的事情。

现在,我可能会使用 Java 8 lambda 表达式来完成我当时尝试做的事情(选择某些项目、比较、排序、限制结果集等)。我确实相信还有其他方法可以解释数据 - 特别是如果数据量很大,但当时没有必要,因为我处理的数据量还不够大,例如考虑重用一些数据库系统。

编辑:我与 JoSQL 没有任何关系,我只是用它来解决我的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-08
    • 2015-08-09
    • 2014-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-19
    相关资源
    最近更新 更多