使用 Hibernate 和 Spring 调用存储过程

Posted

技术标签:

【中文标题】使用 Hibernate 和 Spring 调用存储过程【英文标题】:Calling Stored Procedure with Hibernate and Spring 【发布时间】:2011-12-04 20:14:13 【问题描述】:

网上有很多例子描述了如何使用Hibernate调用存储过程,但是当使用Spring时,情况会有所变化。

我在 mysql 中有一个存储过程,我想调用它: 在 SQL 中,我需要编写以下内容:

CALL inrange(32.342324,32.234234);
It returns a row with the following: `INT,INT,FLOAT`

在 Spring 中,我使用 HibernateTemplate 的方式执行休眠操作,我知道你们中的一些人不会喜欢它,但这是我刚开始项目时的样子,我并没有那么急于改变它,也许在未来……

目前,我在 Java 中有以下代码,它试图调用该过程:

List<Object[]> resultset = hibernateTemplate
                               .findByNamedQuery("inrange",
                                    person.getAddress().getLatitude(),
                                    person.getAddress().getLongitude());

当我运行它时,我得到以下 Hibernate 异常:

org.springframework.orm.hibernate3.HibernateSystemException:
   Named query not known: inrange;

我认为这是因为我没有在休眠中声明存储过程。 我的问题是:

如何申报? 是否有特殊的方式在 Spring 的应用上下文文件中声明它?

【问题讨论】:

【参考方案1】:

您可以在 hibernate 中调用本机 sql 查询。

看看这个链接: http://www.mkyong.com/hibernate/how-to-call-store-procedure-in-hibernate/

顺便说一句,如果你想调用存储过程,你可以简单地使用 Spring JdbcTemplate。

请注意,休眠扩展可以满足您的需求: http://www.hibernatespatial.org/

【讨论】:

Hibernatespatial 看起来很酷,但是我使用的是 mySQL,并且该数据库似乎不支持大多数功能,尤其是距离函数... 实际上每个数据库都提供了自己的特性/功能,您可能可以为该项目做出贡献,以便它也可以与 mySQL 一起使用。祝你好运【参考方案2】:

您将 Hibernate 的命名查询与 MySQL 的存储过程混淆了。

如果你想调用 MySQL 存储过程,通过 Hibernate 的 API 这样做没有任何好处。我推荐你使用 Spring 的 JdbcTemplate 来执行查询。

如果你绝对必须使用 Hibernate,这样的东西应该可以工作:

SQLQuery query = hibernateTemplate.getCurrentSession()
  .createSQLQuery("SELECT inrange(:latitude, :longitude)";
query.setDouble("latitude", ...);
query.setDouble("longitude", ...);
List<Object[]> result = query.list(); // requires casting for generics

【讨论】:

我不困惑,谷歌一下,你会找到我指的。【参考方案3】:

您需要将命名查询添加到您的休眠映射文件中。

你能分享你的休眠映射文件吗?您可以找到一些示例here。

除了上一个链接,您还可以通过this 访问。

如果你能共享POJO、hibernate映射和你正在使用的程序会更容易。

This blog 将为您提供帮助。我希望您在使用getHibernateTemplate().execute(HibernateCallback) 方法时不会有任何问题。

【讨论】:

其实我没有Hibernate映射文件。我正在使用 Spring 的上下文 XML & Annotations 进行休眠映射。如果您觉得有帮助,我可以发布 spring 配置。 可以分享一下POJO类吗? 没有pojo,存储过程的结果集,没有映射到pojo,都是标量。 这个问题是没有 inRange 类......它不能被映射,它是标量。 那么您可能应该考虑使用***.com/questions/4863883/… 中给出的ResultTransformer 以及***.com/questions/602397/… 来外部化注释【参考方案4】:

您可以使用 JPA,因为 Spring 在 Core 或 Spring Data 中都支持它。

可以使用StoredProcedureQuery调用存储过程,如下:

StoredProcedureQuery query = entityManager
    .createStoredProcedureQuery("count_comments")
    .registerStoredProcedureParameter(
        "postId", Long.class, ParameterMode.IN)
    .registerStoredProcedureParameter(
        "commentCount", Long.class, ParameterMode.OUT)
    .setParameter("postId", 1L);

query.execute();

Long commentCount = (Long) query
    .getOutputParameterValue("commentCount");

【讨论】:

以上是关于使用 Hibernate 和 Spring 调用存储过程的主要内容,如果未能解决你的问题,请参考以下文章

GWT 开发模式 + Spring 3.1 + Hibernate 4.0.1 中的异常

使用 spring 和 hibernate 时,如何处理会话/事务?

用struts+spring+hibernate/ibatis 框架配合,写一个输入用户名、密码,然后到数据库校验的功能

ssh整合思想 Spring与Hibernate和Struts2的action整合 调用action添加数据库 使用HibernateTemplate的save(entity)方法

Spring + Hibernate+ HikariCP:如何在进行长时间运行的 REST 调用时处理数据库连接?

如何从 Spring/Hibernate 调用存储的例程/函数?