【问题标题】:JpaRepository - Inner Join - Subsequent selectsJpaRepository - 内部连接 ​​- 后续选择
【发布时间】: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&lt;ServiceCup&gt; ServiceLanguage“sl”不需要在查询的选择部分。试试看,我相信这就是 hibernate 执行额外查询的原因。

标签: spring-boot spring-data-jpa hibernate-mapping


【解决方案1】:

我只需要使用投影而不是实体来执行一次查询。

ServiceCupProj

public interface ServiceCupProj {

    public Long getId();

    public String getDescription();

    public String getInternalname();
......

存储库

@Repository
public interface CupServiceRepository extends JpaRepository<ServiceCup, Long> {

@Query(value = "select servicecup0_.id as id, servicelan1_.translated_description as description, servicelan1_.translated_name as internalname \n"
            + "from csm_service servicecup0_ inner join csm_service_language servicelan1_ on (servicecup0_.id=servicelan1_.csm_service_id_fk) \n"
            + "where servicelan1_.csm_language_id_fk = :languageId ", nativeQuery = true)
    List<ServiceCupProj> findAllServicesByLanguageId(@Param("languageId") String languageId);
......

在服务层中,我将这个 ServiceCupProj 转换为我需要的实体。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-21
    • 2013-03-16
    • 1970-01-01
    • 2017-11-16
    • 2013-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多