J'ai un objet Admin
qui étend User
. Par défaut, les deux objets se trouvent dans la table User_
de ma base de données Derby (champs inclus de Admin
). Normalement, je choisirais une User
comme ceci:
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();
Cependant, en raison de la complexité de ma requête, j'utilise une requête native comme celle-ci:
Query query = em.createNativeQuery("SELECT USER.* FROM USER_ AS USER WHERE ID = ?");
query.setParameter(1, id);
return (User) query.getSingleResult();
Bien que cela jette une exception de casting. Je suppose que cela est dû aux champs de Admin
.
Ma question est la suivante: comment sélectionner une User
en utilisant une requête native avec un résultat identique à celui du premier exemple (y compris les mêmes valeurs pour @LOB
et @ManyToOne
(et cetera) que la requête JPQL renverrait)?
Vous voudrez peut-être essayer l'une des méthodes suivantes:
createNativeQuery(sqlString, resultClass)
Les requêtes natives peuvent également être définies de manière dynamique à l'aide de l'API EntityManager.createNativeQuery()
.
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();
@NamedNativeQuery
Les requêtes natives sont définies à l'aide des annotations @NamedNativeQuery
et @NamedNativeQueries
Ou de l'élément XML <named-native-query>
.
@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();
Vous pouvez en lire plus dans l'excellent livre ouvert Java Persistence (disponible dans PDF ).
───────
NOTE: En ce qui concerne l'utilisation de getSingleResult()
, voir Pourquoi vous ne devriez jamais utiliser getSingleResult()
dans JPA .
Veuillez vous référer à JPA: comment convertir un jeu de résultats de requête natif en collection de classes POJO
Pour Postgres 9.4
,
List<String> list = em.createNativeQuery("select cast(row_to_json(u) as text) from myschema.USER_ u WHERE ID = ?")
.setParameter(1, id).getResultList();
User map = new ObjectMapper().readValue(list.get(0), User.class);
La réponse acceptée est incorrecte.
createNativeQuery
retournera toujours un Query
:
public Query createNativeQuery(String sqlString, Class resultClass);
L'appel de getResultList
sur une Query
renvoie List
:
List getResultList()
Lors de l'attribution (ou de la conversion) à List<MyEntity>
, un avertissement d'attribution non vérifié est généré.
Attendu que, createQuery
retournera un TypedQuery
:
public <T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass);
L'appel de getResultList
sur une TypedQuery
renvoie List<X>
.
List<X> getResultList();
Ceci est correctement typé et ne donnera pas d'avertissement.
Avec createNativeQuery
, utiliser ObjectMapper
semble être le seul moyen de se débarrasser de l'avertissement. Personnellement, je choisis de supprimer l’avertissement, car j’estime qu’il s’agissait d’une lacune dans la bibliothèque et non d’un problème qui me préoccupe.