【问题标题】:@ManyToOne and @BatchSize@ManyToOne 和 @BatchSize
【发布时间】:2012-10-24 11:36:03
【问题描述】:

我在一些旧代码中发现了奇怪的东西(至少对我来说)。

注解为@ManyToOne 的字段也注解为@BatchSize。

我一直认为@BatchSize注解只在类级别或集合(@OneToMany)注解时影响,在迭代时影响预取。

但也许我错了,用@BatchSize 注释@ManyToOne 会影响某些事情。我在文档中找不到答案。

用@BatchSize注释@ManyToOne有意义吗?

【问题讨论】:

    标签: java hibernate hibernate-mapping hibernate-annotations


    【解决方案1】:

    我认为这个问题是指将@ManyToOne 和@BatchSize 组合在同一个字段上,例如:

    @ManyToOne
    @BatchSize(size = 5)
    private User owner;
    

    Hibernate 不支持此用例,至少在使用注释时是这样。 documentation 提到的批量提取的唯一用途是:

    • 在集合字段上,即@OneToMany 或@ManyToMany(但不是 @ManyToOne)
    • 关于要获取的实体类

    例如:

    @Entity
    @BatchSize(size = 5)
    public class User {
      ...
    }
    

    后一种情况支持对所有用户类型的关系进行批处理,包括多对一关系。但是,使用实体类上的注释无法逐个字段地控制行为。

    在 Hibernate 源代码中搜索@BatchSize 的所有用途,确认不支持您的使用。从我在AnnotationBinder.java 中看到的情况来看,@BatchSize 注释仅在实体类和具有某种@XxxToMany 注释的字段上进行检查。

    【讨论】:

    • 我觉得你的回答很有趣。这似乎与 OP 接受的相矛盾。我没有检查你的研究,但你说服了我,所以我赞成你的回答。如果专家能解决这个问题就好了。
    【解决方案2】:

    与@BatchSize关联的@ManyToOne只有在对应的字段被标记为lazy(lazy=true)时才有意义。

    确实,如果该字段不是lazy,则根据定义,自从加载了封闭实体以来,它就已经加载了,因此不存在数据库调用的问题。

    想象一个Person 类有一个ShoesPair 元素(ShoesPair.class)的集合,并且在这个集合中存在一个标记为惰性的owner 字段(因为是可选的,并且在检索特定的一双鞋)。

    一个人想要遍历 25 双鞋(25 个ShoesPair 对象)以检索它们的所有者。

    如果owner字段(对应一个人)只标注@ManyToOne,则有25选择到数据库。

    但是,如果使用 @BatchSize(size=5) 进行注释,则只会有 5 次调用,从而提高性能。

    从Hibernate documentation 中可以看出,批量大小不仅适用于集合:

    您可以也启用集合的批量获取。

    Hibenate 尤其提到了 @OneToMany 案例,因为这些案例应用的字段在 90% 的案例中标记为 lazy。

    【讨论】:

    • 如果它真的像你写的那样有效,我没问题。但我在文档中找不到它。在那里我只看到这个:“19.1.5。使用批量获取使用批量获取,如果访问一个代理,Hibernate 可以加载多个未初始化的代理。批量获取是延迟选择获取策略的优化。有两种方法可以配置批处理获取:在类级别和集合级别。”
    • 我的意思是片段:在类级别和集合级别。
    • @Łukasz Rzeszotarski 我认为文档认为这很明显,这就是为什么没有提到它。事实上,这个概念只适用于惰性对象。我更新了我的答案。
    • 也许很明显也许不是。文档应该涵盖所有可能性,或者只是以更一般的方式编写——就像你写的“这个概念适用于惰性对象”。但是感谢您的回答,我会接受它,但也许有人想添加一些东西。
    • 但是在文档中,用owner 字段解释了一个类似的例子。这个可以被标记为@ManyToOne(无所谓)。据我所知,您的需求已包含在此示例中。
    【解决方案3】:

    用 Hibernate 解决 N+1 查询问题

    1 使用带有 fetchMode 的条件查询

    条件标准 = session.createCriteria(Customer.class); criteria.setFetchMode("contact", FetchMode.EAGER);

    2 HOL fetch 连接

    3 @BatchSize

    @BatchSize 注释可用于定义在单个数据库查询中填充多少相同的关联。如果会话附加了 100 个客户,并且“联系人”集合的映射使用大小为 n 的 @BatchSize 进行注释。这意味着每当 Hibernate 需要填充惰性联系人集合时,它会检查会话,如果它有更多客户需要填充他们的联系人集合,它会获取最多 n 个集合。

    @OneToMany(mappedBy="customer",cascade=CascadeType.ALL, fetch=FetchType.LAZY)
        @BatchSize(size=25)
        private Set<Contact> contacts = new HashSet<Contact>();
    

    【讨论】:

      猜你喜欢
      • 2015-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-14
      • 1970-01-01
      • 2014-10-02
      • 1970-01-01
      相关资源
      最近更新 更多