2010-06-02 99 views
3

我被迫从代码管理自动增量字段。我决定写一个存储过程为我做这个。我们的想法是创建一个插入新行的过程,并将自动递增的值返回给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对所有帮助。

回答

4

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

16.2.2. Using stored procedures for querying

Hibernate3中提供了通过存储过程 查询和 功能的支持。大多数以下 文档对于两者都是等效的。 存储过程/函数必须返回结果集作为第一个输出参数,以便能够与 休眠一起使用。 (...)与

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 server有如下规则:

  • 过程必须返回一个结果集。注意,因为这些服务器可以 返回多个结果集和更新计数 ,Hibernate将在 结果和采取的第一个结果是 是设定它的返回值的结果。 其他一切都将被丢弃。
  • 如果您可以在您的程序中启用SET NOCOUNT ON,它可能会更有效,但这不是 的要求。
0

免责声明:我绝不熟悉冬眠,还是Java,但是从我读上面你似乎需要有至少在这个单个ResultSet工作!? 鉴于SQL-2005标签,我假设你的代码是在T-SQL中的,因此我想指出你的代码在这方面是'有缺陷的',它可能是(有,很小的机会,但仍然)发生另一个连接在您选择@newval和您执行实际插入的那一刻之间将新记录插入到表中。 这可以通过使用锁定或恕我直言更简单地通过将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的限制,帮助您无论在什么支持我们所需要的