使用 JPA 解析琐碎查询的语法错误

Posted

技术标签:

【中文标题】使用 JPA 解析琐碎查询的语法错误【英文标题】:Syntax error parsing a trivial query with JPA 【发布时间】:2011-06-26 10:30:41 【问题描述】:

我使用 netbeans 向导创建了实体 bean,并试图从数据库中获取数据。无论我使用什么 SQL 查询,它都不起作用。我尝试使用向导创建的命名查询:

@NamedQuery(name = "Usr.findAll", query = "SELECT u FROM Usr u")

返回:

Caused by: Exception [EclipseLink-8025] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Syntax error parsing the query [Usr.findAll], line 1, column 0: unexpected token [Usr].

如果我尝试;

SELECT uid FROM usr;

我明白了:

Caused by: java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager: 
Exception Description: Syntax error parsing the query [SELECT uid FROM usr;], line 0, column -1: unexpected end of query.
Internal Exception: MismatchedTokenException(-1!=78)

即使我尝试:

SELECT * FROM usr

我明白了:

Caused by: Exception [EclipseLink-8025] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Syntax error parsing the query [SELECT * FROM usr], line 1, column 7: unexpected token [*].

我获取数据的路线是:

@PersistenceContext
EntityManager em;
....

em=Persistence.createEntityManagerFactory("SchoolPU").createEntityManager();
List users = em.createQuery("SELECT * FROM usr").getResultList();

谁能帮我解决这个小问题?

Usr 实体类:

import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

/**
 *
 * @author danizmax
 */
@Entity
@Table(name = "USR")
@NamedQueries(
    @NamedQuery(name = "Usr.findAll", query = "SELECT u FROM Usr u"),
    @NamedQuery(name = "Usr.findByUid", query = "SELECT u FROM Usr u WHERE u.uid = :uid"),
    @NamedQuery(name = "Usr.findByPassword", query = "SELECT u FROM Usr u WHERE u.password = :password"),
    @NamedQuery(name = "Usr.findByFistname", query = "SELECT u FROM Usr u WHERE u.fistname = :fistname"),
    @NamedQuery(name = "Usr.findByLastname", query = "SELECT u FROM Usr u WHERE u.lastname = :lastname"),
    @NamedQuery(name = "Usr.findByAddress1", query = "SELECT u FROM Usr u WHERE u.address1 = :address1"),
    @NamedQuery(name = "Usr.findByAddress2", query = "SELECT u FROM Usr u WHERE u.address2 = :address2"),
    @NamedQuery(name = "Usr.findByPostcode", query = "SELECT u FROM Usr u WHERE u.postcode = :postcode"),
    @NamedQuery(name = "Usr.findByEmail", query = "SELECT u FROM Usr u WHERE u.email = :email"),
    @NamedQuery(name = "Usr.findByPhone", query = "SELECT u FROM Usr u WHERE u.phone = :phone"))
public class Usr implements Serializable 
    private static final long serialVersionUID = 1L;
    @Id
    @Basic(optional = false)
    @Column(name = "UID", nullable = false, length = 8)
    private String uid;
    @Basic(optional = false)
    @Column(name = "PASSWORD", nullable = false, length = 20)
    private String password;
    @Basic(optional = false)
    @Column(name = "FISTNAME", nullable = false, length = 30)
    private String fistname;
    @Basic(optional = false)
    @Column(name = "LASTNAME", nullable = false, length = 60)
    private String lastname;
    @Basic(optional = false)
    @Column(name = "ADDRESS1", nullable = false, length = 100)
    private String address1;
    @Column(name = "ADDRESS2", length = 100)
    private String address2;
    @Basic(optional = false)
    @Lob
    @Column(name = "CITY", nullable = false)
    private byte[] city;
    @Basic(optional = false)
    @Column(name = "POSTCODE", nullable = false, length = 10)
    private String postcode;
    @Column(name = "EMAIL", length = 50)
    private String email;
    @Column(name = "PHONE")
    private Integer phone;

    public Usr() 
    

    public Usr(String uid) 
        this.uid = uid;
    

    public Usr(String uid, String password, String fistname, String lastname, String address1, byte[] city, String postcode) 
        this.uid = uid;
        this.password = password;
        this.fistname = fistname;
        this.lastname = lastname;
        this.address1 = address1;
        this.city = city;
        this.postcode = postcode;
    

    public String getUid() 
        return uid;
    

    public void setUid(String uid) 
        this.uid = uid;
    

    public String getPassword() 
        return password;
    

    public void setPassword(String password) 
        this.password = password;
    

    public String getFistname() 
        return fistname;
    

    public void setFistname(String fistname) 
        this.fistname = fistname;
    

    public String getLastname() 
        return lastname;
    

    public void setLastname(String lastname) 
        this.lastname = lastname;
    

    public String getAddress1() 
        return address1;
    

    public void setAddress1(String address1) 
        this.address1 = address1;
    

    public String getAddress2() 
        return address2;
    

    public void setAddress2(String address2) 
        this.address2 = address2;
    

    public byte[] getCity() 
        return city;
    

    public void setCity(byte[] city) 
        this.city = city;
    

    public String getPostcode() 
        return postcode;
    

    public void setPostcode(String postcode) 
        this.postcode = postcode;
    

    public String getEmail() 
        return email;
    

    public void setEmail(String email) 
        this.email = email;
    

    public Integer getPhone() 
        return phone;
    

    public void setPhone(Integer phone) 
        this.phone = phone;
    

    @Override
    public int hashCode() 
        int hash = 0;
        hash += (uid != null ? uid.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 Usr)) 
            return false;
        
        Usr other = (Usr) object;
        if ((this.uid == null && other.uid != null) || (this.uid != null && !this.uid.equals(other.uid))) 
            return false;
        
        return true;
    



    @Override
    public String toString() 
        return "org.danizmax.Usr[uid=" + uid + "]";
    


persistance.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="SchoolPU" transaction-type="JTA">
    <jta-data-source>jdbc/school</jta-data-source>
    <properties>
    </properties>
  </persistence-unit>
</persistence>

我使用实体的类:

import java.util.Iterator;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;

/**
 *
 * @author danizmax
 */
@Stateless
public class ValidatorBean 

    @PersistenceContext
    EntityManager em;

    public ValidatorBean() 


    

    public boolean validate(String user, String pass) 

        List users = em.createQuery("SELECT * FROM usr").getResultList();

        Iterator it = users.iterator();

        //ignore the stupid validation it's only to try out JPA
        while(it.hasNext())
            Usr u = (Usr) it.next();

            if(u.getUid().equals(user) && u.getPassword().equals(pass))
                return true;
            
        


        return false;
    

更新:为了公平对待回答并奖励您的努力的你们,既然我已经真正学习了这项技术并在现实世界中使用它,我决定通过授予最佳答案来结束这个答案这是我很久以前找到的最可能的解决方案。

【问题讨论】:

我确实找到了解决方案,但不记得到底是什么了,只是它与代码中的强制转换有关。如果我弄清楚它到底是什么,我会把它作为答案发布。 【参考方案1】:

我遇到了同样的问题。就我而言,我使用了方法 em.createQuery("Usr.findAll"); 而不是 em.createNamedQuery("Usr.findAll");

【讨论】:

我只是在同一件事上浪费了 2 个小时...虽然我承认错误是我的错,但我对错误消息的非描述性不太满意...跨度> 【参考方案2】:

只有你的第一个查询是正确的,其他的不是 JPQL,所以应该会导致错误。对 SQL 使用 @NamedNativeQuery。

对于第一个查询,这似乎不是您真正用来获取错误的原因,

异常描述:语法错误解析查询 [Usr.findAll],第 1 行,第 0 列:意外标记 [Usr]。

请注意,错误显示“第 0 列”是“Usr”,这似乎是您在查询中输入了名称而不是名称。我猜你在做,

em.createQuery("Usr.findAll").getResultList();

但是应该做的,

em.createNamedQuery("Usr.findAll").getResultList();

或者,

em.createQuery("Select u from Usr u").getResultList();

看, http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL

【讨论】:

你的回答最能说明问题,恭喜!【参考方案3】:

您要获取的实体的类名是什么? (也许您需要显示放置@NamedQuery 的类)。

这真的是Usr 还是User?如果最后一个是真的,Select u from User u 肯定可以工作。

此外,您不需要@PersistenceContextem=Persistence.createEntityManagerFactory(...)。使用其中之一。如果您在托管环境中,请使用注入变体。自己创建一个实体管理器会给你一个所谓的application managed entity manager,你的代码必须为此做更多的管理才能保持正常运行。

【讨论】:

实体 Usr 是使用 netbeans 向导从现有的 derby 表创建的,所以我猜还有其他问题,因为我的代码是 hello world 微不足道的,甚至是数据库中表的自动生成from entity class 也不起作用,它应该。我如何知道我是否处于托管环境中? 如果您要部署到 Glassfish 并且出现 @PersistenceContext 的代码是 Servlet、ServletFilter、JSF 托管 bean、CDI bean 或 EJB bean,那么您处于托管环境中。这基本上意味着你不用 new 操作符来实例化这些对象,你只使用一个 persistence.xml 文件来声明你的持久化单元。 我添加了类,注意这是向导从 USR 表生成的类。它应该可以工作,将数据提交到表可以工作,只是无法识别 SQL 语句。我还将添加persistence.xml,它可能会让您知道出了什么问题。我正在使用 EclipseLink 2.0 进行连接。 我现在有点困惑。您为 em.createQuery() 调用创建的查询肯定是错误的,因此这些异常是意料之中的。但是命名查询对我来说看起来不错。你到底是什么时候得到这个异常的? Glassfish 何时启动或执行 entityManager.createNamedQuery() 时? Same here... 我自己尝试了几个 SQL 语句来测试问题。我的代码中没有 entityManager.createNamedQuery() 行。我会将我的 bean 发布在我尝试使用实体的位置,也许问题太明显以至于我看不到,【参考方案4】:

不确定这是否对您有帮助,因为这个问题似乎有点老了。但是,您可能希望使用 .createNativeQuery(...) 而不是 .createQuery(...),如下所示:

List users = em.create<b>Native</b>Query("SELECT * FROM usr").getResultList(); 

【讨论】:

【参考方案5】:

EclipseLink 倾向于在相对简单的配置问题上给出非常通用或神秘的错误消息。

我猜您在persistence.xml 中缺少对Usr 类的引用。您必须要么添加类,要么添加一个路径引用,告诉 EclipseLink 要处理哪些类以实现持久性。这是一个带有直接类引用的示例:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="SchoolPU" transaction-type="JTA">
    <jta-data-source>jdbc/school</jta-data-source>
    <class>my.package.Usr</class>
  </persistence-unit>
</persistence>

类引用是最直接的方法,但如果您有很多类,管理起来可能会很繁琐。

【讨论】:

已经试过了...结果是一样的。命名查询“Usr.findAll”在解析查询 [Usr.findAll],第 1 行,第 0 列时仍返回语法错误:意外标记 [Usr]。我敢打赌我的 netbeans 安装有问题。【参考方案6】:

我遇到了同样的问题。 Strangs 的解决方案——对我来说——是:Toplink 在与 persistence.xml 进行比较时将“表名”区分大小写。因此,如果您对 java 类使用标准的驼峰式命名,您必须在查询中使用相同的驼峰式命名。我非常喜欢完全误导性的错误信息。

【讨论】:

我将所有转换/重构为大写,在 bean、entity、persistance.xml 中,甚至数据库显示相同,但​​我仍然收到异常描述:解析查询的语法错误 [USR.findAll],第 1 行,第 0 列:意外令牌 [USR]。简单的 JPA 就这么多……【参考方案7】:

我的@NamedQuery 遇到了这样的问题。它根本没有用。我解决了通过em.createNamedQuery("anything.anotherthing") 更改em.createQuery("anything.anotherthing") 的问题,现在它工作正常。

【讨论】:

以上是关于使用 JPA 解析琐碎查询的语法错误的主要内容,如果未能解决你的问题,请参考以下文章

解析服务器云代码查询语法错误 141

Spring数据Jpa findTop和findFirst生成错误'@P0'附近的语法不正确

GraphQLError:语法错误:无法解析意外字符“\u00A0”

CDI 中的 Spring-JDBC 等价物是啥?

解析错误:语法错误,意外标记“:”

GraphQL - 语法错误:预期“:”,找到“)”[关闭]