Spring & Hibernate:为什么获取 1 个惰性字段会触发加载所有其他惰性字段
Spring & Hibernate: Why fetch 1 lazy field triggers loading all other lazy fields
在我的应用程序中,我有一个 Staff
实体,其中包含许多像这样的延迟加载字段。
@Entity(name="CommonStaff")
@Table(name="staff")
@Getter @Setter
public class Staff implements Serializable {
...
@ManyToOne(fetch=FetchType.LAZY)
@LazyToOne(LazyToOneOption.NO_PROXY)
@JoinColumn(name="nationality", referencedColumnName="code", insertable=false, updatable=false)
private Nationality nationality;
@ManyToOne(fetch=FetchType.LAZY)
@LazyToOne(LazyToOneOption.NO_PROXY)
@JoinColumn(name="marital_status", referencedColumnName="code", insertable=false, updatable=false)
private MaritalStatus maritalStatus;
...
}
当我加载 Staff
记录时,none 字段按预期被急切加载。但是,例如,当我触发 getNationality()
时,我看到框架也在执行 SQL 以加载 MaritalStatus
。我一直在尝试找到解决此问题的方法,但找不到任何有用的资源。如果您能指出我的方向,我将不胜感激。
一些示例代码。
@Autowired
@Qualifier("dataModuleStaffRepo")
private StaffRepo staffRepo;
@CustomerTransactional
@GetMapping("/profile")
public void testProfile(@RequestParam String userId) {
Optional<Staff> staff = staffRepo.findByUserId(userId);
if (staff.isPresent()) {
System.out.println(staff.get().getName());
System.out.println(staff.get().getNationality().getName());
}
}
下面是我在控制台中看到的内容。打印员工姓名后,getNationality()
也触发加载MaritalStatus
。
Edgar Rey Tann
2020-04-16 14:29:40,283 DEBUG [http-nio-9000-exec-2] org.hibernate.SQL :
/* sequential select
com.ft.common.db.customer.domain.Staff */ select
staff_.marital_status as marital19_23_,
staff_.nationality as nationa22_23_
from
staff staff_
where
staff_.id=?
2020-04-16 14:29:40,283 TRACE [http-nio-9000-exec-2] org.hibernate.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [660]
2020-04-16 14:29:40,291 DEBUG [http-nio-9000-exec-2] org.hibernate.SQL :
/* load com.ft.common.db.customer.domain.MaritalStatus */ select
maritalsta0_.id as id1_9_0_,
maritalsta0_.code as code2_9_0_,
maritalsta0_.description as descript3_9_0_,
maritalsta0_.name as name4_9_0_,
maritalsta0_.order_id as order_id5_9_0_,
maritalsta0_.short_name as short_na6_9_0_
from
marital_status maritalsta0_
where
maritalsta0_.code=?
2020-04-16 14:29:40,291 TRACE [http-nio-9000-exec-2] org.hibernate.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [MAR_2]
2020-04-16 14:29:40,298 DEBUG [http-nio-9000-exec-2] org.hibernate.SQL :
/* load com.ft.common.db.customer.domain.Nationality */ select
nationalit0_.id as id1_16_0_,
nationalit0_.code as code2_16_0_,
nationalit0_.description as descript3_16_0_,
nationalit0_.name as name4_16_0_,
nationalit0_.order_id as order_id5_16_0_,
nationalit0_.short_name as short_na6_16_0_
from
nationality nationalit0_
where
nationalit0_.code=?
2020-04-16 14:29:40,298 TRACE [http-nio-9000-exec-2] org.hibernate.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [NAT_I]
Indonesian
默认情况下,实体的所有惰性属性class 都属于名为 DEFAULT 的组。获取 DEFAULT 组的任何 属性 也会获取其他组。为了解决这个问题,我们需要使用 @LazyGroup
注释定义我们希望单独获取的组。
因此,我们使用@LazyGroup 注释对国籍和婚姻状况进行注释,如下所示。
@ManyToOne(fetch=FetchType.LAZY)
@LazyToOne(LazyToOneOption.NO_PROXY)
@LazyGroup("nationality")
@JoinColumn(name="nationality", referencedColumnName="code", insertable=false, updatable=false)
private Nationality nationality;
@ManyToOne(fetch=FetchType.LAZY)
@LazyToOne(LazyToOneOption.NO_PROXY)
@LazyGroup("maritalStatus")
@JoinColumn(name="marital_status", referencedColumnName="code", insertable=false, updatable=false)
private MaritalStatus maritalStatus;
希望您正在使用字节码增强功能进行无代理延迟抓取
在我的应用程序中,我有一个 Staff
实体,其中包含许多像这样的延迟加载字段。
@Entity(name="CommonStaff")
@Table(name="staff")
@Getter @Setter
public class Staff implements Serializable {
...
@ManyToOne(fetch=FetchType.LAZY)
@LazyToOne(LazyToOneOption.NO_PROXY)
@JoinColumn(name="nationality", referencedColumnName="code", insertable=false, updatable=false)
private Nationality nationality;
@ManyToOne(fetch=FetchType.LAZY)
@LazyToOne(LazyToOneOption.NO_PROXY)
@JoinColumn(name="marital_status", referencedColumnName="code", insertable=false, updatable=false)
private MaritalStatus maritalStatus;
...
}
当我加载 Staff
记录时,none 字段按预期被急切加载。但是,例如,当我触发 getNationality()
时,我看到框架也在执行 SQL 以加载 MaritalStatus
。我一直在尝试找到解决此问题的方法,但找不到任何有用的资源。如果您能指出我的方向,我将不胜感激。
一些示例代码。
@Autowired
@Qualifier("dataModuleStaffRepo")
private StaffRepo staffRepo;
@CustomerTransactional
@GetMapping("/profile")
public void testProfile(@RequestParam String userId) {
Optional<Staff> staff = staffRepo.findByUserId(userId);
if (staff.isPresent()) {
System.out.println(staff.get().getName());
System.out.println(staff.get().getNationality().getName());
}
}
下面是我在控制台中看到的内容。打印员工姓名后,getNationality()
也触发加载MaritalStatus
。
Edgar Rey Tann
2020-04-16 14:29:40,283 DEBUG [http-nio-9000-exec-2] org.hibernate.SQL :
/* sequential select
com.ft.common.db.customer.domain.Staff */ select
staff_.marital_status as marital19_23_,
staff_.nationality as nationa22_23_
from
staff staff_
where
staff_.id=?
2020-04-16 14:29:40,283 TRACE [http-nio-9000-exec-2] org.hibernate.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [660]
2020-04-16 14:29:40,291 DEBUG [http-nio-9000-exec-2] org.hibernate.SQL :
/* load com.ft.common.db.customer.domain.MaritalStatus */ select
maritalsta0_.id as id1_9_0_,
maritalsta0_.code as code2_9_0_,
maritalsta0_.description as descript3_9_0_,
maritalsta0_.name as name4_9_0_,
maritalsta0_.order_id as order_id5_9_0_,
maritalsta0_.short_name as short_na6_9_0_
from
marital_status maritalsta0_
where
maritalsta0_.code=?
2020-04-16 14:29:40,291 TRACE [http-nio-9000-exec-2] org.hibernate.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [MAR_2]
2020-04-16 14:29:40,298 DEBUG [http-nio-9000-exec-2] org.hibernate.SQL :
/* load com.ft.common.db.customer.domain.Nationality */ select
nationalit0_.id as id1_16_0_,
nationalit0_.code as code2_16_0_,
nationalit0_.description as descript3_16_0_,
nationalit0_.name as name4_16_0_,
nationalit0_.order_id as order_id5_16_0_,
nationalit0_.short_name as short_na6_16_0_
from
nationality nationalit0_
where
nationalit0_.code=?
2020-04-16 14:29:40,298 TRACE [http-nio-9000-exec-2] org.hibernate.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [NAT_I]
Indonesian
默认情况下,实体的所有惰性属性class 都属于名为 DEFAULT 的组。获取 DEFAULT 组的任何 属性 也会获取其他组。为了解决这个问题,我们需要使用 @LazyGroup
注释定义我们希望单独获取的组。
因此,我们使用@LazyGroup 注释对国籍和婚姻状况进行注释,如下所示。
@ManyToOne(fetch=FetchType.LAZY)
@LazyToOne(LazyToOneOption.NO_PROXY)
@LazyGroup("nationality")
@JoinColumn(name="nationality", referencedColumnName="code", insertable=false, updatable=false)
private Nationality nationality;
@ManyToOne(fetch=FetchType.LAZY)
@LazyToOne(LazyToOneOption.NO_PROXY)
@LazyGroup("maritalStatus")
@JoinColumn(name="marital_status", referencedColumnName="code", insertable=false, updatable=false)
private MaritalStatus maritalStatus;
希望您正在使用字节码增强功能进行无代理延迟抓取