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

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

问题描述

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



一般示例是:A汽车有很多轮子。对于每辆汽车,我都希望得到每个车轮。

 从汽车中选择* 
从车轮中选择* carId =?

  List< Car>汽车= getCarsFromDB(); 
代表(汽车:汽车){
List< Wheel>车轮= car.getWheels(); //轮子是实体。
}

但是非实体呢?

  List< Car>汽车= getCarsFromDB(); 
for(汽车:汽车){
//从汽车中选择car.plate,其中car.id =吗?
字符串板= car.getPlate(); // Plate只是一个varchar。
}

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

解决方案

简短的答案,取决于情况。



如果您没有使用Hibernate的字节码增强功能,则在加载实体时会自动获取任何基本类型的列,因此它们既不懒惰,也不引入额外的查询以使其可用。



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



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



在这种情况下,您可以做什么为避免N + 1问题(此处N是每个懒惰的注释字段),您可以指定 @LazyGroup 并将多个懒惰的初始化字段组合在一起,以便当该组是acc



但同样,上述第二种情况仅适用于使用字节码增强功能且



JPA特定



JPA规范陈述以下内容:


3.2.9:



实体被认为是如果具有FetchType.EAGER的所有属性(无论是显式指定的
还是默认情况下的所有属性)(包括关系和其他具有集合值的属性)已从数据库中装入
或由应用程序分配,则将被装入。可能尚未加载具有FetchType.LAZY或
的属性。实体实例和关联实例的可用状态如3.2.7节中所述。$

如果满足以下条件,则认为是可嵌入属性:可嵌入属性已从数据库中加载
或由应用程序分配,并且,如果该属性引用了可嵌入实例
(即不为null),则已知已嵌入可嵌入实例状态(即,则可从数据库加载或由应用程序分配的可嵌入FetchType.EAGER的
的所有属性)。





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


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


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天全站免登陆