2013-04-25 37 views
5

Tôi gặp sự cố liên quan đến truy vấn jpa. Có hai bảng có nghĩa là Bảng bài và bảng Tag Có nhiều mối quan hệ giữa Đăng và ThẻIN và = toán tử trong ngôn ngữ truy vấn JPA

Bây giờ tôi muốn viết truy vấn sao cho khi nhiều thẻ được chọn thì tất cả các bài đăng được liên kết với các thẻ đó phải là đã chọn. Ví dụ,

post1 has tags friends and motivation 
post2 has tags motivation and pune 
post3 has tag boxing 

nếu thẻ bạn bè và pune được chọn sau đó post1 và gửi 2 nên được lấy ra nếu thẻ đấm bốc được chọn sau đó chỉ gửi 3 nên được lấy ra nếu thẻ đấm bốc và động lực được lựa chọn sau đó cả ba bài đăng phải được truy xuất.

tôi đã cố gắng sau điều

SELECT DISTINCT p FROM Post p JOIN p.tags tags WHERE p.tags IN :tags 

nhưng nó mang lại cho lỗi validator rằng

The state field path 'p.tags' cannot be resolved to a collection type. 

Nếu tôi cố gắng như thế này

SELECT DISTINCT p FROM Post p JOIN p.tags tags WHERE p.tags = :tags 

sau đó nó tuân thủ tốt nhưng sau khi đi qua một danh sách các thẻ cho lỗi

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. 

Cảm ơn bạn đã đọc nhiều điều này :) bạn có thể hướng dẫn tôi về điều này không?

làm cách nào tôi có thể đạt được kết quả được đề cập ở trên? cung cấp bền bỉ của tôi là EclipseLink

Đây là bài thực thể

@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 + "]"; 
} 

} 

Đây là Tag Entity

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

} 
+0

bạn có thể vui lòng đăng mã của pháp nhân Bài đăng của mình không? Có vẻ như vấn đề có thể ở đó – kostja

+0

@kostja Đã thêm mã thực thể theo đề xuất của bạn. và bạn có thể nhận thấy rằng thẻ NamedQuery Tag.selectTagForAllPosts đã truy xuất tất cả các thẻ cho người dùng hoạt động tốt. Tôi nghĩ rằng lấy thẻ từ bài viết cũng nên tương tự thats lý do tại sao tôi đã thử ở trên điều nhưng nó không hoạt động –

+0

Tôi nghĩ rằng phiên bản này đơn giản có thể làm việc: 'CHỌN DISTINCT p FROM Post p WHERE p.tags IN: tags' – kostja

Trả lời

7

Hãy thử:

... 
    @NamedQuery(name = "Post.selectPostsByTags", query = 
     "SELECT DISTINCT p FROM Post p JOIN p.tags tags WHERE tags IN (:tags)") }) 
public class Post implements Serializable { 
    ... 

Sử dụng nó như thế này:

@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); 
} 
+0

thực ra tôi không thể tìm thấy phương thức getNamedQuery chút nào, và tôi cho rằng đối tượng phiên mà bạn đang đề cập đến là kiểu EntityManager. Ngoài ra, tôi không thể tìm thấy phương thức setParameterList trên createNamedQuery. Tôi có đúng hay tôi đang làm điều gì đó khủng khiếp sai? –

+0

Thực ra, 'setParameterList' hoạt động trên Hibernate. Tôi đã chỉnh sửa câu trả lời. Nên làm việc như mong đợi (trong Eclipselink) bây giờ. – acdcjunior

+1

hey người đàn ông ... đó là một trợ giúp lớn. Nó đã làm việc. thực sự tôi vẫn phải thay thế thẻ IN (: tags) bằng IN:. Tôi không hiểu tại sao nó gây ra vấn đề. Ngoài ra, tôi đã sai khi viết p.tags trong mệnh đề WHERE thay vì thẻ. Bạn có thể giải thích cho tôi sự khác biệt là gì không? Bạn có thể vui lòng đề xuất một hướng dẫn tốt giải thích cú pháp ngôn ngữ truy vấn JPA rất tốt :) cảm ơn sự giúp đỡ của bạn. Tôi sẽ bỏ phiếu ngay sau khi tôi đủ điều kiện –

Các vấn đề liên quan