是否必须在hibernate中的createSqlQuery()中使用addScalar()?为什么我们需要在执行SQL查询时指定要休眠的数据类型?

时间:2015-08-13 19:17:32

标签: java sql hibernate hql

String sql = "select Band.band_id bandId from guest_band Band";
   sessionFactory.getCurrentSession().createSQLQuery(sql)
    .addScalar("bandId", Hibernate.LONG)
    .list();

我知道addScalar()用于表示所选项的数据类型hibernate,在这种情况下为bandId。 但我的问题是,为什么我们需要指定要休眠的类型?它内部执行什么?其次,如果我们不添加标签(),这是一个例外吗?最后,有没有其他方法可以实现这一目标?

3 个答案:

答案 0 :(得分:3)

这不是强制性的,但肯定有助于使用

来自https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querysql.html

最基本的SQL查询是获取标量列表(值)。

sess.createSQLQuery("SELECT * FROM CATS").list();
sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").list();

这些将返回一个对象数组列表(Object []),其中包含CATS表中每列的标量值。 Hibernate将使用ResultSetMetadata来推断返回的标量值的实际顺序和类型。

为了避免使用ResultSetMetadata的开销,或者只是在返回的内容中更明确,可以使用addScalar():

sess.createSQLQuery("SELECT * FROM CATS")
 .addScalar("ID", Hibernate.LONG)
 .addScalar("NAME", Hibernate.STRING)
 .addScalar("BIRTHDATE", Hibernate.DATE)

此查询指定:

  

SQL查询字符串   要返回的列和类型

这将返回Object数组,但现在它不会使用ResultSetMetadata,而是显式地将ID,NAME和BIRTHDATE列分别从底层结果集中获取Long,String和Short。

  

这也意味着只返回这三列   虽然查询使用*并且可以返回超过三个   列出的专栏。

可以省略所有或部分标量的类型信息。

sess.createSQLQuery("SELECT * FROM CATS")
 .addScalar("ID", Hibernate.LONG)
 .addScalar("NAME")
 .addScalar("BIRTHDATE")

这与以前的查询基本相同,但现在ResultSetMetaData用于确定NAME和BIRTHDATE的类型,其中明确指定了ID类型。

如何将从ResultSetMetaData返回的java.sql.Types映射到Hibernate类型由Dialect控制。如果没有映射特定类型,或者没有产生预期类型,则可以通过调用Dialect中的registerHibernateType来自定义它。

答案 1 :(得分:1)

使用addScalar的简单示例:

public byte[] getFile(Integer id){
Query q = session
    .createSQLQuery("select some_file from tbl_name where id=:id")
            .addScalar("some_file", StandardBasicTypes.BINARY);
    q.setInteger("id", id);
    return (byte[]) q.uniqueResult();
}

例如,您的数据库中有blob数据类型,在这种情况下,您可以轻松地将结果转换为byte [],但如果您运行不带addScalar函数的查询,您将获得结果作为blob而不能直接将blob转换为byte [],需要编写转换代码:

try{
    Blob blob =(Blob)q.uniqueResult();
    int blobLength = (int) blob.length();  
    byte[] blobAsBytes = blob.getBytes(1, blobLength);
    return blobAsBytes;
} catch (Exception e) {
    return null;
}

在这个问题中,使用addScalar要容易得多。

答案 2 :(得分:0)

就我而言,没有必要。我从来没有用.addScalar编写查询。

您可以简单地用以下内容替换它:

Query q = sessionFactory.getCurrentSession().createQuery(
                "select b.band_id " +
                "from guest_band as b "
                );

List idList = q.list();

虽然这可能取决于您的实体的设置方式,但它应该有效。

或许.createSQLQuery.createQuery以这种方式不同。

请参阅此帖子,了解.addScalar()实际执行的操作:What does addScalar do?

编辑:我熟悉Java,我想我假设您使用Java作为帖子。如果使用C#,这可能会有所不同。