[英]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.