2013-04-25 10 views
5

Ho un problema riguardante la query jpa. Ci sono due tavoli IE tavolo Post e tavolo Tag C'è molti a molti tra Post e TagIN e = operatore in linguaggio di interrogazione JPA

Ora voglio scrivere una query in modo tale che, quando più tag vengono scelti poi tutti i messaggi associati a tali modifiche dovrebbero essere selezionato. Per esempio,

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

se Tag Amici e Pune sono scelti poi post1 e post 2 dovrebbe essere recuperate se viene scelta una tag boxe allora solo Post 3 devono essere recuperate se i tag di boxe e la motivazione sono scelti poi tutti e tre i post dovrebbero essere recuperati.

ho provato le seguenti cose

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

ma dà l'errore di convalida che

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

Se provo come questo

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

allora conforme bene, ma dopo aver superato un elenco di tag dà errore

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. 

Grazie per aver letto molto :) puoi per favore guidarmi su questo?

come posso ottenere i risultati sopra menzionati? il mio provider di persistenza è EclipseLink

Questo è post entità

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

} 

Si tratta di tag entità

@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

puoi pubblicare il codice della tua posta? Sembra che il problema potrebbe essere lì – kostja

+0

@kostja Aggiunto codice entità come da tuo suggerimento. e si può notare che NamedQuery Tag.selectTagForAllPosts che ha recuperato tutti i tag per l'utente funziona perfettamente. Penso che il recupero dei tag dai post dovrebbe essere simile anche perché ho provato la cosa sopra ma non funziona –

+0

Penso che questa versione semplificata potrebbe funzionare: 'SELECT DISTINTO p FROM Post p WHERE p.tags IN: tags' – kostja

risposta

7

Prova:

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

usare in questo modo:

@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

in realtà non sono in grado di trovare il metodo getNamedQuery e suppongo che l'oggetto di sessione a cui si fa riferimento sia di tipo EntityManager. Inoltre, non sono riuscito a trovare il metodo setParameterList su createNamedQuery. Ho ragione o sto facendo qualcosa di terribilmente sbagliato? –

+0

In realtà, 'setParameterList' funziona su Hibernate. Ho modificato la risposta. Dovrebbe funzionare come previsto (in Eclipselink) ora. – acdcjunior

+1

hey man ... è stato di grande aiuto. Ha funzionato. in realtà dovevo ancora sostituire IN (: tags) con IN: tags. Non capisco perché causa problemi. Inoltre, ho sbagliato a scrivere p.tags nella clausola WHERE invece dei tag. Puoi spiegarmi per favore qual è la differenza? Puoi suggerire un buon tutorial che spiega molto bene la sintassi del linguaggio di query JPA :) grazie per l'aiuto. Voterò appena sarò idoneo –

Problemi correlati