【发布时间】:2021-03-16 02:12:16
【问题描述】:
当我尝试使用 ServiceLanguage 获取 ServiceCup 列表时遇到问题。当我尝试在我的服务层中操作 ServiceCup 列表时,休眠正在执行第二个查询并再次使用所有 ServiceLanguage 填充我的 ServiceCup。
ServiceCup x ServiceLanguage x LanguageCup
服务杯:
@Data
@Entity
@Table(name = "csm_service")
public class ServiceCup extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
private String context;
// bi-directional many-to-one association to CsmServiceLanguage
@OneToMany(mappedBy = "service")
private List<ServiceLanguage> serviceLanguages;
}
服务语言:
@Data
@Entity
@Table(name = "csm_service_language")
public class ServiceLanguage extends BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "translated_name")
private String translatedName;
// bi-directional many-to-one association to CsmLanguage
@ManyToOne
@JoinColumn(name = "csm_language_id_fk")
private LanguageCup language;
// bi-directional many-to-one association to CsmService
@ManyToOne
@JoinColumn(name = "csm_service_id_fk")
private ServiceCup service;
}
JpaRepository:
@Query(value = "select s, sl from ServiceCup s \n" + "INNER JOIN FETCH ServiceLanguage sl on s.id = sl.service \n"
+ "where sl.language.id = :languageId")
List<ServiceCup> findAllServicesByLanguageId(@Param("languageId") String languageId);
存储库层中的查询:
select *all_fields* from csm_service servicecup0_ inner join csm_service_language servicelan1_ on (servicecup0_.id=servicelan1_.csm_service_id_fk) where servicelan1_.csm_language_id_fk=?
但是在服务层执行很多查询来带来ServiceCup的所有关系。我希望填充 ServiceCup 对象,但仅使用查询中的结果。
我怎样才能得到一个只有查询结果的 ServiceCup 对象?
PS:在我的服务层方法中,我有 @Transactional(readOnly = true),但如果我删除,我无法获取与 ServiceCup 相关的对象。
【问题讨论】:
-
如果从查询
@Query(value = "select s from ServiceCup s \n" + "INNER JOIN FETCH ServiceLanguage sl on s.id = sl.service \n" + "where sl.language.id = :languageId")的选择部分中删除 sl,它是否表现出相同的行为? -
@HopeyOne 但我需要 sl 因为 languageId 不在 ServiceCup 中。
-
您无需选择实体即可在联接中使用它。
OneToMany的默认FetchType是惰性的,ManyToOne的默认值是急切的。我认为即使您没有在查询方法中返回它,选择 ServiceLanguage 也意味着 Hibernate 将急切地获取 ServiceLanguage 实体的每个相关实体。您仍然可以从 ServiceCup 访问相关的 ServiceLanguage 实体,即使它们没有在查询中被选中,并且 hibernate 会根据需要自动加载它们(懒惰FetchType)。 -
@HopeyOne 我怎样才能解决只带我想要的东西? ServiceCup 及其相关的 ServiceLanguage 与 LanguageCup 的 Id?
-
我的建议是您从
select s, sl from ...中删除“sl”,使其读取为select s from ...,因为您的查询方法仅返回List<ServiceCup>ServiceLanguage“sl”不需要在查询的选择部分。试试看,我相信这就是 hibernate 执行额外查询的原因。
标签: spring-boot spring-data-jpa hibernate-mapping