JPA Native Query选择和转换对象

Men*_*nno 24 java sql jpa jpql

我有一个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();
Run Code Online (Sandbox Code Playgroud)

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

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

虽然这会抛出一个强制转换异常.我认为这是由于任何领域Admin.

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

Pau*_*gas 49

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

  • 使用方法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();
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用注释@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();
    
    Run Code Online (Sandbox Code Playgroud)

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

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

  • @PaulVargas,我建议这样做:Integer val =(Integer)query.getSingleResult(); 但是,我通常建议不要使用query.getSingleResult(),因为它会抛出许多已检查的异常.如果您将结果作为列表获得,则可以相应地处理任何结果和多个结果. (2认同)

Der*_*ite 9

接受的答案是不正确的。

createNativeQuery将始终返回一个Query

public Query createNativeQuery(String sqlString, Class resultClass);
Run Code Online (Sandbox Code Playgroud)

调用getResultListQuery的回报List

List getResultList()
Run Code Online (Sandbox Code Playgroud)

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

而,createQuery将返回一个TypedQuery

public <T> TypedQuery<T> createQuery(String qlString, Class<T> resultClass);
Run Code Online (Sandbox Code Playgroud)

调用getResultList一个TypedQuery返回List<X>

List<X> getResultList();
Run Code Online (Sandbox Code Playgroud)

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

对于createNativeQuery,使用ObjectMapper似乎是摆脱警告的唯一方法。就我个人而言,我选择取消警告,因为我认为这是库中的一个缺陷,而不是我应该担心的事情。


sha*_*kar 8

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

一个简单的例子。

@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 
     }
Run Code Online (Sandbox Code Playgroud)