2013-04-25 6 views
5

Ich habe ein Problem in Bezug auf JPA-Abfrage. Es gibt zwei Tabellen, dh Beitrag Tisch und Tag Tisch Es zu viele Beziehung zwischen Pfosten viele und TagIN und = Operator in JPA-Abfragesprache

Jetzt möchte ich eine Abfrage schreiben, so dass, wenn mehrere Tags gewählt werden dann alle mit diesen Tags zugeordnet Beiträge sein sollten ausgewählt. Zum Beispiel

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

wenn Tags Freunde und pune gewählt werden dann post1 und 2 Post sollte wenn Tag Boxen dann nur 3 Post gewählt abgerufen werden sollen wenn Tags Boxen und Motivation werden dann drei ausgewählt abgerufen werden alle Beiträge sollten abgerufen werden.

Ich habe versucht, folgende Dinge

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

aber es Validator Fehler gibt, dass

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

Wenn ich wie diese versuchen

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

dann erfüllt es in Ordnung, aber nach einer Liste der Weitergabe Tags gibt es Fehler

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. 

Vielen Dank für das Lesen so viel :) können Sie mir bitte dabei helfen?

Wie erreiche ich die oben genannten Ergebnisse? meine Persistenz-Provider ist Eclipse

Dies ist Entität Beitrag

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

} 

Dies ist 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

können Sie bitte den Code Ihrer Post-Entität posten? Sieht so aus, als ob das Problem da sein könnte – kostja

+0

@kostja Entity-Code gemäß Ihren Vorschlägen hinzugefügt. und Sie können feststellen, dass das NamedQuery Tag.selectTagForAllPosts, das alle Tags für den Benutzer abgerufen hat, einwandfrei funktioniert. Ich denke, das Abrufen von Tags aus Posts sollte auch ähnlich sein, warum ich oben Ding versucht habe, aber es funktioniert nicht –

+0

Ich denke, diese vereinfachte Version könnte funktionieren: 'SELECT DISTINCT p FROM Post p WHERE p.tags IN: tags' – kostja

Antwort

7

Versuchen:

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

es wie folgt verwendet:

@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

eigentlich bin ich nicht in der Lage, getNamedQuery Methode überhaupt zu finden, und ich nehme an, das Sitzungsobjekt, das Sie beziehen, ist vom Typ EntityManager. Außerdem konnte ich die setParameterList-Methode in createNamedQuery nicht finden. Habe ich Recht oder mache ich etwas schrecklich falsch? –

+0

Tatsächlich arbeitet 'setParameterList' in Hibernate. Ich habe die Antwort bearbeitet. Sollte jetzt wie erwartet funktionieren (in Eclipselink). – acdcjunior

+1

Hey Mann ... das war eine große Hilfe. Es funktionierte. eigentlich musste ich noch IN (: tags) durch IN: tags ersetzen. Ich verstehe nicht, warum es Probleme verursacht. Auch war ich falsch beim Schreiben von p.tags in WHERE-Klausel anstelle von Tags. Können Sie mir bitte erklären, was der Unterschied ist? Können Sie bitte vorschlagen, ein gutes Tutorial, das JPA Abfrage Sprache Syntax sehr gut erklärt :) danke für die Hilfe. Ich werde abstimmen, sobald ich berechtigt bin –