【问题标题】:How to map a database query into an Object [in Java]?如何将数据库查询映射到对象 [in Java]?
【发布时间】:2009-12-09 11:33:26
【问题描述】:

我有一个连接 5 个表的查询。 然后我用我需要的列值填充我的手工对象。

这里有哪些使用特定工具解决该问题的普遍解决方案?有这样的工具吗?

我才刚刚开始学习 Hibernate,所以我的问题是:Hibernate 是解决这个问题的正确决定吗?

Hibernate 将一个表映射到一个类。所以,如果我有 5 个类而不是 5 个表,那没有什么区别。还是很难将查询结果加入到一个类中

可以使用休眠将查询映射到我预先定义的结构(类)中,就像我们对表映射所做的那样?或者更好的是,它能否像逆向工程一样将查询结果映射到有意义的字段中[自动创建带有字段的类]?

我一直在考虑视图,但是.. 每次我们需要复杂查询时创建一个新视图.. 太冗长了。

正如 S.Lott 所问,这是一个简单版本的问题:

一般问题:

选择 A.field_a、B.field_b、C.field_c from table_a A 内连接 table_b B 内连接 table_c C 在哪里 ...

每个表包含 100 个字段 查询返回 3 个字段,但每个字段都属于唯一的表

如何以 OO 风格解决这个问题? 设计一个新对象,其属性对应于查询的返回值。

我想知道这是否是正确的 [也是唯一可能的] 决定,是否有任何共同的解决方案。

另见我的 cmets。

【问题讨论】:

  • -1:这个问题的标题含糊不清。请更新标题以反映您真的想知道。 “映射”太简单了。这个问题比这更深。
  • 我想知道它通常是如何制作的,不仅仅是在我的特殊情况下。 ORM 可能不是这里的真实情况,我提到了 Hibernate,因为我怀疑它可以在这种情况下使用。但它也可以手工制作。 ORM 赞扬表和类之间 1:1 关系的概念[可能有细微的差异,例如字段名和字段数]。在我的情况下可能会使用它,但应该使用它吗?
  • @EugeneP:不要要求我们阅读您的 cmets。更新您的问题。问题永远存在,很多很多人会阅读这个问题。请花时间回答正确的问题。绝对正确。如果您必须关闭它才能重试,那很好。但是,您的 cmets 将被忽略。

标签: java hibernate orm


【解决方案1】:

ORM 的重点是将对象映射到关系。

ORM 的意义在于——明确地——不是去关注特定 SQL 连接的细节。

理解 ORM 的一个基本准则是这样的。

SQL 连接是一种 hack,因为 SQL 没有适当的导航。

为了进行 ORM 设计,我们有意将 SQL 连接考虑因素放在一边(很大程度上)不相关。放弃旧方法。没关系,真的。 SQL 拐杖不能很好地支持我们。

步骤 1. 定义话语领域。现实世界的对象。

第 2 步。定义作为现实世界事物的高保真模型的实现类。

步骤 3. 将对象映射到关系。这是黑客攻击开始的地方。 SQL 没有多种集合——它只有表。 SQL 没有子类,它只有表。所以你必须在对象类和表之间设计一个“足够好”的映射。理想情况下,这是一对一的。但实际上,情况并非如此。通常你会有一些非规范化来处理类层次结构。除此之外,它应该工作得相当好。

是的,您必须添加没有对象映射的多对多关联表。

第 4 步。您已完成。编写您的应用程序。

“但是我的查询连接了 5 个(或 3 个)表但只从每个表中获取一个属性呢?”

怎么样?其中一张表是您正在处理的真实对象。这 5 个(或 3 个)表中的另一个是 1-m 嵌套集合、m-1 个容器或 m-m 关联的一部分。这只是对象之间的导航。

一米长的嵌套集合是 SQL 将其视为“结果集”的类型。在 ORM 中,它将成为一个适当的对象集合。

一个 m-1 包含是典型的 FK 关系。在 ORM 中,它只是通过普通对象导航获取相关对象。

一个 m-m 关联也是一个对象集合。这是一个奇怪的集合,因为两个对象是彼此集合的成员,但它只是一个对象集合。

您绝不会设计与查询匹配的对象。您设计一个与现实世界匹配的对象,将其映射到数据库。

“性能怎么样?”只有当你颠覆 ORM 的简单映射规则时才会出现问题。一旦进入蓝月亮,您必须创建一个特殊用途的视图来处理对象之间非常大的面向批处理的连接。但这真的很少见。通常,重新考虑 Java 程序的导航模式会提高性能。

请记住,ORM 会缓存您的结果。每个“导航”可能不是数据库查询的完整“往返”。 ORM 可能会为您分批处理一些查询。

【讨论】:

  • 我有一个这样的模式: SomeOtherUserPropsTable Service_User -> 服务(用户可以使用的)已经有 4 个表。如果我们一次需要所有这些信息,这很常见。
  • >>"5-table join 不是——也不应该是——一个单一的类"
  • 那么那些子属性应该是不同的类;例如在上述情况下,ServiceUserUser 的子类,并包含其他属性Map 和对Service 实例的引用等。单个类本身通常应该在单个表中定义,即使您可能需要查找多个表以完全填充其依赖项。
  • @EugeneP:请用更多信息更新问题。
  • @Andrzej。是的参考。这里的主要类是用户。其他属性可能存在或不存在,如果需要,它们将是复杂类型,如 Map。他们是不同的班级。但它们都提供了一个复杂的实例,即代表我的 5-joins-query 的 Class [User]。
【解决方案2】:

有几个选项:

  1. 使用<join> 元素为相关表创建单个表映射。以这种方式连接将允许其他表为您的类贡献属性。
  2. 按照之前的建议使用数据库视图。
  3. 使用 Hibernate 映射视图 - 您可以使用 <class name=... select="select A.field_a, B.field_b, ... from A, B, ..."> 代替 <class name=... table=...。它本质上是在 Hibernate 端创建一个视图,因此数据库不必更改。生成的 sql 最终看起来像“select * from (select A.field_a, B.field_b from A, B, ...) "。我知道这适用于 Oracle、DB2 和 MySQL

所有这些都可以选择;如果您需要进行插入/更新,您可能需要重新考虑您的数据模型或对象模型。

【讨论】:

  • 仅选择 - 这就是我的重点。
  • +1。如果没有复杂的连接条件,第一个选项是最好的。
【解决方案3】:

认为您可以使用 Hibernate 中的 Criteria API 将您的连接结果映射到您的目标类中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-30
    • 1970-01-01
    • 2012-07-18
    • 1970-01-01
    • 1970-01-01
    • 2013-08-30
    相关资源
    最近更新 更多