Java JPA:如何将本机查询结果集转换为POJO类集合

Java JPA:如何将本机查询结果集转换为POJO类集合,java,jpa,Java,Jpa,我在我的项目中使用JPA 我遇到了一个查询,其中我需要对五个表执行联接操作。因此,我创建了一个本机查询,它返回五个字段 现在我想将结果对象转换为java POJO类,该类包含相同的五个字符串 在JPA中有没有办法直接将结果转换到POJO对象列表中 我得出了下面的解决办法 @NamedNativeQueries({ @NamedNativeQuery( name = "nativeSQL", query = "SELECT * FROM Acto

我在我的项目中使用JPA

我遇到了一个查询,其中我需要对五个表执行联接操作。因此,我创建了一个本机查询,它返回五个字段

现在我想将结果对象转换为java POJO类,该类包含相同的五个字符串

在JPA中有没有办法直接将结果转换到POJO对象列表中

我得出了下面的解决办法

@NamedNativeQueries({  
    @NamedNativeQuery(  
        name = "nativeSQL",  
        query = "SELECT * FROM Actors",  
        resultClass = db.Actor.class),  
    @NamedNativeQuery(  
        name = "nativeSQL2",  
        query = "SELECT COUNT(*) FROM Actors",  
        resultClass = XXXXX) // <--------------- problem  
})  
现在在resultClass中,我们需要提供一个实际的JPA实体类吗? 或 我们可以将其转换为任何包含相同列名的JAVA POJO类?

使用DTO设计模式。它在EJB2.0中使用。实体由容器管理。DTO设计模式被用来解决这个问题。 但是,当应用程序分别在服务器端和客户端开发时,现在可以使用DTO。当服务器端不希望将带有注释的实体传递/返回到客户端时,可以使用DTO

DTO示例:

PersonEntity.java

@Entity
public class PersonEntity {
    @Id
    private String id;
    private String address;

    public PersonEntity(){

    }
    public PersonEntity(String id, String address) {
        this.id = id;
        this.address = address;
    }
    //getter and setter

}
PersonDTO.java

public class PersonDTO {
    private String id;
    private String address;

    public PersonDTO() {
    }
    public PersonDTO(String id, String address) {
        this.id = id;
        this.address = address;
    }

    //getter and setter 
}
DTOBuilder.java

public class DTOBuilder() {
    public static PersonDTO buildPersonDTO(PersonEntity person) {
        return new PersonDTO(person.getId(). person.getAddress());
    }
}
javaJPA提供了一个可用于将本机查询返回的任何内容映射到实体或自定义类的

EDIT JPA 1.0不允许映射到非实体类。只有在JPA2.1中,才添加了一个java类来映射返回值


另外,对于OP获取计数的问题,使用单个

定义一个结果集映射就足够了。我找到了一些解决方案

使用映射实体JPA2.0

使用JPA2.0,不可能将本机查询映射到POJO,只能使用实体进行映射

例如:

Query query = em.createNativeQuery("SELECT name,age FROM jedi_table", Jedi.class);
@SuppressWarnings("unchecked")
List<Jedi> items = (List<Jedi>) query.getResultList();
然后,我们可以简单地做:

TypedQuery<Jedi> query = em.createNamedQuery("jedisQry", Jedi.class);
List<Jedi> items = query.getResultList();
Query query = em.createNativeQuery("SELECT name,age FROM jedis_table", "JediResult");
@SuppressWarnings("unchecked")
List<Jedi> samples = query.getResultList();
然后我们简单地做:

TypedQuery<Jedi> query = em.createNamedQuery("jedisQry", Jedi.class);
List<Jedi> items = query.getResultList();
Query query = em.createNativeQuery("SELECT name,age FROM jedis_table", "JediResult");
@SuppressWarnings("unchecked")
List<Jedi> samples = query.getResultList();

这些就是我所知道的所有解决方案。如果我们可以使用JPA2.1,最后两种方法是理想的方法。

请参见下面的示例,使用POJO作为伪实体从本机查询检索结果,而不使用复杂的SQLResultsMapping。只需要两个注释,在POJO中有一个裸@Enity和一个伪@Id@Id可以用于您选择的任何字段,@Id字段可以有重复的键,但不能有空值

由于@Enity不映射到任何物理表,因此此POJO称为伪实体

环境:eclipselink 2.5.0-RC1、jpa-2.1.0、mysql-connector-java-5.1.14

您可以下载完整的maven项目

本机查询基于mysql示例数据库

persistence.xml

<?xml version="1.0" encoding="UTF-8"?><persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="jpa-mysql" transaction-type="RESOURCE_LOCAL">
    <class>org.moonwave.jpa.model.pojo.Employee</class>
    <properties>
        <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/employees" />
        <property name="javax.persistence.jdbc.user" value="user" />
        <property name="javax.persistence.jdbc.password" value="***" />
        <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
    </properties>
</persistence-unit>
employeentivequiry.java

public class EmployeeNativeQuery {
private EntityManager em;
private EntityManagerFactory emf;

public void setUp() throws Exception {
    emf=Persistence.createEntityManagerFactory("jpa-mysql");
    em=emf.createEntityManager();
}
public void tearDown()throws Exception {
    em.close();
    emf.close();
}

@SuppressWarnings("unchecked")
public void query() {
    Query query = em.createNativeQuery("select e.emp_no as empNo, e.first_name as firstName, e.last_name as lastName," + 
            "t.title from employees e join titles t on e.emp_no = t.emp_no", Employee.class);
    query.setMaxResults(30);
    List<Employee> list = (List<Employee>) query.getResultList();
    int i = 0;
    for (Object emp : list) {
        System.out.println(++i + ": " + emp.toString());
    }
}

public static void main( String[] args ) {
    EmployeeNativeQuery test = new EmployeeNativeQuery();
    try {
        test.setUp();
        test.query();
        test.tearDown();
    } catch (Exception e) {
        System.out.println(e);
    }
}
}

首先声明以下注释:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface NativeQueryResultEntity {
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NativeQueryResultColumn {
    int index();
}
然后按如下说明您的POJO:

Query query = em.createNativeQuery("SELECT name,age FROM jedis_table");
List<Jedi> jedis = getResultList(query, Jedi.class);
@NativeQueryResultEntity
public class ClassX {
    @NativeQueryResultColumn(index=0)
    private String a;

    @NativeQueryResultColumn(index=1)
    private String b;
}
String sql = "select a,b from x order by a";
Query q = entityManager.createNativeQuery(sql);

List<ClassX> results = NativeQueryResultsMapper.map(q.getResultList(), ClassX.class);
然后写入注释处理器:

public class NativeQueryResultsMapper {

    private static Logger log = LoggerFactory.getLogger(NativeQueryResultsMapper.class);

    public static <T> List<T> map(List<Object[]> objectArrayList, Class<T> genericType) {
        List<T> ret = new ArrayList<T>();
        List<Field> mappingFields = getNativeQueryResultColumnAnnotatedFields(genericType);
        try {
            for (Object[] objectArr : objectArrayList) {
                T t = genericType.newInstance();
                for (int i = 0; i < objectArr.length; i++) {
                    BeanUtils.setProperty(t, mappingFields.get(i).getName(), objectArr[i]);
                }
                ret.add(t);
            }
        } catch (InstantiationException ie) {
            log.debug("Cannot instantiate: ", ie);
            ret.clear();
        } catch (IllegalAccessException iae) {
            log.debug("Illegal access: ", iae);
            ret.clear();
        } catch (InvocationTargetException ite) {
            log.debug("Cannot invoke method: ", ite);
            ret.clear();
        }
        return ret;
    }

    // Get ordered list of fields
    private static <T> List<Field> getNativeQueryResultColumnAnnotatedFields(Class<T> genericType) {
        Field[] fields = genericType.getDeclaredFields();
        List<Field> orderedFields = Arrays.asList(new Field[fields.length]);
        for (int i = 0; i < fields.length; i++) {
            if (fields[i].isAnnotationPresent(NativeQueryResultColumn.class)) {
                NativeQueryResultColumn nqrc = fields[i].getAnnotation(NativeQueryResultColumn.class);
                orderedFields.set(nqrc.index(), fields[i]);
            }
        }
        return orderedFields;
    }
}
使用上述框架如下:

Query query = em.createNativeQuery("SELECT name,age FROM jedis_table");
List<Jedi> jedis = getResultList(query, Jedi.class);
@NativeQueryResultEntity
public class ClassX {
    @NativeQueryResultColumn(index=0)
    private String a;

    @NativeQueryResultColumn(index=1)
    private String b;
}
String sql = "select a,b from x order by a";
Query q = entityManager.createNativeQuery(sql);

List<ClassX> results = NativeQueryResultsMapper.map(q.getResultList(), ClassX.class);

如果您使用的是Spring,那么可以使用org.springframework.jdbc.core.RowMapper

以下是一个例子:

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

是的,使用JPA2.1很容易。您有非常有用的注释。它们简化了你的生活

首先声明本机查询,然后声明结果集映射,该映射定义了数据库返回的数据到POJO的映射。为了简洁起见,请编写您的POJO类以参考此处未包含的内容。最后但并非最不重要的一点:例如,在DAO中创建一个方法来调用查询。这在dropwizard 1.0.0应用程序中对我有效

首先在实体类中声明本机查询:

@NamedNativeQuery (
name = "domain.io.MyClass.myQuery",
query = "Select a.colA, a.colB from Table a",
resultSetMapping = "mappinMyNativeQuery")   // must be the same name as in the SqlResultSetMapping declaration
在下面,您可以添加resultset映射声明:

@SqlResultSetMapping(
name = "mapppinNativeQuery",  // same as resultSetMapping above in NativeQuery
   classes = {
      @ConstructorResult( 
          targetClass = domain.io.MyMapping.class,
          columns = {
               @ColumnResult( name = "colA", type = Long.class),  
               @ColumnResult( name = "colB", type = String.class)
          }
      )
   } 
)
稍后在DAO中,您可以将查询称为

public List<domain.io.MyMapping> findAll() {
        return (namedQuery("domain.io.MyClass.myQuery").list());
    }

就是这样。

将SQL查询转换为POJO类集合的简单方法

Query query = getCurrentSession().createSQLQuery(sqlQuery).addEntity(Actors.class);
List<Actors> list = (List<Actors>) query.list();
return list;
如果您使用Spring jpa,这是对答案和问题的补充。如果有任何缺陷,请更正。根据我满足的实际需要,我主要使用了三种方法来实现将结果对象[]映射到pojo:

JPA内置方法就足够了。 JPA内置方法还不够,但一个带有实体的定制sql就足够了。 前2个失败了,我必须使用nativeQuery。 下面是一些例子。 pojo预计:

public class Antistealingdto {

    private String secretKey;

    private Integer successRate;

    // GETTERs AND SETTERs

    public Antistealingdto(String secretKey, Integer successRate) {
        this.secretKey = secretKey;
        this.successRate = successRate;
    }
}
方法1:将pojo更改为接口:

public interface Antistealingdto {
    String getSecretKey();
    Integer getSuccessRate();
}
和存储库:

interface AntiStealingRepository extends CrudRepository<Antistealing, Long> {
    Antistealingdto findById(Long id);
}
@Query("select new AntistealingDTO(secretKey, successRate) from Antistealing where ....")
Antistealing whatevernamehere(conditions);
注意:POJO构造函数的参数序列在POJO定义和sql中必须相同

方法3: 在Edwin Dalorzo的回答中,使用实体中的@SqlResultSetMapping和@NamedNativeRequesty作为示例


前两个方法将调用许多中间处理程序,如自定义转换器。例如,反序列化定义了一个secretKey,在它被持久化之前,插入一个转换器对它进行加密。这将导致前两个方法返回一个转换后的secretKey,这不是我想要的。虽然方法3将克服转换器,返回的secretKey将与存储的加密密钥相同。

由于其他人已经提到了所有可能的解决方案,我正在分享我的解决方案

在我9.4级的情况下,与Jackson一起工作时

我相信你可以在其他数据库中找到相同的


此外,还可以执行展开过程,将结果分配给非实体Beans/POJO。程序如下: 跟着

List<JobDTO> dtoList = entityManager.createNativeQuery(sql)
        .setParameter("userId", userId)
        .unwrap(org.hibernate.Query.class).setResultTransformer(Transformers.aliasToBean(JobDTO.class)).list();

该用法适用于JPA Hibernate实现。

不确定这是否适合这里,但我有类似的问题,并找到了以下简单的解决方案/示例:

private EntityManager entityManager;
...
    final String sql = " SELECT * FROM STORE "; // select from the table STORE
    final Query sqlQuery = entityManager.createNativeQuery(sql, Store.class);

    @SuppressWarnings("unchecked")
    List<Store> results = (List<Store>) sqlQuery.getResultList();
在我的例子中,我必须在其他地方使用字符串中定义的SQL部分,因此我不能只使用NamedNativeQuery。

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

使用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"));
                }
            }
        }
    });
}

最简单的方法是使用so投影。它可以将查询结果直接映射到接口,并且比使用SqlResultSetMapping更容易实现

示例如下所示:

@Repository
public interface PeopleRepository extends JpaRepository<People, Long> {

    @Query(value = "SELECT p.name AS name, COUNT(dp.people_id) AS count " +
        "FROM people p INNER JOIN dream_people dp " +
        "ON p.id = dp.people_id " +
        "WHERE p.user_id = :userId " +
        "GROUP BY dp.people_id " +
        "ORDER BY p.name", nativeQuery = true)
    List<PeopleDTO> findByPeopleAndCountByUserId(@Param("userId") Long userId);

    @Query(value = "SELECT p.name AS name, COUNT(dp.people_id) AS count " +
        "FROM people p INNER JOIN dream_people dp " +
        "ON p.id = dp.people_id " +
        "WHERE p.user_id = :userId " +
        "GROUP BY dp.people_id " +
        "ORDER BY p.name", nativeQuery = true)
    Page<PeopleDTO> findByPeopleAndCountByUserId(@Param("userId") Long userId, Pageable pageable);

}



// Interface to which result is projected
public interface PeopleDTO {

    String getName();

    Long getCount();

}
投影接口中的字段必须与此实体中的字段匹配。否则,字段映射可能会中断


另外,如果使用SELECT table.column符号,请始终定义与实体名称匹配的别名,如示例所示。

在hibernate中,您可以使用此代码轻松映射本机查询

private List < Map < String, Object >> getNativeQueryResultInMap() {
String mapQueryStr = "SELECT * FROM AB_SERVICE three ";
Query query = em.createNativeQuery(mapQueryStr);
NativeQueryImpl nativeQuery = (NativeQueryImpl) query;
nativeQuery.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
List < Map < String, Object >> result = query.getResultList();
for (Map map: result) {
    System.out.println("after request  ::: " + map);
}
return result;}

我们通过以下方式解决了该问题:

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

我尝试了上面答案中提到的很多事情。SQLmapper对于将其放在何处非常混乱。非管理POJO只是一个问题。我尝试了各种方法,其中一个简单的方法就是像往常一样。我正在使用hibernate-jpa-2.1

List<TestInfo> testInfoList = factory.createNativeQuery(QueryConstants.RUNNING_TEST_INFO_QUERY)
                    .getResultList();

在这种情况下,使用像实体a.k.a不可变实体这样的数据库视图非常容易

正规实体 @实体 @Tablename=人 数据类人员 @身份证 valid:Long=-1, val firstName:String=, val lastName:字符串?=无效的 类视图实体 @实体 @不变的 @再选择 选择 p、 身份证, 以姓名、姓氏作为全名 来自人民党 数据类人员 @身份证 val id:Long, val fullName:String, 在任何存储库中,我们都可以创建查询函数/方法,如下所示:

@Queryvalue=从PersonMin p中选择p 寻欢作乐的人最小可寻呼:可寻呼:页面
如果查询不太复杂,可以这样做。在我的例子中,我需要使用H2 FT_搜索结果查询来进行另一个查询

var ftSearchQuery = "SELECT * FROM FT_SEARCH(\'something\', 0, 0)";
List<Object[]> results = query.getResultList();
List<Model> models = new ArrayList<>();
for (Object[] result : results) {
    var newQuery = "SELECT * FROM " + (String) result[0];
    models.addAll(entityManager.createNativeQuery(newQuery, Model.class).getResultList());
  }

可能有更干净的方法可以做到这一点。

谢谢你的回答。这里我不需要图案。我的要求不是对客户机隐藏注释细节。因此,我不需要在我的应用程序中再创建一个POJO。我的要求是将结果集强制转换为qa pojo,qa pojo不是JAVA实体,而是简单的pojo类,它具有与结果集列相同的字段。在这里,我们使用带有@EntityResult和@FieldResult注释的java实体类的实体映射结果。那很好。但在这里我需要更清楚。是否要求我们映射结果的类必须是JPA实体类?或者我们可以使用一个简单的POJO类,它不是一个实体buy,在结果集中有所有必需的变量作为列。@Gunjansah:最好的方法是尝试一下:另外,一个实体就是同一个POJO,只是有一些注释。只要您不尝试持久化它,它就会保持为pojo。当我尝试此操作时,我得到一个错误,即该类不是已知的实体。我最终使用了这种方法,而不是尝试使用本机查询。@EdwinDalorzo:这对于JPA1.0来说是正确的。在JPA2.1中,他们将ConstructorResult作为参数之一添加到SqlResultsMapping中,该参数允许在构造函数中设置所有字段时使用pojo。我将更新答案。我看到了另一个痛苦的事实:ConstructorResult可以映射到POJO。。但是ConstructorResult本身必须在Entity类中,这样您就无法避免Entity…因此更大的硬事实是:您需要一些不在乎主键的结果-仍然必须在Entity中有@Id…荒谬吧?旁注:我刚刚使用JPA2.1依赖项的JPA2.0方法,但失败了。所以这可能是向下不兼容的…你说的实体中的某处是什么意思?我的Pojo不是JPA实体。我不能在我的Pojo中声明@SqlResultSetMapping吗?我对JPA2.1解决方案感兴趣。请更精确一点。@Alboz必须将@SqlResultSetMapping放置在实体中,因为JPA将从实体中读取元数据。你不能指望JPA检查你的POJO。放置映射的实体是不相关的,可能是与POJO结果更相关的实体。或者,映射可以用XML表示,以避免与完全不相关的实体耦合。constructorresult是否可以使用具有嵌套类的类?如果将JPA 2.1与@SqlResultsMapping一起使用,则值得注意的是,Jedi类将需要一个all-arg构造函数,并且@ColumnResult注释可能需要需要将type属性添加到可能不是隐式的转换中我需要为某些列添加type=ZonedDateTime.class。既然您的列表据称是员工列表,为什么您的for-each循环在类型对象上迭代?如果您以forEmployee emp:list的形式编写for-each循环,那么您会发现您的答案是错误的,并且列表中的内容不是员工,并且您压制的警告是为了
提醒您注意此潜在错误。@SuppressWarningUnchecked用于抑制List=List query.getResultList的警告;将对象emp:list更改为Employee emp:list更好,但如果保留为对象emp,则不会出现错误,因为list是list的一个实例。我在git project中更改了代码,但不是为了让您的注释与原始post相关。问题是,您的查询不返回员工列表,而是返回一个对象数组。你的警告掩盖了这一点。当您尝试将其中任何一个转换为员工时,您将得到一个错误,一个强制转换异常;和persistence.xml,本机查询将返回员工列表。我刚刚签出并运行项目,没有问题。如果您在本地设置mysql示例employees db,那么您也应该能够运行该项目哦,我现在明白您的意思了。但在这种情况下,您的答案并不满足这个问题,因为这是关于使用常规POJO作为目标对象,而您的答案是使用Employee,我假设它是一个实体。不是吗?方法1实际上不需要Spring,它可以与纯Hibernate一起工作。@MartinVysny是的,M1是JPQL。任何实现JPQL的项目都应该支持它。通过这种方式,也许M2也得到了广泛的支持?答案不错,但我认为您在第一个@ColumnResult注释后遗漏了一个括号。代码中有错误,但很容易纠正。例如:resultSetMapping=应该是resultSetMapping=我看到了另一个痛苦的事实:NamedNavity&SqlResultSetMapping必须在@Entity类中检查这个答案。它有完整的答案:他使用的是jpa,而不是springnote,JobDTO应该有默认构造函数。或者,您可以基于AliasToBeanResultTransformer实现实现自己的转换器。为什么要设置参数?只要返回实体。没什么特别的。问题是当您尝试将结果映射到非托管POJO时。BeanUtils在哪个包中?本机查询和投影不能很好地结合在一起。我无法使字段映射正常工作-大多数值始终返回为null
@Setter
@Getter
@NoArgsConstructor
@ToString
public class TestInfo {

    private String emailid;
    private Long testcount;

    public TestInfo(String emailId, Long testCount) {
        super();
        this.emailid = emailId;
        this.testcount = testCount;
    }

}
var ftSearchQuery = "SELECT * FROM FT_SEARCH(\'something\', 0, 0)";
List<Object[]> results = query.getResultList();
List<Model> models = new ArrayList<>();
for (Object[] result : results) {
    var newQuery = "SELECT * FROM " + (String) result[0];
    models.addAll(entityManager.createNativeQuery(newQuery, Model.class).getResultList());
  }