简体   繁体   English

JPA OneToMany 关系中的查询无法按预期工作

[英]JPA Queries in OneToMany Relationships Don't Work as Expected

Given the following Questionnaire entity...鉴于以下Questionnaire实体...

@Entity
@Table(name = "questionnaire")
@EntityListeners(AuditingEntityListener.class)
@Getter
@Builder
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class Questionnaire {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  ...

  @Builder.Default
  @OneToMany(
      mappedBy = "questionnaire",
      fetch = FetchType.LAZY,
      cascade = {CascadeType.ALL})
  private List<Definition> definitionVersions = new ArrayList<>();
}

... and the following Definition entity: ...以及以下Definition实体:

@Entity
@Table(name = "definition")
@IdClass(VersionPk.class)
@EntityListeners(AuditingEntityListener.class)
@Getter
@Setter
@Builder
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class Definition implements Comparable<Definition>, Persistable<Long> {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  @Id
  @Column(name = "version", nullable = false)
  private Integer version;

  ...

  @ManyToOne
  @JoinColumn(name = "definition_id", nullable = false, referencedColumnName = "id")
  private Questionnaire questionnaire;

  @Builder.Default
  @OneToMany(
      mappedBy = "definition",
      fetch = FetchType.LAZY,
      cascade = {CascadeType.ALL})
  private List<Questionnaire> questionnaires = new ArrayList<>();
}

... and for completeness: ...为了完整性:

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Builder
@EqualsAndHashCode
public class VersionPk implements Serializable {

  private Long id;
  private Integer version;
}

For instance, the mechanism above is just to manage many versions of the same questionnaire.例如,上述机制只是管理同一份问卷的多个版本。 Now let's suppose I want to retrieve version 2 of a questionnaire... here below is my custom query:现在假设我要检索问卷的第 2 版……下面是我的自定义查询:

@Repository
public interface QuestionnaireRepository extends JpaRepository<Questionnaire, Long> {

  String QUERY_FIND_BY_ID_AND_VERSION =
    "select q from Questionnaire q"
      + " join q.definitionVersions v"
      + " where q.id = ?1 and v.version = ?2";

  @Query(value = QUERY_FIND_BY_ID_AND_VERSION)
  Optional<Questionnaire> findByIdAndVersion(Long id, Integer version);

  ...
}

I'd expect that definitionVersions in Questionnaire contains only the specified Definition version;我希望Questionnaire中的definitionVersions版本仅包含指定的Definition版本; instead, I always get all the definitions associated with a given Questionnaire .相反,我总是得到与给定Questionnaire相关的所有definitions Am I missing something?我错过了什么吗?

You are filtering for a questionnaire that has version=2, but the questionnaire you are fetching isn't complete unless it contains all the details (and definitions) that you've mapped to it.您正在过滤版本 = 2 的调查问卷,但您获取的调查问卷不完整,除非它包含您映射到的所有详细信息(和定义)。 JPA does not apply the filters to the query results themselves - some JPA providers allow hooks to do so, but this generally causes issues when the managed entity is 'saved' back, as the data within it is incomplete. JPA 不会将过滤器应用于查询结果本身 - 一些 JPA 提供程序允许挂钩这样做,但这通常会在托管实体“保存”回来时导致问题,因为其中的数据不完整。

If you want only the definition/questionaire pair, put them in your query for selection:如果您只想要定义/问卷对,请将它们放在您的查询中以供选择:

String QUERY_FIND_BY_ID_AND_VERSION =
    "select v, q from Questionnaire q"
      + " join q.definitionVersions v"
      + " where q.id = ?1 and v.version = ?2";

This will then return a list holding a Object[2], containing a Definition and Questionnaire for each result that matches.然后,这将返回一个包含 Object[2] 的列表,其中包含每个匹配结果的定义和问卷。 Use that Definition instead of accessing the Questionnaire's definitionVersions list.使用该定义而不是访问问卷的定义版本列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM