【问题标题】:Approach for mapping one-to-many in sql without ORM在没有ORM的情况下在sql中映射一对多的方法
【发布时间】:2019-02-15 09:27:48
【问题描述】:

假设我有一个实体。

class Building {
  List<Floor> floors;
  List<Elevator> elevators; 
}

为了简单起见,Floor and Elevator 只有id。并且大楼有id, elevator_id, floor_id

因此,获取所有楼层和所有电梯的所有建筑物的查询将是:

select 
      id, 
      floor.id as floor_id, 
      elevator.id as elevator_id 
from building 
left join floor on (floor.building_id = building.id)
left join elevator on (elevator.building_id = building.id)

现在假设我有 1 栋有 2 层楼和 2 部电梯的建筑物。查询将给出如下结果集:

 id|floor_id|elevator_id
 1   f1        e1
 2   f2        e2
 1   f1        e2
 2   f2        e1 

所以 4 条记录。解析方式:

  1. 不是逐行,而是逐列。
  2. 分别创建每个实体
  3. 删除重复项
  4. 将所有实体合并到适当的结构中。

所以问题是 - 有没有更好的方法来解决这个问题? ORM 是否也做同样的事情?

没有寻找特定的库,因为我试图弄清楚它是如何工作的。

【问题讨论】:

    标签: java sql jdbc orm


    【解决方案1】:

    运行多个查询

    一个智能 ORM 应该运行 2-3 个查询:

    1. 查询所有建筑物,可能还有它们的楼层
    2. 获取楼层的查询(如果尚未获取)
    3. 获取所有电梯的查询

    执行这些查询后,可以在客户端中再次合并数据。这不是一个好主意,无论是在 SQL 中,还是在 ORM 中,使用多对左连接一次性完成所有操作,因为您将使用建议的 SQL 在楼层和电梯之间创建笛卡尔积。想象一下,如果每个建筑物的两个左连接都产生 1000 行,那么即使每个建筑物只有 2000 个孩子,您也会得到 1000000 行重复数据。

    关于多重集的附注

    请注意,SQL 标准有一个 MULTISET() 运算符,这将是这里的最佳选择,但很少有 RDBMS 实现它:

    select 
      building.*,
      multiset(select * from floor where floor.building_id = building.id),
      multiset(select * from elevator where elevator.building_id = building.id)
    from building 
    

    许多数据库都支持 XML 和 JSON,因此使用这些格式的解决方法可能有助于解决此问题,如果您可以将其抽象得足够好的话。我不知道目前有任何 ORM 在 Java 中执行此操作。 jOOQ has it on the roadmap,但没有实现。 Neither is Hibernate's version.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-11
      • 2014-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-30
      • 1970-01-01
      • 2023-03-08
      相关资源
      最近更新 更多