我有以下实体
@Builder
@Getter @Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "Employee")
@Table(schema = "core", name = "employee")
public class EmployeeEntity {
@Id
@SequenceGenerator(schema = "core", name = Sequence.EMPLOYEE_ID_SEQ, sequenceName = Sequence.EMPLOYEE_ID_SEQ)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = Sequence.EMPLOYEE_ID_SEQ)
@Column(name = "id", nullable = false, updatable = false)
private Integer id;
@Column(name = "person_id", nullable = false)
private Integer personId;
@Column(name = "user_account_id")
private Integer userAccountId;
@Column(name = "employee_type_id", nullable = false)
private Integer employeeTypeId;
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "person_id", insertable = false, updatable = false)
private PersonEntity person;
@ManyToOne(fetch = FetchType.EAGER, targetEntity = EmployeeTypeEntity.class)
@JoinColumn(name = "employee_type_id", insertable = false, updatable = false)
private EmployeeTypeEntity employeeType;
}
和
@Builder
@Getter @Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "EmployeeType")
@Table(schema = "type", name = "employee_type")
@Cacheable @Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class EmployeeTypeEntity implements TypeTable {
@Id
@Column(name = "id", nullable = false, updatable = false)
private Integer id;
@Column(name = "name", length = 100, nullable = false)
private String name;
@Column(name = "abbreviation", length = 10)
private String abbreviation;
@Column(name = "description", length = 100)
private String description;
@Builder.Default
@Enumerated(EnumType.STRING)
@Column(name = "active", length = 1, nullable = false)
private Active active = Active.Y;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "employeeType", targetEntity = EmployeeEntity.class)
private List<EmployeeEntity> employees;
}
我在 Quarkus 中使用 JPA Hibernate 并使用以下方法
@Override
public Pageable<EmployeeEntity> findAll(PageRequest request) {
var query = employeePanacheRepository.findAll(
Sort.by(request.getSortBy(), Direction.valueOf(request.getSortDirection()))
)
.page(Page.of(request.getPage(), request.getSize()));
return Pageable.<EmployeeEntity>builder()
.content(query.list())
.totalPages(query.pageCount())
.hasPrevious(query.hasPreviousPage())
.hasNext(query.hasNextPage())
.build();
}
这里的问题是为什么当
query.list()
被调用时 Hibernate 会产生两个 Select
Hibernate:
select
ee1_0.id,
ee1_0.employee_type_id,
ee1_0.person_id,
ee1_0.user_account_id
from
core.employee ee1_0
order by
ee1_0.id
offset
? rows
fetch
first ? rows only
Hibernate:
select
ete1_0.id,
ete1_0.abbreviation,
ete1_0.active,
ete1_0.description,
ete1_0.name
from
type.employee_type ete1_0
where
ete1_0.id = any (?)
当我有另一个实体(它是 EmployeeEntity 的父级)并在一个选择中获取所有类型表时,事情变得更加令人困惑
@Builder
@Getter @Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity(name = "Person")
@Table(schema = "core", name = "person")
public class PersonEntity {
@Id
@SequenceGenerator(schema = "core", name = Sequence.PERSON_ID_SEQ, sequenceName = Sequence.PERSON_ID_SEQ)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = Sequence.PERSON_ID_SEQ)
@Column(name = "id", nullable = false, updatable = false)
private Integer id;
@Column(name = "first_name", length = 100, nullable = false)
private String firstName;
@Column(name = "last_name", length = 100, nullable = false)
private String lastName;
@Column(name = "document_number", length = 50, nullable = false)
private String documentNumber;
@Column(name = "document_type_id", nullable = false)
private Integer documentTypeId;
@Column(name = "gender_type_id", nullable = false)
private Integer genderTypeId;
@Column(name = "birth_date", nullable = false)
private LocalDate birthDate;
@Column(name = "email", nullable = false)
private String email;
@Column(name = "mobile_number", nullable = false)
private String mobileNumber;
@UpdateTimestamp
@Column(name = "update_date", nullable = false)
private LocalDateTime updateDate;
@CreationTimestamp
@Column(name = "create_date", nullable = false)
private LocalDateTime createDate;
@Builder.Default
@Enumerated(EnumType.STRING)
@Column(name = "active", length = 1, nullable = false)
private Active active = Active.Y;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "document_type_id", insertable = false, updatable = false)
private DocumentTypeEntity documentType;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "gender_type_id", insertable = false, updatable = false)
private GenderTypeEntity genderType;
}
Hibernate:
select
pe1_0.id,
pe1_0.active,
pe1_0.birth_date,
pe1_0.create_date,
pe1_0.document_number,
dt1_0.id,
dt1_0.abbreviation,
dt1_0.active,
dt1_0.description,
dt1_0.name,
pe1_0.document_type_id,
pe1_0.email,
pe1_0.first_name,
gt1_0.id,
gt1_0.abbreviation,
gt1_0.active,
gt1_0.description,
gt1_0.name,
pe1_0.gender_type_id,
pe1_0.last_name,
pe1_0.mobile_number,
pe1_0.update_date
from
core.person pe1_0
left join
type.document_type dt1_0
on dt1_0.id=pe1_0.document_type_id
left join
type.gender_type gt1_0
on gt1_0.id=pe1_0.gender_type_id
where
pe1_0.id = any (?)
有人可以向我解释为什么 EmployeeEntity 会出现这种奇怪的行为,而 PersonEntity 却不会出现这种奇怪的行为
这实际上是正常的,因为在获取多个实体的请求中 fetchMode 被忽略。
我在新文档中找不到对此的引用,但是这个旧文档指出:
映射文档中定义的获取策略影响:
- 通过 get() 或 load() 检索
- 导航关联时隐式发生的检索
- 条件查询
- 如果使用子选择获取,则进行 HQL 查询
此更多最新文档
也提到了该行为要解决您的问题,您可以使用 join fetch 或实体图(with spring data jpa 或 without)