有两种型号:Page&标签。一页可以有很多标签。
页:
public class Page {
@Id
@GeneratedValue
@Column(name="page_id")
private Integer id;
// TAGS
@OneToMany(orphanRemoval=true, mappedBy="pageId", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<Tag> tag = new HashSet<Tag>();
}
标签:
public class Tag {
// GENERIC FIELDS
@Id
@GeneratedValue
private Integer id;
@Index(name = "tag")
@Column
private String tag;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name="page_id")
private Page pageId;
}
现在的任务是选择具有特定标记的所有页面。使用普通的MySQL我会做(工作正常):
SELECT * from Page join Tag on Page.page_id = Tag.page_id where Tag.tag = 'sport'
但是Hibernate抱怨我是这样做的:
List<Page> pageList = (List<Page>) session.createQuery("from Page join Tag on Page.page_id = Tag.page_id where Tag.tag = 'sport'").list();
// ERROR: [QuerySyntaxException: unexpected token: on near line 1, column 27 [from models.Page join Tag on Page.page_id = Tag.page_id where tag = 'sport']]
当我删除&#34;意外令牌&#34;然后Hibernate再次抱怨:
List<Page> pageList = (List<Page>) session.createQuery("from Page join Tag where tag = 'sport'").list();
[TypeMismatchException: left and right hand sides of a binary logic operator were incompatibile [java.util.Set(models.Page.tag) : string]]
第二种方法的问题似乎是,Page.tag
是Set
,Hibernate似乎无法使用该查询的结果创建它。
那我怎么解决这个问题呢?查询有问题还是有办法解决TypeMismatchException
?
奖金问题: 我找到了以下解决方案,它在某种程度上起作用..至少是一点点:
List<Page> pageList = (List<Page>) session.createQuery("from Page where id in (from Tag where tag = 'sport')").list();
它有效..但它只提供了一半有Tag&#34; sport&#34;的页面。有人可以解释原因吗?
任何建议都非常感谢!
答案 0 :(得分:1)
在HQL中,您只需使用集合名称加入:
from Page as page left join tag as tags where tags.tag = 'sport'
您的集合标记有一个令人困惑的名称,我将其命名为“tagList”以避免与标记属性(String one)混淆。
答案 1 :(得分:1)
在HQL和JPQL中,如果要在FROM子句之后引用实体属性,则需要指定别名;所以你的查询将是:
from Page p join Tag t on p.id = t.pageId where t.tag = 'sport'
还有另一种隐式连接语法:
from Page p where p.tag.tag = 'sport'
要完全符合JPQL,您还需要指定select子句:
select p from Page p where p.tag.tag = 'sport'