2012-08-27 4 views
0

Я пытаюсь использовать следующий кодСинтаксическая ошибка разбора запроса (JPA)

Query query; 
query = entityManager.createQuery("SELECT g.name FROM group g INNER JOIN user_group ug INNER JOIN user u ON u.id = ug.userid AND ug.groupoid = g.id AND u.name = ?1 AND u.password = ?2"); 
query.setParameter(1, user.getName()); 
query.setParameter(2, user.getPassword()); 

Object result = (Object) query.getSingleResult(); 
String name = (String) result; 

И я получаю следующее исключение при запуске кода

Caused by: Exception [EclipseLink-8023] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.JPQLException 
Exception Description: Syntax error parsing the query [SELECT g.name FROM group g INNER JOIN user_group ug INNER JOIN user u ON u.id = ug.userid AND ug.groupoid = g.id AND u.name = ?1 AND u.password = ?2]. 
Internal Exception: org.eclipse.persistence.internal.libraries.antlr.runtime.EarlyExitException 
    at org.eclipse.persistence.exceptions.JPQLException.syntaxError(JPQLException.java:352) 
    at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.handleRecognitionException(JPQLParser.java:354) 
    at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.addError(JPQLParser.java:246) 
    at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.reportError(JPQLParser.java:363) 
    at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.joinAssociationPathExpression(JPQLParser.java:2746) 
    at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.join(JPQLParser.java:2364) 
    at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.identificationVariableDeclaration(JPQLParser.java:2179) 
    at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.fromClause(JPQLParser.java:2043) 
    at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.selectStatement(JPQLParser.java:364) 
    at org.eclipse.persistence.internal.jpa.parsing.jpql.antlr.JPQLParser.document(JPQLParser.java:281) 
    at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.parse(JPQLParser.java:134) 
    at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.buildParseTree(JPQLParser.java:95) 
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:215) 
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:190) 
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:142) 
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:126) 
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1475) 
    ... 71 more 

Когда я бегу sql-код на консоли mysql, он работает. Наверное, я не правильно делаю JPQL.

Кто-нибудь знает, как сделать правильный запрос?

EDIT: Мой класс Группа:

/* 
* To change this template, choose Tools | Templates 
* and open the template in the editor. 
*/ 
package model.entities; 

import java.io.Serializable; 
import java.util.Collection; 
import javax.persistence.Basic; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.JoinTable; 
import javax.persistence.ManyToMany; 
import javax.persistence.NamedQueries; 
import javax.persistence.NamedQuery; 
import javax.persistence.Table; 
import javax.validation.constraints.Size; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlTransient; 

/** 
* 
* @author Felipe 
*/ 
@Entity 
@Table(name = &quot;grupo&quot;) 
@XmlRootElement 
@NamedQueries({ 
    @NamedQuery(name = &quot;Grupo.findAll&quot;, query = &quot;SELECT g FROM Grupo g&quot;), 
    @NamedQuery(name = &quot;Grupo.findById&quot;, query = &quot;SELECT g FROM Grupo g WHERE g.id = :id&quot;), 
    @NamedQuery(name = &quot;Grupo.findByNome&quot;, query = &quot;SELECT g FROM Grupo g WHERE g.nome = :nome&quot;)}) 
public class Grupo implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = &quot;Id&quot;) 
    private Integer id; 
    @Size(max = 255) 
    @Column(name = &quot;Nome&quot;) 
    private String nome; 
    @JoinTable(name = &quot;usuario_grupo&quot;, joinColumns = { 
     @JoinColumn(name = &quot;GrupoID&quot;, referencedColumnName = &quot;Id&quot;)}, inverseJoinColumns = { 
     @JoinColumn(name = &quot;UsuarioID&quot;, referencedColumnName = &quot;Id&quot;)}) 
    @ManyToMany(fetch = FetchType.EAGER) 
    private Collection&lt;Usuario&gt; usuarioCollection; 

    public Grupo() { 
    } 

    public Grupo(Integer id) { 
     this.id = id; 
    } 

    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    public String getNome() { 
     return nome; 
    } 

    public void setNome(String nome) { 
     this.nome = nome; 
    } 

    @XmlTransient 
    public Collection&lt;Usuario&gt; getUsuarioCollection() { 
     return usuarioCollection; 
    } 

    public void setUsuarioCollection(Collection&lt;Usuario&gt; usuarioCollection) { 
     this.usuarioCollection = usuarioCollection; 
    } 

    @Override 
    public int hashCode() { 
     int hash = 0; 
     hash += (id != null ? id.hashCode() : 0); 
     return hash; 
    } 

    @Override 
    public boolean equals(Object object) { 
     // TODO: Warning - this method won't work in the case the id fields are not set 
     if (!(object instanceof Grupo)) { 
      return false; 
     } 
     Grupo other = (Grupo) object; 
     if ((this.id == null &amp;&amp; other.id != null) || (this.id != null &amp;&amp; !this.id.equals(other.id))) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public String toString() { 
     return &quot;model.entities.Grupo[ id=&quot; + id + &quot; ]&quot;; 
    } 

} 

И мой класс Пользователь:

/* 
* To change this template, choose Tools | Templates 
* and open the template in the editor. 
*/ 
package model.entities; 

import java.io.Serializable; 
import java.util.Collection; 
import javax.persistence.Basic; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.ManyToMany; 
import javax.persistence.NamedQueries; 
import javax.persistence.NamedQuery; 
import javax.persistence.Table; 
import javax.validation.constraints.Size; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlTransient; 

/** 
* 
* @author Felipe 
*/ 
@Entity 
@Table(name = &quot;usuario&quot;) 
@XmlRootElement 
@NamedQueries({ 
    @NamedQuery(name = &quot;Usuario.findAll&quot;, query = &quot;SELECT u FROM Usuario u&quot;), 
    @NamedQuery(name = &quot;Usuario.findById&quot;, query = &quot;SELECT u FROM Usuario u WHERE u.id = :id&quot;), 
    @NamedQuery(name = &quot;Usuario.findBySenha&quot;, query = &quot;SELECT u FROM Usuario u WHERE u.senha = :senha&quot;), 
    @NamedQuery(name = &quot;Usuario.findByNome&quot;, query = &quot;SELECT u FROM Usuario u WHERE u.nome = :nome&quot;)}) 
public class Usuario implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Basic(optional = false) 
    @Column(name = &quot;Id&quot;) 
    private Integer id; 
    @Size(max = 255) 
    @Column(name = &quot;Senha&quot;) 
    private String senha; 
    @Size(max = 255) 
    @Column(name = &quot;Nome&quot;) 
    private String nome; 
    @ManyToMany(mappedBy = &quot;usuarioCollection&quot;, fetch = FetchType.EAGER) 
    private Collection&lt;Grupo&gt; grupoCollection; 

    public Usuario() { 
    } 

    public Usuario(Integer id) { 
     this.id = id; 
    } 

    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    public String getSenha() { 
     return senha; 
    } 

    public void setSenha(String senha) { 
     this.senha = senha; 
    } 

    public String getNome() { 
     return nome; 
    } 

    public void setNome(String nome) { 
     this.nome = nome; 
    } 

    @XmlTransient 
    public Collection&lt;Grupo&gt; getGrupoCollection() { 
     return grupoCollection; 
    } 

    public void setGrupoCollection(Collection&lt;Grupo&gt; grupoCollection) { 
     this.grupoCollection = grupoCollection; 
    } 

    @Override 
    public int hashCode() { 
     int hash = 0; 
     hash += (id != null ? id.hashCode() : 0); 
     return hash; 
    } 

    @Override 
    public boolean equals(Object object) { 
     // TODO: Warning - this method won't work in the case the id fields are not set 
     if (!(object instanceof Usuario)) { 
      return false; 
     } 
     Usuario other = (Usuario) object; 
     if ((this.id == null &amp;&amp; other.id != null) || (this.id != null &amp;&amp; !this.id.equals(other.id))) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public String toString() { 
     return &quot;model.entities.Usuario[ id=&quot; + id + &quot; ]&quot;; 
    } 

} 

ПРИМЕЧАНИЕ: Эти классы был сгенерирован Netbeans. ПРИМЕЧАНИЕ 2. Некоторые имена находятся на португальском языке.

+0

Не могли бы вы разместить свои классы 'User' и' Group'? –

+0

Я отредактировал сообщение, чтобы поставить классы пользователя и группы. –

ответ

1

На самом деле, если вы хотите, чтобы получить имя группы по имени пользователя и пароля, вы можете переписать запрос следующим образом:

SELECT g.nome FROM Grupo g INNER JOIN g.usuarioCollection u 
WHERE u.nome = ?1 AND u.senha = ?2 

Поскольку в JPQL вы работаете с объектами, не с таблицами вы будете использовать в JOIN пунктах association fields это поля, аннотированные @OneToMany и @ManyToMany.

+0

спасибо. Ты лучший. –

0

У вас есть FROM group g. Не group зарезервированное слово?

+0

Фактически имена на португальском языке, и я просто переводил их на английский. но sql работает, а код jpql не –

0

Ваш запрос - это запрос SQL, а не запрос JPQL. JPQL! = SQL. Я также совет против опроса пользователей по имени + пароль, поскольку это довольно дорого. Вместо этого запрашивайте пользователей по их первичному ключу. Ваш запрос должен выглядеть следующим образом:

select g.name from group g where :user in g.users 

Параметр :user должен быть объект пользователя. Вы можете установить это следующим образом:

query.setParameter("user", user); 

Это, как говорится, скажите, пожалуйста, что в столбце «пароль» содержит только зашифрованные и соленых пароли.

+0

Код предназначен только для изучения, но я знаю о рисках. По вашему коду переменная «пользователь» должна быть компонентом сущности, не так ли? Итак, как должна быть таблица в базе данных, поэтому я могу использовать этот запрос jpql? –

Смежные вопросы