31

我有一个Admin扩展的对象User。默认情况下,这两个对象都在User_我的 Derby 数据库的表中(包括来自 的字段Admin)。通常我会选择User这样的:

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();

但是由于我的查询的复杂性,我正在使用这样的本机查询:

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

虽然这会引发强制转换异常。我认为这是由于来自Admin.

我的问题是,如何User使用与第一个示例具有相同结果的本机查询来选择一个(包括与JPQL 查询返回的@LOB和(等)相同的值)?@ManyToOne

4

5 回答 5

65

您可能想尝试以下方法之一:

  • 使用方法createNativeQuery(sqlString, resultClass)

    本机查询也可以使用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();
    
  • 使用注释@NamedNativeQuery

    本机查询是通过@NamedNativeQuery@NamedNativeQueries 注释或<named-native-query>XML 元素定义的。

    @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();
    

您可以在优秀的开放书籍Java Persistence(以PDF形式提供)中阅读更多内容。

────────
注意:关于使用 of getSingleResult(),请参阅为什么你不应该getSingleResult()在 JPA中使用。

于 2013-07-17T20:11:12.353 回答
9

接受的答案不正确。

createNativeQuery将始终返回Query

public Query createNativeQuery(String sqlString, Class resultClass);

调用返回:getResultList_QueryList

List getResultList()

分配(或强制转换)到 时List<MyEntity>,会产生未经检查的分配警告。

而,createQuery将返回一个TypedQuery

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

调用返回。getResultList_TypedQueryList<X>

List<X> getResultList();

这是正确键入的,不会发出警告。

使用createNativeQuery, usingObjectMapper似乎是摆脱警告的唯一方法。就个人而言,我选择抑制警告,因为我认为这是图书馆的缺陷,而不是我应该担心的事情。

于 2018-12-21T19:05:01.857 回答
5

当您的本机查询基于联接时,在这种情况下,您可以将结果作为对象列表获取并进行处理。

一个简单的例子。

@Autowired
EntityManager em;

    String nativeQuery = "select name,age from users where id=?";   
    Query query = em.createNativeQuery(nativeQuery);
    query.setParameter(1,id);

    List<Object[]> list = query.getResultList();

    for(Object[] q1 : list){

        String name = q1[0].toString();
        //..
        //do something more on 
     }
于 2019-04-13T17:30:24.337 回答
2

请参考JPA : How to convert a native query result set to POJO class collection

对于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);
于 2017-11-11T05:35:00.113 回答
-1

首先创建一个模型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
}

控制器

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;
    }
}
于 2017-11-10T13:14:11.540 回答