Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA Native Query select and cast object

Tags:

java

sql

jpa

jpql

I have got an Object Admin which extends User. By default both Objects are in the table User_ of my Derby Database (included fields from Admin). Normally I'd select an User like this:

CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<User> query = cb.createQuery(User.class); Root user= query.from(User.class); Predicate predicateId = cb.equal(category.get("id"), id); query.select(user).where(predicateId); return em.createQuery(query).getSingleResult(); 

However due to the complexity of my query I'm using a native query like this:

Query query = em.createNativeQuery("SELECT USER.* FROM USER_ AS USER WHERE ID = ?"); query.setParameter(1, id); return (User) query.getSingleResult(); 

Though this throws a cast exception. I figure this is due to any fields from Admin.

My question is, how can I select a User using a native query with an equal result as the first example (including the same values for @LOB and @ManyToOne (et cetera) as the JPQL query would return)?

like image 700
Menno Avatar asked Jul 17 '13 19:07

Menno


People also ask

How do you map native query results to entities?

You can do this with a @SqlResultSetMapping which specifies the mapping for each entity attribute. As you can see in the code snippet, the @SqlResultSetMapping requires a name and an @EntityResult annotation which defines the mapping to the entity.

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.

What is createNativeQuery in JPA?

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

How 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.


2 Answers

You might want to try one of the following ways:

  • Using the method createNativeQuery(sqlString, resultClass)

    Native queries can also be defined dynamically using the EntityManager.createNativeQuery() API.

    String sql = "SELECT USER.* FROM USER_ AS USER WHERE ID = ?";  Query query = em.createNativeQuery(sql, User.class); query.setParameter(1, id); User user = (User) query.getSingleResult(); 
  • Using the annotation @NamedNativeQuery

    Native queries are defined through the @NamedNativeQuery and @NamedNativeQueries annotations, or <named-native-query> XML element.

    @NamedNativeQuery(     name="complexQuery",     query="SELECT USER.* FROM USER_ AS USER WHERE ID = ?",     resultClass=User.class ) public class User { ... }  Query query = em.createNamedQuery("complexQuery", User.class); query.setParameter(1, id); User user = (User) query.getSingleResult(); 

You can read more in the excellent open book Java Persistence (available in PDF).

───────
NOTE: With regard to use of getSingleResult(), see Why you should never use getSingleResult() in JPA.

like image 198
Paul Vargas Avatar answered Sep 25 '22 20:09

Paul Vargas


The accepted answer is incorrect.

createNativeQuery will always return a Query:

public Query createNativeQuery(String sqlString, Class resultClass); 

Calling getResultList on a Query returns List:

List getResultList() 

When assigning (or casting) to List<MyEntity>, an unchecked assignment warning is produced.

Whereas, createQuery will return a TypedQuery:

public <T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass); 

Calling getResultList on a TypedQuery returns List<X>.

List<X> getResultList(); 

This is properly typed and will not give a warning.

With createNativeQuery, using ObjectMapper seems to be the only way to get rid of the warning. Personally, I choose to suppress the warning, as I see this as a deficiency in the library and not something I should have to worry about.

like image 36
Derek White Avatar answered Sep 24 '22 20:09

Derek White