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

后端 未结 21 1502
孤街浪徒
孤街浪徒 2020-11-22 09:23

I am using JPA in my project.

I came to a query in which I need to make join operation on five tables. So I created a native query which returns five fields.

相关标签:
21条回答
  • 2020-11-22 09:43

    Old style using ResultSet

    @Transactional(readOnly=true)
    public void accessUser() {
        EntityManager em = this.getEntityManager();
        org.hibernate.Session session = em.unwrap(org.hibernate.Session.class);
        session.doWork(new Work() {
            @Override
            public void execute(Connection con) throws SQLException {
                try (PreparedStatement stmt = con.prepareStatement(
                        "SELECT u.username, u.name, u.email, 'blabla' as passe, login_type as loginType FROM users u")) {
                    ResultSet rs = stmt.executeQuery();
                    ResultSetMetaData rsmd = rs.getMetaData();
                    for (int i = 1; i <= rsmd.getColumnCount(); i++) {
                        System.out.print(rsmd.getColumnName(i) + " (" + rsmd.getColumnTypeName(i) + ") / ");
                    }
                    System.out.println("");
                    while (rs.next()) {
                        System.out.println("Found username " + rs.getString("USERNAME") + " name " + rs.getString("NAME") + " email " + rs.getString("EMAIL") + " passe " + rs.getString("PASSE") + " email " + rs.getInt("LOGIN_TYPE"));
                    }
                }
            }
        });
    }
    
    0 讨论(0)
  • 2020-11-22 09:43

    We have resolved the issue using following way :

       //Add actual table name here in Query
        final String sqlQuery = "Select a.* from ACTORS a"
        // add your entity manager here 
        Query query = entityManager.createNativeQuery(sqlQuery,Actors.class);
        //List contains the mapped entity data.
        List<Actors> list = (List<Actors>) query.getResultList();
    
    0 讨论(0)
  • 2020-11-22 09:44

    JPA provides an SqlResultSetMapping that allows you to map whatever returns from your native query into an Entity or a custom class.

    EDIT JPA 1.0 does not allow mapping to non-entity classes. Only in JPA 2.1 a ConstructorResult has been added to map return values a java class.

    Also, for OP's problem with getting count it should be enough to define a result set mapping with a single ColumnResult

    0 讨论(0)
  • 2020-11-22 09:45

    Since others have already mentioned all the possible solutions, I am sharing my workaround solution.

    In my situation with Postgres 9.4, while working with Jackson,

    //Convert it to named native query.
    List<String> list = em.createNativeQuery("select cast(array_to_json(array_agg(row_to_json(a))) as text) from myschema.actors a")
                       .getResultList();
    
    List<ActorProxy> map = new ObjectMapper().readValue(list.get(0), new TypeReference<List<ActorProxy>>() {});
    

    I am sure you can find same for other databases.

    Also FYI, JPA 2.0 native query results as map

    0 讨论(0)
  • 2020-11-22 09:46

    if you are using Spring, you can use org.springframework.jdbc.core.RowMapper

    Here is an example:

    public List query(String objectType, String namedQuery)
    {
      String rowMapper = objectType + "RowMapper";
      // then by reflection you can instantiate and use. The RowMapper classes need to follow the naming specific convention to follow such implementation.
    } 
    
    0 讨论(0)
  • 2020-11-22 09:49

    Using Hibernate :

    @Transactional(readOnly=true)
    public void accessUser() {
        EntityManager em = repo.getEntityManager();
        org.hibernate.Session session = em.unwrap(org.hibernate.Session.class);
        org.hibernate.SQLQuery q = (org.hibernate.SQLQuery) session.createSQLQuery("SELECT u.username, u.name, u.email, 'blabla' as passe, login_type as loginType FROM users u")
            .addScalar("username", StringType.INSTANCE).addScalar("name", StringType.INSTANCE)
            .addScalar("email", StringType.INSTANCE).addScalar("passe", StringType.INSTANCE)
            .addScalar("loginType", IntegerType.INSTANCE)
            .setResultTransformer(Transformers.aliasToBean(User2DTO.class));
    
        List<User2DTO> userList = q.list();
    }
    
    0 讨论(0)
提交回复
热议问题