with query namednativequery example create java sql jpa jpql

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; } }



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.