java - query - jpql
JPA Native Query selecciona y lanza objeto (4)
Tengo un Admin
objetos que extiende el User
. De forma predeterminada, ambos objetos se encuentran en la tabla User_
de mi base de datos Derby (campos incluidos de Admin
). Normalmente seleccionaría un User
como este:
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();
Sin embargo, debido a la complejidad de mi consulta, estoy usando una consulta nativa como esta:
Query query = em.createNativeQuery("SELECT USER.* FROM USER_ AS USER WHERE ID = ?");
query.setParameter(1, id);
return (User) query.getSingleResult();
Aunque esto arroja una excepción de reparto. Me imagino que esto se debe a los campos de Admin
.
Mi pregunta es, ¿cómo puedo seleccionar a un User
utilizando una consulta nativa con el mismo resultado que el primer ejemplo (incluidos los mismos valores para @LOB
y @ManyToOne
(etc.) que devolvería la consulta de JPQL)?
En primer lugar crea un modelo POJO.
import javax.persistence.*;
@Entity
@Table(name = "sys_std_user")
public class StdUser {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "class_id")
public int classId;
@Column(name = "user_name")
public String userName;
//getter,setter
}
Controlador
import com.example.demo.models.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import java.util.List;
@RestController
public class HomeController {
@PersistenceUnit
private EntityManagerFactory emf;
@GetMapping("/")
public List<StdUser> actionIndex() {
EntityManager em = emf.createEntityManager(); // Without parameter
List<StdUser> arr_cust = (List<StdUser>)em
.createQuery("SELECT c FROM StdUser c")
.getResultList();
return arr_cust;
}
@GetMapping("/paramter")
public List actionJoin() {
int id = 3;
String userName = "Suresh Shrestha";
EntityManager em = emf.createEntityManager(); // With parameter
List arr_cust = em
.createQuery("SELECT c FROM StdUser c WHERE c.classId = :Id ANd c.userName = :UserName")
.setParameter("Id",id)
.setParameter("UserName",userName)
.getResultList();
return arr_cust;
}
}
Consulte JPA: Cómo convertir un conjunto de resultados de consultas nativas a la colección de clases POJO
Para 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);
Es posible que desee probar una de las siguientes formas:
Usando el método
createNativeQuery(sqlString, resultClass)
Las consultas nativas también se pueden definir dinámicamente usando la 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();
Usando la anotación
@NamedNativeQuery
Las consultas nativas se definen a través de las anotaciones
@NamedNativeQuery
y@NamedNativeQueries
, o el elemento 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();
Puede leer más en el excelente libro abierto Persistencia de Java (disponible en PDF ).
───────
NOTA : con respecto al uso de getSingleResult()
, vea Por qué nunca debe usar getSingleResult()
en JPA .
La respuesta aceptada es incorrecta.
createNativeQuery
siempre devolverá una Query
:
public Query createNativeQuery(String sqlString, Class resultClass);
Llamando a getResultList
en una List
devoluciones de Query
:
List getResultList()
Al asignar (o lanzar) a la List<MyEntity>
, se produce una advertencia de asignación sin List<MyEntity>
.
Mientras que, createQuery
devolverá un TypedQuery
:
public <T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass);
Llamar a getResultList
en un TypedQuery
devuelve la List<X>
.
List<X> getResultList();
Esto está escrito correctamente y no dará una advertencia.
Con createNativeQuery
, usar ObjectMapper
parece ser la única manera de deshacerse de la advertencia. Personalmente, elijo suprimir la advertencia, ya que veo esto como una deficiencia en la biblioteca y no es algo de lo que deba preocuparme.