JPA 查询语言中的 IN 和 = 运算符
Posted
技术标签:
【中文标题】JPA 查询语言中的 IN 和 = 运算符【英文标题】:IN and = operator in JPA query language 【发布时间】:2013-04-18 23:32:52 【问题描述】:我有一个关于 jpa 查询的问题。 有两个表,即 Post 表和 Tag 表 Post和Tag之间存在多对多的关系
Now I want to write a query such that when multiple tags are chosen then all the posts associated with those tags should be selected. 例如,
post1 has tags friends and motivation
post2 has tags motivation and pune
post3 has tag boxing
如果选择了标签friends和pune,则应该检索post1和post 2 如果选择了标签装箱,则只应检索帖子 3 如果选择了标签 boxing 和 Motivation,则应检索所有三个帖子。
我尝试了以下事情
SELECT DISTINCT p FROM Post p JOIN p.tags tags WHERE p.tags IN :tags
但它给出了验证器错误
The state field path 'p.tags' cannot be resolved to a collection type.
如果我这样尝试
SELECT DISTINCT p FROM Post p JOIN p.tags tags WHERE p.tags = :tags
然后它可以正常运行,但是在传递标签列表后会出错
java.lang.IllegalArgumentException: You have attempted to set a value of type class java.util.ArrayList for parameter tags with expected type of class com.justme.model.entities.Tag from query string SELECT DISTINCT p FROM Post p JOIN p.tags tags WHERE p.tags = :tags.
感谢您阅读这么多:)您能指导我吗?
我怎样才能达到上面提到的结果? 我的持久性提供者是 eclipseLink
这是帖子实体
@Entity
@NamedQueries(
@NamedQuery(name = "Post.selectAllPosts", query = "SELECT p FROM Post p ORDER BY p.dateCreated DESC"),
@NamedQuery(name = "Post.selectPostForUser", query = "SELECT p FROM Post p WHERE p.user = :user ORDER BY p.dateCreated DESC"),
@NamedQuery(name = "Post.selectPostsByTags", query = "SELECT DISTINCT p FROM Post p JOIN p.tags tags WHERE p.tags IN :tags") )
public class Post implements Serializable
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int idpost;
@Lob
private String content;
private String title;
// bi-directional many-to-one association to User
@ManyToOne(cascade = CascadeType.PERSIST)
@JoinColumn(name = "iduser")
private User user;
// bi-directional many-to-many association to Tag
@ManyToMany(cascade = CascadeType.PERSIST)
@JoinTable(name = "post_tag", joinColumns = @JoinColumn(name = "idpost"), inverseJoinColumns = @JoinColumn(name = "idtag"))
private List<Tag> tags = new ArrayList<Tag>();
@Temporal(TemporalType.DATE)
private Date date = null;
@Temporal(TemporalType.TIMESTAMP)
private Date dateCreated = new Date();
public Post()
public int getIdpost()
return this.idpost;
public void setIdpost(int idpost)
this.idpost = idpost;
public String getContent()
return this.content;
public void setContent(String content)
this.content = content;
public String getTitle()
return this.title;
public void setTitle(String title)
this.title = title;
public User getUser()
return this.user;
public void setUser(User user)
this.user = user;
public List<Tag> getTags()
return this.tags;
public void setTags(List<Tag> tags)
this.tags = tags;
public Date getDate()
return date;
public void setDate(Date date)
this.date = date;
public Date getDateCreated()
return dateCreated;
public void setDateCreated(Date dateCreated)
this.dateCreated = dateCreated;
@Override
public String toString()
return "Post [idpost=" + idpost + ", content=" + content + ", title="
+ title + ", date=" + date + "]";
这是标签实体
@Entity
@NamedQueries(
@NamedQuery(name = "Tag.selectTags", query = "SELECT tag FROM Tag tag WHERE tag.tagName LIKE :keyword"),
@NamedQuery(name = "Tag.selectMatchingTags", query = "SELECT t.tagName FROM Tag t WHERE t.tagName LIKE :keyword"),
@NamedQuery(name = "Tag.selectTagByName", query = "SELECT tag FROM Tag tag WHERE tag.tagName = :tagName"),
@NamedQuery(name = "Tag.selectTagsForAllPosts", query = "SELECT DISTINCT tag FROM Tag tag, Post post JOIN tag.posts posts WHERE post.user = :user"))
public class Tag implements Serializable
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int idtag;
private String tagName;
// bi-directional many-to-many association to Post
@ManyToMany(mappedBy = "tags", cascade = CascadeType.PERSIST)
private List<Post> posts;
public Tag()
public Tag(String tagName)
this.tagName = tagName;
public int getIdtag()
return this.idtag;
public void setIdtag(int idtag)
this.idtag = idtag;
public String getTagName()
return this.tagName;
public void setTagName(String tagName)
this.tagName = tagName;
public List<Post> getPosts()
return this.posts;
public void setPosts(List<Post> posts)
this.posts = posts;
@Override
public String toString()
return tagName;
【问题讨论】:
能否请您发布您的 Post 实体的代码?看起来问题可能存在 @kostja 根据您的建议添加了实体代码。您会注意到为用户检索所有标签的 NamedQuery Tag.selectTagForAllPosts 工作得很好。我认为从帖子中检索标签也应该是相似的,这就是为什么我尝试了上面的事情但它不起作用 我认为这个简化版本可以工作:SELECT DISTINCT p FROM Post p WHERE p.tags IN :tags
@kostja 谢谢你的回答,但是当我写你给我的查询时,它再次显示验证错误,如上所述状态字段路径“p.tags”无法解析为集合类型。
那么我实际上是一无所知,查询和实体对我来说是正确的,很抱歉浪费您的时间。
【参考方案1】:
试试:
...
@NamedQuery(name = "Post.selectPostsByTags", query =
"SELECT DISTINCT p FROM Post p JOIN p.tags tags WHERE tags IN (:tags)") )
public class Post implements Serializable
...
像这样使用它:
@PersistenceContext
public EntityManager em;
...
List<Tag> ltags = new ArrayList<Tag>();
ltags.add(tagOne);
ltags.add(tagTwo);
List<?> list = em.createNamedQuery("Post.selectPostsByTags")
.setParameter("tags", ltags)
.getResultList();
for (Object object : list)
System.out.println("Results: "+object);
【讨论】:
实际上我根本找不到 getNamedQuery 方法,我想您所指的会话对象是 EntityManager 类型的。另外,我在 createNamedQuery 上找不到 setParameterList 方法。我是对的还是我做错了什么? 实际上,setParameterList
在 Hibernate 上工作。我编辑了答案。现在应该可以按预期工作(在 Eclipselink 中)。
嘿,伙计……这是一个很大的帮助。有效。实际上我仍然不得不用 IN :tags 替换 IN (:tags)。我不明白为什么它会导致问题。另外,我在 WHERE 子句而不是标签中写 p.tags 是错误的。你能解释一下有什么区别吗?您能否建议一个很好的教程,它很好地解释了 JPA 查询语言语法:) 谢谢您的帮助。一旦我符合条件,我会立即投票
伙计们,如果我希望传递集合中的所有标签都匹配怎么办? JPA可以吗?以上是关于JPA 查询语言中的 IN 和 = 运算符的主要内容,如果未能解决你的问题,请参考以下文章