我被迫从代码管理自动增量字段。我决定编写一个存储过程来为我做这个。我们的想法是拥有一个插入新行并将自动递增的值返回给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提供所有帮助。
答案 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限制,则可以帮助您解决支持的内容和需要什么。