JPA是否也懒于原始属性? [英] Is JPA also lazy for primitive attribues?

查看:109
本文介绍了JPA是否也懒于原始属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试检测代码中的N + 1问题.我发现的每个问题示例始终涉及两个实体,但这并不能真正解释单个实体是否也会发生这种情况.

一般的例子是:汽车有很多轮子.对于每辆车,我都想要每个轮子.

Select * from cars
Select * from wheels where carId=?

List<Car> cars = getCarsFromDB();
for(Car car : cars){
   List<Wheel> wheels = car.getWheels(); //Wheels are entities.
}

但是非实体呢?

List<Car> cars = getCarsFromDB();
for(Car car : cars){
   //select car.plate from Car car where car.id = ?
   String plate = car.getPlate(); //Plate is just a varchar.
}

JPA是否也懒惰地获取非实体? 这也是N + 1问题吗?

解决方案

简短的答案取决于情况.

如果您没有使用Hibernate的字节码增强功能,那么在加载实体时,将自动获取任何基本类型的列,因此它们并不懒惰,也不会引入额外的查询来使它们可用. /p>

因此,在您的情况下,在创建Car实例时填充该板.

现在,如果您使用的是Hibernate的字节码增强功能,并且专门将字段注释为@Lazy,则该字段是惰性的,并且在您首次访问该字段时会产生数据库查询成本,就像懒惰的关联.

在这种情况下,为了避免N + 1问题(此处N是每个懒惰的注释字段),您可以执行以下操作:可以指定@LazyGroup并将多个懒惰的初始化字段组合在一起,以便组被访问时,其余的将被同时加载.

但是同样,我上面描述的后一种情况仅在您使用字节码增强功能并且特定指定要延迟加载字段时适用.

JPA特定

JPA规范规定以下内容:

3.2.9:

如果所有具有FetchType.EAGER的属性(无论是否是显式的),都将视为已加载实体 指定或默认设置(包括关系和其他具有集合值的属性) 从数据库加载或由应用程序分配.具有FetchType.LAZY的属性可以或 可能尚未加载.实体实例和关联实例的可用状态为 在3.2.7节中进行了说明.

如果已嵌入embeddable属性,则视为已嵌入可嵌入属性 从数据库或由应用程序分配,并且,如果属性引用了可嵌入实例 (即不为null),则已知已嵌入可嵌入实例状态(即, 可从数据库加载FetchType.EAGER嵌入的或由应用程序分配的- ).

...

如果基本属性的状态已从数据库中加载或由以下对象分配,则认为该基本属性已加载 该应用程序.

因此,假设您从数据库中加载了Car实例(例如,它不是通过#getReference()获得的Car实例),则基本属性被视为已加载&分配.

I'm trying to detect the N+1 problem in my code. Every example I've found of the issue always involves two entities, which doesn't really explains if that could also happen to single entities.

The general example is: A car has many wheels. For each car I want to get every wheel.

Select * from cars
Select * from wheels where carId=?

or

List<Car> cars = getCarsFromDB();
for(Car car : cars){
   List<Wheel> wheels = car.getWheels(); //Wheels are entities.
}

But what about non-entities?:

List<Car> cars = getCarsFromDB();
for(Car car : cars){
   //select car.plate from Car car where car.id = ?
   String plate = car.getPlate(); //Plate is just a varchar.
}

Does JPA also lazy fetch non-entities? Is this also a N+1 problem?

解决方案

The short answer, it depends.

If you aren't using Hibernate's bytecode enhancement, then any column that is a basic type will be fetched automatically when you load the entity, therefore they're not lazy nor do they introduce an additional query to make them available.

So in your case, the plate is populated when the Car instance was created.

Now, if you're using Hibernate's bytecode enhancement and you specifically annotate the field to be @Lazy, then that field is lazy and would incur a database query cost when you access the field for the first time, just like a lazy association.

In this scenario, what you can do to avoid the N+1 problem (here where N is each lazy annotated field), you can specify @LazyGroup and group a number of lazy initialized fields together so that when one in the group is accessed, the remainder of them will be loaded simultaneously.

But again, the latter case I described above only applies if you're using bytecode enhancement and when you specifically specify that a field is to be lazily loaded.

JPA Specific

The JPA specification states the following:

3.2.9:

An entity is considered to be loaded if all attributes with FetchType.EAGER—whether explictly specified or by default—(including relationship and other collection-valued attributes) have been loaded from the database or assigned by the application. Attributes with FetchType.LAZY may or may not have been loaded. The available state of the entity instance and associated instances is as described in section 3.2.7.

An attribute that is an embeddable is considered to be loaded if the embeddable attribute was loaded from the database or assigned by the application, and, if the attribute references an embeddable instance (i.e., is not null), the embeddable instance state is known to be loaded (i.e., all attributes of the embeddable with FetchType.EAGER have been loaded from the database or assigned by the applica- tion).

...

A basic attribute is considered to be loaded if its state has been loaded from the database or assigned by the application.

So given you have a Car instance loaded from the database (e.g. it isn't a Car instance you obtained by #getReference() for example), basic attributes are considered loaded & assigned.

这篇关于JPA是否也懒于原始属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆