为了账号安全,请及时绑定邮箱和手机立即绑定

如何以类型安全的方式运行 Hibernate NativeQuery 而不是返回 Object[]

如何以类型安全的方式运行 Hibernate NativeQuery 而不是返回 Object[]

潇潇雨雨 2021-09-03 10:21:40
我正在将应用程序从 Hibernate 4.x 迁移到 Hibernate 5.3.6。该应用程序有这样的查询:SQLQuery query = getSession().createSQLQuery("SELECT a.a, a.b, a.c FROM aTable");由于createSQLQuery方法已被弃用,我首先用 Hibernate Javadoc 中建议的替代方法替换了方法调用,即使用 createNativeQuery:NativeQuery query = getSession().createNativeQuery("SELECT a.a, a.b, a.c FROM aTable");这样做的问题是它会产生一个编译器警告“NativeQuery 是原始类型。对泛型类型 NativeQuery 的引用应该被参数化”。此外,当然,我想从类型化查询中受益,因为现在它们可用。所以我将查询更改为NativeQuery<Object[]> query = getSession().createNativeQuery("SELECT a.a, a.b, a.c FROM aTable", Object[].class);现在的问题是执行查询List<Object[]> retList = query.list();产生错误javax.persistence.PersistenceException:org.hibernate.MappingException:未知实体:[Ljava.lang.Object;研究这个问题似乎表明在使用类型化本机查询时不可能使用非映射实体(这似乎是一个严重且不必要的限制,但我在这里离题了)。问题是:有没有什么方法可以在实现类型安全的同时执行本地 SQL 查询,使用 Hibernate 返回一个对象数组,而不会产生编译器警告?如果没有,是否有任何明智的选择?
查看完整描述

3 回答

?
万千封印

TA贡献1891条经验 获得超3个赞

这种投影有更好的替代方案,而不是默认的Object[]。


您可以使用 JPAjavax.persistence.Tuple结果集,因为Hibernate ORM 5.2.11适用于本机 SQL:


 List<Tuple> postDTOs = entityManager

 .createNativeQuery(

     "SELECT " +

     "       p.id AS id, " +

     "       p.title AS title " +

     "FROM Post p " +

     "WHERE p.created_on > :fromTimestamp", Tuple.class)

 .setParameter( "fromTimestamp", Timestamp.from(

     LocalDateTime.of( 2016, 1, 1, 0, 0, 0 )

         .toInstant( ZoneOffset.UTC ) ))

 .getResultList();

您可以使用 Hibernate-specific ResultTransformer,它允许您构建非常复杂的 DTO 结构(例如图形):


 List postDTOs = entityManager

 .createNativeQuery(

     "select " +

     "       p.id as \"id\", " +

     "       p.title as \"title\" " +

     "from Post p " +

     "where p.created_on > :fromTimestamp")

 .setParameter( "fromTimestamp", Timestamp.from(

     LocalDateTime.of( 2016, 1, 1, 0, 0, 0 ).toInstant( ZoneOffset.UTC ) ))

 .unwrap( org.hibernate.query.NativeQuery.class )

 .setResultTransformer( Transformers.aliasToBean( PostDTO.class ) )

 .getResultList();

您还可以使用命名的本机查询:


 List<PostDTO> postDTOs = entityManager

 .createNamedQuery("PostDTO")

 .setParameter( "fromTimestamp", Timestamp.from(

     LocalDateTime.of( 2016, 1, 1, 0, 0, 0 )

         .toInstant( ZoneOffset.UTC ) ))

 .getResultList();

其中PostDTO查询是一个命名的本机 SQL 查询,如下所示:


 @NamedNativeQuery(

     name = "PostDTO",

     query =

         "SELECT " +

         "       p.id AS id, " +

         "       p.title AS title " +

         "FROM Post p " +

         "WHERE p.created_on > :fromTimestamp",

     resultSetMapping = "PostDTO"

 )

 @SqlResultSetMapping(

     name = "PostDTO",

     classes = @ConstructorResult(

         targetClass = PostDTO.class,

         columns = {

             @ColumnResult(name = "id"),

             @ColumnResult(name = "title")

         }

     )

 )

酷,对吧?


查看完整回答
反对 回复 2021-09-03
?
慕慕森

TA贡献1856条经验 获得超17个赞

只需通过调用创建它

createNativeQuery("SELECT a.a, a.b, a.c FROM aTable");

它将默认返回一行Object[].

该警告与您的情况无关,因此只需将其压制即可。


查看完整回答
反对 回复 2021-09-03
  • 3 回答
  • 0 关注
  • 261 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信