Will accessing an element within a list annotated with @LazyCollection(LazyCollectionOption.EXTRA) cause initializing the entire list?

huangapple go评论78阅读模式
英文:

Will accessing an element within a list annotated with @LazyCollection(LazyCollectionOption.EXTRA) cause initializing the entire list?

问题

我有以下的Chat类:

@Data
@Entity
@NoArgsConstructor
public class Chat extends BaseEntity {

    @ManyToOne
    @JoinColumn(name = "user1_id")
    private User user1;

    @ManyToOne
    @JoinColumn(name = "user2_id")
    private User user2;

    @LazyCollection(LazyCollectionOption.EXTRA)
    @OrderBy("sentAt DESC")
    @OneToMany(mappedBy = "chat", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<Message> messages = new ArrayList<>();

    public Chat(User user1, User user2) {
        this.user1 = user1;
        this.user2 = user2;
    }
}

关于messages字段,我只对访问第一个元素感兴趣,这是最新的消息在这种情况下。

执行以下语句:chat.getMessages().get(0)会导致整个messages列表被初始化吗?如果是的话,那么最佳实践是什么?

英文:

I have the following Chat class:

@Data
@Entity
@NoArgsConstructor
public class Chat extends BaseEntity {

    @ManyToOne
    @JoinColumn(name = &quot;user1_id&quot;)
    private User user1;

    @ManyToOne
    @JoinColumn(name = &quot;user2_id&quot;)
    private User user2;

    @LazyCollection(LazyCollectionOption.EXTRA)
    @OrderBy(&quot;sentAt DESC&quot;)
    @OneToMany(mappedBy = &quot;chat&quot;, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List&lt;Message&gt; messages = new ArrayList&lt;&gt;();

    public Chat(User user1, User user2) {
        this.user1 = user1;
        this.user2 = user2;
    }
}

In respect of the messages field, I am only interested in accessing the first element, -which is the latest message this case-

Would executing the following statement: chat.getMessages().get(0) cause the entire messages list to be initialized? If yes, then what is the best practice?

答案1

得分: 1

这种方式不起作用。

根据hibernate文档

> LazyCollectionOption.EXTRA 仅适用于有序集合,即使用 @OrderColumn 或者 Map 注解的列表。
>
> 对于包(例如普通的不保留任何特定顺序的实体列表),@LazyCollection(LazyCollectionOption.EXTRA) 的行为与任何其他 FetchType.LAZY 集合相同(在首次访问时会完整获取集合的内容)。

从另一方面来说,根据@OrderColumn 注解的文档:

> 应该使用 OrderBy 注解来进行持久状态可见且由应用程序维护的排序。当指定了 OrderColumn 时,不使用 OrderBy 注解。
>
> 排序列必须是整数类型。 持久性提供程序在更新关联或元素集合时,维护排序列的值的连续(非稀疏)排序。第一个元素的排序列值为0。

因此,无法使用 @OrderColumn 注解按日期/时间进行排序,从而无法在第一个元素上使用 LazyCollectionOption.EXTRA 进行懒加载。

我建议您为获取最后一条聊天消息使用单独的查询。

英文:

It will not work in this way.

According to the hibernate documentation:

> LazyCollectionOption.EXTRA only works for ordered collections, either List(s) that are annotated with @OrderColumn or Map(s).
>
> For bags (e.g. regular List(s) of entities that do not preserve any certain ordering), the @LazyCollection(LazyCollectionOption.EXTRA) behaves like any other FetchType.LAZY collection (the collection is fetched entirely upon being accessed for the first time).

From the other side, according to the documentation for the @OrderColumn annotation:

> The OrderBy annotation should be used for ordering that is visible as persistent state and maintained by the application. The OrderBy annotation is not used when OrderColumn is specified.
>
> The order column must be of integral type. The persistence provider maintains a contiguous (non-sparse) ordering of the values of the order column when updating the association or element collection. The order column value for the first element is 0.

So, you can not use the @OrderColumn annotation for ordering by date/time and as result the LazyCollectionOption.EXTRA for the first element lazy loading.

I would suggest you to use a separate query for the fetching of the last chat message.

huangapple
  • 本文由 发表于 2020年4月10日 22:30:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/61142447.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定