Java 如何使用Hibernate HQL结果避免类型安全警告?

Java 如何使用Hibernate HQL结果避免类型安全警告?,java,generics,Java,Generics,例如,我有这样的疑问: Query q = sess.createQuery("from Cat cat"); List cats = q.list(); 如果我尝试做这样的事情,它会显示以下警告 Type safety: The expression of type List needs unchecked conversion to conform to List<Cat> List<Cat> cats = q.list(); 类型安全性:类型列表的表达式需要

例如,我有这样的疑问:

Query q = sess.createQuery("from Cat cat");
List cats = q.list();
如果我尝试做这样的事情,它会显示以下警告

Type safety: The expression of type List needs unchecked conversion to conform to List<Cat>


List<Cat> cats = q.list();
类型安全性:类型列表的表达式需要未经检查的转换才能符合列表
列表猫=q.List();

有什么方法可以避免吗?

在我们的代码中,我们用以下注释调用方法:

@抑制警告(“未选中”)


我知道这看起来像是一次黑客攻击,但一位联合开发人员最近检查了一下,发现这是我们所能做的一切。

不,但您可以将其隔离到特定的查询方法中,并使用
@SuppressWarnings(“unchecked”)
注释来抑制警告。

如果您不想使用@SuppressWarnings(“unched”)可以执行以下操作

   Query q = sess.createQuery("from Cat cat");
   List<?> results =(List<?>) q.list();
   List<Cat> cats = new ArrayList<Cat>();
   for(Object result:results) {
       Cat cat = (Cat) result;
       cats.add(cat);
    }
Query q=sess.createQuery(“来自Cat”);
列表结果=(列表)q.List();
列表猫=新的ArrayList();
用于(对象结果:结果){
Cat=(Cat)结果;
cats.add(cat);
}

仅供参考-我创建了一个util方法来为我实现这一点,这样它就不会乱扔我的代码,我也不必使用@SupersWarning

我们也使用
@SuppressWarnings(“unchecked”)
,但我们通常只尝试在变量声明中使用它,而不是在整个方法中使用它:

public List<Cat> findAll() {
    Query q = sess.createQuery("from Cat cat");
    @SuppressWarnings("unchecked")
    List<Cat> cats = q.list();
    return cats;
}
公共列表findAll(){
Query q=sess.createQuery(“来自Cat”);
@抑制警告(“未选中”)
列表猫=q.List();
返回猫;
}

如建议的那样,在任何地方使用
@SuppressWarnings
都是一种很好的方法,尽管每次调用
q.list()
时都需要用手指打字

我还建议使用另外两种技术:

编写一个cast助手

只需将所有
@SuppressWarnings
重构到一个位置:

List<Cat> cats = MyHibernateUtils.listAndCast(q);

...

public static <T> List<T> listAndCast(Query q) {
    @SuppressWarnings("unchecked")
    List list = q.list();
    return list;
}
List cats=MyHibernateUtils.listAndCast(q);
...
公共静态列表listAndCast(查询q){
@抑制警告(“未选中”)
List=q.List();
退货清单;
}
防止Eclipse为不可避免的问题生成警告

在Eclipse中,转到窗口>首选项>Java>编译器>错误/警告,并在泛型类型下选中复选框
忽略由于原始API而不可避免的泛型类型问题

这将关闭类似问题的不必要警告,如上述不可避免的问题

一些评论:

  • 我选择传入
    Query
    而不是
    q.list()
    的结果,因为这样一来,这种“作弊”方法只能用于Hibernate作弊,一般来说不能用于作弊任何
    list
  • 您可以为
    .iterate()
    等添加类似的方法

    • 我们也有同样的问题。但这对我们来说没什么大不了的,因为我们必须用Hibernate查询和会话解决其他更重要的问题

      具体而言:

    • 控制何时可以提交事务。(我们想计算一个发送被“启动”的次数,并且只在发送被“结束”时提交与启动相同的次数。对于不知道是否需要启动事务的代码非常有用。现在,任何需要发送的代码都只“启动”一个,完成后结束。)
    • 性能指标收集
    • 延迟启动事务,直到知道某些事情将实际完成
    • query.uniqueResult()的更温和的行为
    • 因此,对于我们来说,我们有:

    • 创建扩展查询的接口(AmplafiQuery)
    • 创建一个类(AmplafiQueryImpl),该类扩展AmplafiQuery并包装org.hibernate.Query
    • 创建一个返回Tx的Txmanager
    • Tx具有各种createQuery方法并返回AmplafiQueryImpl
    • 最后

      AmplafiQuery有一个“asList()”,它是Query.list()的通用启用版本 AmplafiQuery有一个“unique()”,它是Query.uniqueResult()的通用版本(并且只记录问题,而不是引发异常)


      为了避免@SuppressWarnings,这需要做很多工作。然而,正如我所说(并列出)还有很多其他更好的!包装工作的原因。

      这不是疏忽或错误。这个警告反映了一个真正的潜在问题——java编译器无法真正确保hibernate类能够正确地完成它的工作,并且它返回的列表将只包含CAT。这里的任何建议都很好。

      我知道这是比较老的建议,但在马特鹌鹑的回答中,今天需要注意两点

      第1点 这个

      对此

      List<T> list = q.list();
      
      List List=q.List();
      
      将明显减少浏览器删除原始回复标记中的其他警告。

      显然,Hibernate API中的Query.list()方法“按设计”不是类型安全的,并且存在

      我相信避免编译器警告的最简单解决方案就是添加@SuppressWarnings(“unchecked”)。这是在方法级别,或者,如果在方法内部,则在变量声明之前

      若您有一个封装Query.list()并返回list(或Collection)的方法,您还会收到一条警告。但是,使用@SuppressWarnings(“rawtypes”)可以抑制这一点

      Matt Quail提出的listAndCast(查询)方法不如Query.list()灵活。 虽然我能做到:

      Query q = sess.createQuery("from Cat cat");
      ArrayList cats = q.list();
      
      如果我尝试下面的代码:

      Query q = sess.createQuery("from Cat cat");
      ArrayList<Cat> cats = MyHibernateUtils.listAndCast(q);
      
      Query q=sess.createQuery(“来自Cat”);
      ArrayList猫=MyHibernateUtils.listAndCast(q);
      
      我将得到一个编译错误:类型不匹配:无法从列表转换为ArrayList

      Query q = sess.createQuery("from Cat cat");
      List<?> results = q.list();
      for (Object obj : results) {
          Cat cat = (Cat) obj;
      }
      
      Query q=sess.createQuery(“来自Cat”);
      列表结果=q.List();
      对于(对象对象对象:结果){
      Cat=(Cat)obj;
      }
      
      很久没有人问这个问题了,但我希望我的回答可能对像我这样的人有所帮助

      如果您查看javax.persistence,您将看到自
      javapersistence2.0
      以来添加了一些新方法。其中之一是
      create
      
      Query q = sess.createQuery("from Cat cat");
      ArrayList cats = q.list();
      
      Query q = sess.createQuery("from Cat cat");
      ArrayList<Cat> cats = MyHibernateUtils.listAndCast(q);
      
      Query q = sess.createQuery("from Cat cat");
      List<?> results = q.list();
      for (Object obj : results) {
          Cat cat = (Cat) obj;
      }
      
      Query q = sess.createQuery("from Cat cat", Cat.class);
      List<Cat> cats = q.list();
      
      Cat cat = from(Cat.class);
      org.torpedoquery.jpa.Query<Entity> select = select(cat);
      List<Cat> cats = select.list(entityManager);
      
      Query q = sess.createQuery("from Cat cat", Cat.class);
      List<Cat> cats = q.list();
      
      TypedQuery<Cat> q1 = sess.createQuery("from Cat cat", Cat.class);
      List<Cat> cats = q1.list();
      
      Query<Cat> query = session.createQuery("FROM Cat", Cat.class);
      List<Cat> cats = query.list();
      
      public Integer count() {
          Query<Integer> query = sessionFactory.getCurrentSession().createQuery("SELECT COUNT(id) FROM Cat", Integer.class);
          return query.getSingleResult();
      }
      
      public List<Object[]> String getName() {
          Query<Object[]> query = sessionFactory.getCurrentSession().createQuery("SELECT id, name FROM Cat", Object[].class);
          return query.list();
      }
      
      TypedQuery<EntityName> createQuery = entityManager.createQuery("from EntityName", EntityName.class);
      List<EntityName> resultList = createQuery.getResultList();