2010-06-02 101 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的限制,幫助您無論在什麼支持我們所需要的