Java @ManyTone和@BatchSize

Java @ManyTone和@BatchSize,java,hibernate,hibernate-mapping,hibernate-annotations,Java,Hibernate,Hibernate Mapping,Hibernate Annotations,我在一些旧代码中发现了一些奇怪的东西(至少对我来说是这样) 注释为@ManyToOne的字段也用@BatchSize注释 我一直认为,@BatchSize注释仅在类级别或集合(@OneToMany)上注释时有效,并在迭代时影响预取 但也许我错了,用@BatchSize注释@ManyToOne会影响某些东西。我在文档中找不到答案 用@BatchSize注释@ManyToOne有意义吗?@ManyToOne与@BatchSize相关联的@ManyToOne只有在相应字段标记为惰性时才有意义(lazy

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

注释为
@ManyToOne
的字段也用
@BatchSize
注释

我一直认为,
@BatchSize
注释仅在类级别或集合(
@OneToMany
)上注释时有效,并在迭代时影响预取

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


@BatchSize
注释
@ManyToOne
有意义吗?

@ManyToOne
@BatchSize
相关联的
@ManyToOne
只有在相应字段标记为
惰性时才有意义(
lazy=true

事实上,如果字段不是
惰性的
,根据定义,它已经加载了,因为加载了封闭实体,所以数据库调用的问题不适用

假设有一个
Person
类拥有一组
ShoesPair
元素(
ShoesPair
.class),其中有一个
owner
字段标记为lazy(因为这是可选的,并且在检索特定鞋款时不会真正带来重要信息)

人们希望遍历25双鞋(25
ShoesPair
对象),以检索它们的所有者

如果
所有者
字段(对应于一个人)仅用
@ManyToOne
注释,则会有25选择数据库

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

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

您还可以启用集合的批量提取

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

Hibenate特别提到了
@OneToMany
案例,因为这些案例应用的字段在90%的案例中标记为
惰性

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

@ManyToOne
@BatchSize(size = 5)
private User owner;
Hibernate不支持此用例,至少在使用注释时是这样。报告中提到的批量获取的唯一用途是:

  • 在集合字段上,即
    @OneToMany
    @ManyToMany
    (但不是
    @manytomone
  • 在要获取的实体类上
例如:

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


在Hibernate源代码中搜索
@BatchSize
的所有用法,可以确认您的用法缺乏支持。从中可以看出,
@BatchSize
注释仅在实体类和具有某种
@XxxToMany
注释的字段上进行检查。

解决了Hibernate的N+1查询问题

1在fetchMode下使用条件查询

条件=session.createCriteria(Customer.class); criteria.setFetchMode(“contact”,FetchMode.EAGER)

2.获取连接

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>();
@OneToMany(mappedBy=“customer”,cascade=CascadeType.ALL,fetch=FetchType.LAZY)
@批量大小(大小=25)
private Set contacts=new HashSet();

如果它真的像你写的那样工作,我也可以。但我在文档中找不到它。在这里,我只看到这样的内容:“19.1.5.使用批处理获取使用批处理获取,如果访问一个代理,Hibernate可以加载多个未初始化的代理。批处理获取是对惰性选择获取策略的优化。有两种方法可以配置批处理获取:在类级别和集合级别。”我指的是片段:在类级别和集合级别。@ukasz Rzeszotarski我认为文档认为这是非常明显的,这就是为什么没有提到它的原因。事实上,这个概念只适用于惰性对象。我更新了我的答案。也许很明显,也许不是。文档应该涵盖所有的可能性,或者只是以更一般的方式编写——就像您写的“这个概念适用于惰性对象”。但是谢谢你的回答,我会接受的,但是也许有人想添加一些东西。但是在文档中,它解释了一个类似的例子,其中有一个
owner
字段。这一个可以标记为nothing作为
@ManyToOne
(无事项)。据我所知,你的需求包含在这个例子中。我发现你的答案非常有趣。这似乎与OP接受的答案相矛盾。我不是在检查你的研究,但你说服了我,所以我对你的答案投了赞成票。如果专家能解决这个问题,那就太酷了。