【问题标题】:Cannot fetch multiple bags: why @IndexColumn returns wrong results?无法获取多个包:为什么@IndexColumn 返回错误的结果?
【发布时间】:2011-12-25 22:14:18
【问题描述】:

各位,请帮我解决以下问题。

我遇到了著名的“无法同时提取多个包”错误,因为我的父实体中有两个列表。这是一段代码:

class Manager{
    @OneToMany(cascade = CascadeType.ALL)
    @Fetch(FetchMode.JOIN)
    @IndexColumn(name = "id")
    private List<Action> actions;

    @OneToMany(cascade = CascadeType.ALL)
    @Fetch(FetchMode.JOIN)
    @IndexColumn(name = "id")
    private List<Activity> activities;
(...)
}

映射是单向的。

好的,我在 google 上搜索到我可以使用 IndexColumn 注释来修复它。如您所见,我已经实现了这一点,现在我没有得到提到的异常。但问题是,现在如果我想从 db 中获取所有管理器,我会收到更多真正存在的管理器实例!

例如,如果我在每个集合中只有 1 个管理器和 3 个子实例,则为 9 个管理器实例。我可以理解为什么会这样:Hibernate 产生一个看起来像

的选择
select ... from Manager this_ 
left outer join manager_action actions3_ on this_.id=actions3_.Manager_id 
left outer join Action action4_ on actions3_.actions_id=action4_.id 
left outer join Manager_Activity activities5_ on this_.id=activities5_.Manager_id 
left outer join Activity activity6_ on activities5_.activities_id=activity6_.id 

... 它确实获取了多于一个的行。

为什么会这样? 我该如何解决?

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    Hibernate 生成笛卡尔积,在这种情况下不会去重。像这样的笛卡尔积(3 个动作 * 3 个活动 = 9 行)只适用于集合而不是列表。

    即使有两个 Set,您也应该避免使用这些笛卡尔积。想一想:仅检索一位具有 100 个操作和 100 个活动的经理会从数据库中检索 10,000 行。你或许应该做两个查询:

    • 获取经理及其操作(100 行)
    • 获取同一个经理及其活动(100 行)

    这样只会产生 200 行而不是 10,000 行。结果将是相同的,因为活动将附加到会话中的同一 Manager 实例。它还可以避免您遇到的重复问题。

    【讨论】:

    • 谢谢,JB 尼泽特! (1) 但是您能解释一下 Hibernate 在哪些情况下可以以正确的方式处理多行吗? (2)第二个问题是:为什么你认为额外的行比额外的查询更糟糕?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-05
    • 2016-05-28
    • 2015-11-17
    • 1970-01-01
    • 2015-10-22
    相关资源
    最近更新 更多