6

我对 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,如果选择了标签装箱和动机,则应仅检索post 3,则应检索所有三个帖子。

我尝试了以下事情

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

这是 Post 实体

@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;
}

}
4

1 回答 1

7

尝试:

    ...
    @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);
}
于 2013-04-26T02:10:03.317 回答