QueryDSL 和多对多关系
QueryDSL and ManyToMany relationships
在一个项目中,我有以下实体:具有连接到关键字的模板部分的模板。这两个关系都是@ManyToMany
。一些代码:
@NoArgsConstructor
@Getter
@Setter
@Entity
@Table(name = "TEMPLATE")
public class TemplateEntity extends SystemFlagEntity {
...
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "TEMPLATEPART_CATALOGUE",
joinColumns = @JoinColumn(name = "C_FK_TEMPLATE", referencedColumnName = "C_I_IDF"),
inverseJoinColumns = @JoinColumn(name = "C_FK_TEMPLATEPART", referencedColumnName = "C_I_IDF"))
Set<TemplatePartEntity> templatePartsCatalogue = new HashSet<>();
}
@ToString
@NoArgsConstructor
@Getter
@Setter
@Entity
@Table(name = "TEMPLATEPART")
public class TemplatePartEntity extends SystemFlagEntity {
...
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "TEMPLATEPART_KEYWORD",
joinColumns = @JoinColumn(name = "C_FK_TEMPLATEPART"),
inverseJoinColumns = @JoinColumn(name = "C_FK_KEYWORD"))
Set<KeywordEntity> keywords = new HashSet<>();
}
@NoArgsConstructor
@Getter
@Setter
@Entity
@Table(name = "KEYWORD")
public class KeywordEntity extends LabeledEntity {
...
}
然后我尝试查找与具有给定 ID 的某个模板相关的关键字。我用 QueryDSL
使用这个谓词来做到这一点:
public Iterable<KeywordEntity> findCatalogueKeywordsForTemplate(Long id) {
return findAll(
QKeywordEntity.keywordEntity.in(QTemplateEntity.templateEntity.templatePartsCatalogue.any().keywords)
.and(QTemplateEntity.templateEntity.id.eq(id))
);
}
由于某种原因,谓词根本无法很好地处理。尝试调用方法时出现此错误:
org.hibernate.hql.internal.ast.QuerySyntaxException:
templateEntity.templatePartsCatalogue is not mapped [select
keywordEntity\nfrom
mypackage.core.domain.model.KeywordEntity
keywordEntity\nwhere exists (select 1\nfrom
templateEntity.templatePartsCatalogue as
templateEntity_templatePartsCatalogue_0\nwhere keywordEntity member of
templateEntity_templatePartsCatalogue_0.keywords) and
templateEntity.id = ?1]; nested exception is
java.lang.IllegalArgumentException:
org.hibernate.hql.internal.ast.QuerySyntaxException:
templateEntity.templatePartsCatalogue is not mapped [select
keywordEntity\nfrom
mypackage.core.domain.model.KeywordEntity
keywordEntity\nwhere exists (select 1\nfrom
templateEntity.templatePartsCatalogue as
templateEntity_templatePartsCatalogue_0\nwhere keywordEntity member of
templateEntity_templatePartsCatalogue_0.keywords) and
templateEntity.id = ?1]
它似乎没有很好地处理 @ManyToMany
关联。关于如何解决此问题的任何想法?我知道我可以明确地使用 JPAQuery
,但我想改用 Predicate
。
看到 QueryDSL
's creator 的回答后,我发现我误解了谓词的工作方式。
此查询无需显式定义多对多关联表即可工作:
public Iterable<KeywordEntity> findCatalogueKeywordsForTemplate(Long id) {
return new JPAQuery<>(entityManager)
.select(QKeywordEntity.keywordEntity)
.from(QTemplateEntity.templateEntity)
.innerJoin(QTemplateEntity.templateEntity.templatePartsCatalogue, QTemplatePartEntity.templatePartEntity)
.innerJoin(QTemplatePartEntity.templatePartEntity.keywords, QKeywordEntity.keywordEntity)
.where(interceptPredicate(QTemplateEntity.templateEntity.id.eq(id)))
.distinct()
.fetch();
}
在一个项目中,我有以下实体:具有连接到关键字的模板部分的模板。这两个关系都是@ManyToMany
。一些代码:
@NoArgsConstructor
@Getter
@Setter
@Entity
@Table(name = "TEMPLATE")
public class TemplateEntity extends SystemFlagEntity {
...
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "TEMPLATEPART_CATALOGUE",
joinColumns = @JoinColumn(name = "C_FK_TEMPLATE", referencedColumnName = "C_I_IDF"),
inverseJoinColumns = @JoinColumn(name = "C_FK_TEMPLATEPART", referencedColumnName = "C_I_IDF"))
Set<TemplatePartEntity> templatePartsCatalogue = new HashSet<>();
}
@ToString
@NoArgsConstructor
@Getter
@Setter
@Entity
@Table(name = "TEMPLATEPART")
public class TemplatePartEntity extends SystemFlagEntity {
...
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "TEMPLATEPART_KEYWORD",
joinColumns = @JoinColumn(name = "C_FK_TEMPLATEPART"),
inverseJoinColumns = @JoinColumn(name = "C_FK_KEYWORD"))
Set<KeywordEntity> keywords = new HashSet<>();
}
@NoArgsConstructor
@Getter
@Setter
@Entity
@Table(name = "KEYWORD")
public class KeywordEntity extends LabeledEntity {
...
}
然后我尝试查找与具有给定 ID 的某个模板相关的关键字。我用 QueryDSL
使用这个谓词来做到这一点:
public Iterable<KeywordEntity> findCatalogueKeywordsForTemplate(Long id) {
return findAll(
QKeywordEntity.keywordEntity.in(QTemplateEntity.templateEntity.templatePartsCatalogue.any().keywords)
.and(QTemplateEntity.templateEntity.id.eq(id))
);
}
由于某种原因,谓词根本无法很好地处理。尝试调用方法时出现此错误:
org.hibernate.hql.internal.ast.QuerySyntaxException: templateEntity.templatePartsCatalogue is not mapped [select keywordEntity\nfrom mypackage.core.domain.model.KeywordEntity keywordEntity\nwhere exists (select 1\nfrom templateEntity.templatePartsCatalogue as templateEntity_templatePartsCatalogue_0\nwhere keywordEntity member of templateEntity_templatePartsCatalogue_0.keywords) and templateEntity.id = ?1]; nested exception is java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: templateEntity.templatePartsCatalogue is not mapped [select keywordEntity\nfrom mypackage.core.domain.model.KeywordEntity keywordEntity\nwhere exists (select 1\nfrom templateEntity.templatePartsCatalogue as templateEntity_templatePartsCatalogue_0\nwhere keywordEntity member of templateEntity_templatePartsCatalogue_0.keywords) and templateEntity.id = ?1]
它似乎没有很好地处理 @ManyToMany
关联。关于如何解决此问题的任何想法?我知道我可以明确地使用 JPAQuery
,但我想改用 Predicate
。
看到 QueryDSL
's creator 的回答后,我发现我误解了谓词的工作方式。
此查询无需显式定义多对多关联表即可工作:
public Iterable<KeywordEntity> findCatalogueKeywordsForTemplate(Long id) {
return new JPAQuery<>(entityManager)
.select(QKeywordEntity.keywordEntity)
.from(QTemplateEntity.templateEntity)
.innerJoin(QTemplateEntity.templateEntity.templatePartsCatalogue, QTemplatePartEntity.templatePartEntity)
.innerJoin(QTemplatePartEntity.templatePartEntity.keywords, QKeywordEntity.keywordEntity)
.where(interceptPredicate(QTemplateEntity.templateEntity.id.eq(id)))
.distinct()
.fetch();
}