Java createNativeQuery 映射到 POJO(非实体)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26831893/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 03:22:23  来源:igfitidea点击:

createNativeQuery mapping to POJO (non-entity)

javasqlhibernatejakarta-eejpa

提问by fasth

I have an easy problem at the first glance:

乍一看,我有一个简单的问题:

entityManager()
.createNativeQuery("select count(*) as total, select sum(field) as total_sum ... blabla") 

And I want to write select result into POJO, like this:

我想将选择结果写入 POJO,如下所示:

public class AggregateStatsDto {

    private int total;

    private long totalSum;

    // getters, setters, cosntructors
}

What the best way to achieve this?

实现这一目标的最佳方法是什么?

I can use JPA 2.1 and tried to use @SqlResultSetMappingin conjuction with @ConstructorResult:

我可以使用JPA 2.1,并试图使用@SqlResultSetMapping与一起选择@ConstructorResult

@SqlResultSetMapping(name = "AggregateStatsResult", classes = {
        @ConstructorResult(targetClass = AggregateStatsDto.class,
                columns = {
                        @ColumnResult(name = "total"),
                        @ColumnResult(name = "totalSum")
                })
})
public class AggregateStatsDto {

        private long total;

        private int totalSum;

        // getters, setters, cosntructors
    }

Query:

询问:

AggregateStatsDto result = (AggregateStatsDto) entityManager()
    .createNativeQuery("select count(*) as total, select sum(field) as total_sum ... blabla", "AggregateStatsResult")
    .getSingleResult();

But no luck. It seems that it wants @Entity anyway. But I want just a POJO.

但没有运气。似乎无论如何它都想要@Entity。但我只想要一个 POJO。

org.hibernate.MappingException: Unknown SqlResultSetMapping [AggregateStatsResult]"

Thanks in advance!

提前致谢!

采纳答案by fasth

I resolved my problem in following way: This is a query:

我通过以下方式解决了我的问题:这是一个查询:

  final Query query = Sale.entityManager().createNativeQuery(...);

Then I accessed to internal Hibernate session inside entity manager and applied scalars/resultTransformer. Thats all!

然后我访问了实体管理器内部的内部 Hibernate 会话并应用了标量/resultTransformer。就这样!

 // access to internal Hibernate of EntityManager
        query.unwrap(SQLQuery.class)
                .addScalar("total", LongType.INSTANCE)
                .addScalar("amountOfSales", LongType.INSTANCE)
                .addScalar("amountOfProducts", LongType.INSTANCE)
                .setResultTransformer(Transformers.aliasToBean(SaleStatsInfo.class));

        ...
        query.getSingleResult();

回答by Hannes

Hibernate will fill any pojo if you privide a propper constructor.

如果您提供一个合适的构造函数,Hibernate 将填充任何 pojo。

select new Pojo(p1, p2, p3,...) from entity)

select new Pojo(p1, p2, p3,...) from entity)

will return a list of Pojo instances.

将返回 Pojo 实例的列表。

回答by jeff

Put your @SqlResultSetMapping annotation in a class which is an actual entity, not in the DTO Class. Your entity manager can not discover your mapping when you annotate a SqlResultSetMapping in a non-entity.

将您的 @SqlResultSetMapping 注释放在一个实际实体的类中,而不是放在 DTO 类中。当您在非实体中注释 SqlResultSetMapping 时,您的实体管理器无法发现您的映射。

@SqlResultSetMapping(name = "AggregateStatsResult", classes = {
    @ConstructorResult(targetClass = AggregateStatsDto.class,
            columns = {
                    @ColumnResult(name = "total"),
                    @ColumnResult(name = "totalSum")
            })
})
@Entity
public class SomeOtherClassWhichIsAnEntity {

回答by goyalshub1509

I struggled a lot in this issue and finally a found a good solution.

我在这个问题上挣扎了很多,终于找到了一个很好的解决方案。

Situation: I have a native query and I am fetching only few fields or all fields from the database table or may be I also have some operations on columns while I am fetching data from table.

情况:我有一个本机查询,我只从数据库表中获取几个字段或所有字段,或者我在从表中获取数据时也对列进行了一些操作。

Now I want to map the output of this nativequery which we get using getResultList() method into a own POJO class/non-JPA class. The output of getResultList() is a list of objects i.e. List, so we need to manually loop through and set values into our bean/pojo class. Looks at the snippet below.

现在我想将我们使用 getResultList() 方法获得的这个 nativequery 的输出映射到一个自己的 POJO 类/非 JPA 类中。getResultList() 的输出是一个对象列表,即 List,因此我们需要手动循环并将值设置到我们的 bean/pojo 类中。看看下面的片段。

So my query is this -

所以我的查询是这样的 -

// This is your POJO/bean class where you have settter/getter 
// methods of values you want to fetch from the database
List<YourPOJO> yourPOJOList = new ArrayList<YourPOJO>();
YourPOJO pojo = null;

StringBuffer SQL = new StringBuffer();
// I am creating some random SQL query
SQL.append("SELECT tb1.col1, ");
SQL.append(" tb1.col2, ");
SQL.append(" tb2.col3, ");
SQL.append("FROM Table1 tb1, Table2 tb2 ");
SQL.append("WHERE tb1.ID = tb2.ID       ");

qry = getEntityManager().createNativeQuery(SQL.toString());
List<Object[]> cdList = qry.getResultList();

for(Object[] object : cdList){
pojo = new YourPojo();

// Here you manually obtain value from object and map to your pojo setters
pojo.setCode(object[0]!=null ? object[0].toString() : "");

pojo.setProductName(object[1]!=null ? object[1].toString() : "");

pojo.setSomeCode(object[2]!=null ? object[2].toString() : "");

yourPOJOList.add(pojo);
}

回答by AbstactVersion

This is not the suggested way . The more efficient way is mentioned above with @SqlResultSetMapping but in case you want something more hardcore you can access the Entity Manager's result by the object it returns .

这不是建议的方式。上面使用@SqlResultSetMapping 提到了更有效的方法,但如果您想要更核心的东西,您可以通过它返回的对象访问实体管理器的结果。

For instance :

例如 :

 Query q = getEntityManager().createNativeQuery(queryString);

Trggering that with q.getSingleResult();brings back to u an Object of type java.util.HashMapwhich you can use to access your results row by row .

触发它 q.getSingleResult();会给你带回一个类型的对象 java.util.HashMap,你可以用它来逐行访问你的结果。

For instance:

例如:

    Query q = getEntityManager().createNativeQuery(queryString);
    java.util.HashMap res =  (java.util.HashMap) q.getSingleResult();
     for (Object key : res.keySet()) {
         System.out.println(key.toString());
         System.out.println( res.get(key).toString());
     }