Hibernate存储过程结果

时间:2010-06-02 15:17:35

标签: sql-server-2005 hibernate stored-procedures

我被迫从代码管理自动增量字段。我决定编写一个存储过程来为我做这个。我们的想法是拥有一个插入新行并将自动递增的值返回给Java的过程,以便我可以进一步使用它。以下是我到目前为止的情况。我不知道要改变什么来填补空白,使一切顺利。

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE addNewMSO
    @sourceApplication char(8), 
    @selectionStatusDate datetime = NULL,
    @sysLstUpdtUserId char(10)
AS
BEGIN
    SET NOCOUNT ON;

    Declare @newVal int
    SET @newVal = (select max(seqNo) from MemberSelectedOptions) + 1

    INSERT INTO MemberSelectedOptions
       ([SourceApplication]
       ,[SeqNo]
       ,[SelectionStatusDate]
       ,[SysLstUpdtUserId])
 VALUES
      (@sourceApplication
       ,@newVal
       ,@selectionStatusDate
       ,@sysLstUpdtUserId)

END
GO

然后在我的Java代码中,我有以下内容。

@NamedNativeQuery(name="addNewMSO", 
  query="exec addNewMSO :sourceApplication :selectionStatusDate :sysLstUpdtUserId", callable=true)

我的DAO就这样称呼它......

Query q = session.getNamedQuery("addNewMSO");
q.setParameter("sourceApplication", mso.getSourceApplication());
q.setParameter("selectionStatusDate", mso.getSelectionStatusDate());
q.setParameter("sysLstUpdtUserId", mso.getSysLstUpdtUserId());
q.executeUpdate();

即使这样,这也行不通,因为我得到了“尚未支持纯本机标量查询”错误。所以我不知道下一步该去哪里。我已经阅读了Hibernate文档,但我不知道如何从SP获取返回值。但我还是不能称之为......呃!

TIA提供所有帮助。

2 个答案:

答案 0 :(得分:5)

如果您的SP没有返回结果集,那么我担心您将不得不使用session.getConnection()和原始JDBC。根据Hibernate的文档:

  

16.2.2. Using stored procedures for querying

     

Hibernate3提供支持   通过存储过程查询和   功能。大部分以下内容   文档对两者都是等价的。   存储过程/函数必须返回结果集作为第一个   out-parameter能够使用   冬眠即可。 (...)

     

16.2.2.1. Rules/limitations for using stored procedures

     

您无法使用存储过程   Hibernate,除非你遵循一些   程序/功能规则。 如果有的话   不遵循他们不遵守的规则   可用于Hibernate。如果你还是   想要使用这些程序   通过执行它们   session.connection() 即可。规则是   因为每个数据库都不同   数据库供应商有不同的存储   过程语义/语法。

     

存储过程查询不能   分页   setFirstResult()/setMaxResults()

     

推荐的致电表格是标准的   SQL92:{ ? = call functionName(<parameters>) }{ ? = call procedureName(<parameters>}。不支持本机调用语法。

     

(...)

     

对于Sybase或MS SQL服务器,以下规则适用:

     
      
  • 该过程必须返回结果集。请注意,因为这些服务器可以   返回多个结果集并进行更新   计数,Hibernate将迭代   结果并取得第一个结果   是一个结果集作为其返回值。   其他一切都将被丢弃。
  •   
  • 如果您可以在您的程序中启用SET NOCOUNT ON,则可能是   效率更高,但这不是一个   要求。
  •   

答案 1 :(得分:0)

免责声明:我不熟悉HIBERNATE,也不熟悉Java,但从我上面的内容来看,您似乎需要至少有一个结果集才能实现这一点! 鉴于SQL-2005标签,我假设您的代码是在T-SQL中,因此我想指出您的代码在这方面是“有缺陷的”它可能(是的,非常小的机会,但仍然)发生另一个连接在您选择@newval和执行实际插入的那一刻之间将新记录插入到表中。 这可以通过使用锁定或IMHO来解决,更简单地将INSERT和SELECT放在单个语句中。添加ISNULL()还将确保如果您需要使用空表重新启动,即使存储过程没有要添加的起始值,存储过程仍将按预期运行。

CREATE PROCEDURE addNewMSO
@sourceApplication char(8), 
@selectionStatusDate datetime = NULL,
@sysLstUpdtUserId char(10)
AS
BEGIN
SET NOCOUNT ON;

INSERT INTO MemberSelectedOptions
   ([SourceApplication]
   ,[SeqNo]
   ,[SelectionStatusDate]
   ,[SysLstUpdtUserId])
OUTPUT (inserted.[SeqNo])
 SELECT [SourceApplication]   = @sourceApplication,
    [SeqNo]               = ISNULL((SELECT max([SeqNo]) FROM MemberSelectedOptions), 0) + 1,
    [SelectionStatusDate] = @selectionStatusDate,
    [SysLstUpdtUserId]    = @sysLstUpdtUserId
END

OUTPUT子句将在记录集中返回新插入的值,如果我正确理解了HIBERNATE限制,则可以帮助您解决支持的内容需要什么