Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL Query error in JSF, JPA application

Tags:

java

jpa

I have a problem with a query in my application. This is the query method doing the query:

public List<Product> obtainProductListByCategory(String category)
   {
      Query query = em.createQuery("SELECT p FROM PRODUCT p WHERE CATEGORY='" + category + "'");
      List<Product> ret = query.getResultList();

      if (ret == null)
      {
         return new ArrayList<Product>();
      }
      else
      {
         return ret;
      }
   } 

And this is the error: javax.ejb.EJBException

And in the trace I found:

Caused by: java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager: Exception Description: Syntax error parsing [SELECT * FROM PRODUCT WHERE CATEGORY='Humano']. [22, 22] A select statement must have a FROM clause. [7, 7] The left expression is missing from the arithmetic expression. [9, 22] The right expression is not an arithmetic expression

Any ideas? My objective is to refresh a JSF datatable in my webpage.


Edited my code based on @Ilya's answer, and now I got this exception

Caused by: java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager: Exception Description: Problem compiling [SELECT p FROM PRODUCT p WHERE CATEGORY='Humano']. [14, 21] The abstract schema type 'PRODUCT' is unknown. [30, 38] The identification variable 'CATEGORY' is not defined in the FROM clause.


As requested by @Ilya, I post my Product class: EDIT: Added @Table to the annotations.

package model;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;


@Table
@Entity
public class Product implements Serializable, IProduct
{
   private static final long serialVersionUID = 1L;
   @GeneratedValue(strategy = GenerationType.AUTO)
   @Id
   private String name;
   private int stock;
   private float price;
   private String category;
   private String description;

  @Override 
  public String getDescription() {
        return description;
    }


  public void setDescription(String description) {
        this.description = description;
    }


   public Product()
   {
   }


   public Product(String name, int stock, float price, String category, String description)
   {
      this.name = name;
      this.stock = stock;
      this.price = price;
      this.category = category;
      this.description = description;
   }





   @Override
   public String getName()
   {
      return name;
   }


   public void setName(String name)
   {
      this.name = name;
   }


   @Override
   public float getPrice()
   {
      return price;
   }


   public void setPrice(float price)
   {
      this.price = price;
   }


   @Override
   public int getStock()
   {
      return stock;
   }


   public void setStock(int stock)
   {
      this.stock = stock;
   }


   @Override
   public int hashCode()
   {
      return name.hashCode();
   }


   @Override
   public boolean equals(Object object)
   {
      if (!(object instanceof Product))
      {
         return false;
      }
      Product other = (Product) object;
      if (name.equals(other.getName()))
      {
         return true;
      }
      return false;
   }

   @Override
   public String getCategory()
   {
      return category;
   }

   @Override
   public String toString()
   {
      return "Marketv2.model.Product[ name=" + name + " ]";
   }

}

Thanks for the help so far. Here I post another query in my application, which is working properly:

   public void removeProduct(Product g)
   {
      Query q = em.createQuery("SELECT x FROM BasketItem x WHERE x.product.name = '" + g.getName() + "'");
      List<BasketItem> bItems = q.getResultList();
      for (BasketItem i : bItems)
      {
         em.remove(i);
      }

      q = em.createQuery("DELETE FROM Product x WHERE x.name = '" + g.getName() + "'");
      q.executeUpdate();
   }
}
like image 786
Jean Carlos Suárez Marranzini Avatar asked Oct 16 '13 19:10

Jean Carlos Suárez Marranzini


People also ask

How to write native SQL query in JPA?

We can use @Query annotation to specify a query within a repository. Following is an example. In this example, we are using native query, and set an attribute nativeQuery=true in Query annotation to mark the query as native. We've added custom methods in Repository in JPA Custom Query chapter.

What is createNativeQuery in JPA?

Imagine having a tool that can automatically detect JPA and Hibernate performance issues.

What is the difference between JPA and JPQL?

The main difference between JPQL and SQL lies in that the former deals with JPA entities, while the latter deals directly with relational data.

What is the difference between JPQL and native query?

JPQL is the most commonly used query language with JPA and Hibernate. It provides an easy way to query data from the database. But it supports only a small subset of the SQL standard, and it also does not support database-specific features. If you want to use any of these features, you need to use a native SQL query.


1 Answers

1) You should specify alias for tables in FROM clause, and SELECT clause should contains alias
Product should be an entity

em.createQuery("SELECT p FROM Product p WHERE p.category='" + category + "'");   

If PRODUCT isn't an entity, you should create nativeQuery

em.createNativeQuery("SELECT p FROM PRODUCT p WHERE p.CATEGORY='" + category + "'");  

EntityManager::createQuery is for JPQL (Java Persistence query language)
EntityManager::createNativeQuery is for SQL

2) JPA throws the "Unknown abstract schema type" error when JPA fails to locate your entity class
Also add entity to persistence.xml

 <persistence-unit ...>
        <class>com.package.Product</class>  

3) Add @Table annotation to your @Entity
4) As I see in documentation, JPQL is case-sensitive.

With the exception of names of Java classes and properties, queries are case-insensitive. So SeLeCT is the same as sELEct is the same as SELECT, but org.hibernate.eg.FOO and org.hibernate.eg.Foo are different, as are foo.barSet and foo.BARSET.

So JPQL query should be

SELECT p FROM Product p WHERE p.category = '...
like image 119
Ilya Avatar answered Nov 14 '22 21:11

Ilya