现在的位置: 首页 > 综合 > 正文

让Hibernate和触发器协同工作

2013年10月11日 ⁄ 综合 ⁄ 共 1973字 ⁄ 字号 评论关闭

Sql Server触发器和hibernate一起使用时经常报类似如下错误

Batch update returned unexpected row count from update [0];

这个问题困扰了我半年,不止上面的错误还有其他类似的错误,半年内一直很郁闷,半年是什么概念真是晕倒,曾经也百度过但是没有解决方案,很多回答都是说hibernate和sqlserver 兼容不好,或者说程序是oo的不能用触发器,但这些都不是解决问题的方法,今天又遇到同事写的程序有这个问题,因为这个问题,我已经不将hibernate和sqlserver触发器一起使用了,但是遇到了就得解决,仔细分析这段话

Batch update returned unexpected row count from update [0];

批量保存失败,因为返回的行数和预期的不一样,从语意上来看hibernate做的是对的,因为如果只写一句session.update(u);hibernate是有理由做校验的,这时我在想如何能让hibernate感知不到触发器的工作,前几天写存储过程使用临时表的一个小技巧给了我提示.

前段时间我写个了针对存储过程的java调用封装

http://blog.csdn.net/sunyujia/archive/2008/05/18/2456325.aspx

我把这段程序放到了实际项目中,但是我的同事在使用的时候却遇到了问题。如果存储过程中这样写

select * into #t from table

在java中利用我封装的类无法取得最后返回的结果集,起初我认为是我封装的程序有问题,后来查看了前人写的存储过程发现了线索,原来少了一句set nocount on,这句话起关键作用。

从单词上看,意思是不计数返回的行数,当时我还没有预见到这句话可以解决hibernate和触发器协作的问题,直到今天我突然联想到了这件事,因为这几天还一直在做数据库性能优化,set nocount on还可以起到性能优化的作用。

所以今天再次遇到hibernate和触发器冲突的问题时,我突然想到了set nocount on,有了这句话java程序就感知不到返回的行数了也自然谈不上unexpected的问题了。

至于hibernate和触发器一起工作的其他问题我目前还没发现有障碍性的,基本通过编程都可以解决,至于session同步,刷新就可以了。

为了说明问题还是发小段代码

SET QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS ON 
GO
Create  TRIGGER [Syj_User_Triger] ON [dbo].[Syj_User] 
FOR INSERT, UPDATE, DELETE 
AS
set nocount on  --不加这句话hibernate会报错,因为下面的update操作计数返回的值>1
update authors set state=state 
GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO
SET NOCOUNT

最后看下sqlserver帮助里面的解释

SET NOCOUNT

使返回的结果中不包含有关受 Transact-SQL 语句影响的行数的信息。

语法

SET NOCOUNT { ON | OFF }

注释

当 SET NOCOUNT 为 ON 时,不返回计数(表示受 Transact-SQL 语句影响的行数)。当 SET NOCOUNT 为 OFF 时,返回计数。

即使当 SET NOCOUNT 为 ON 时,也更新 @@ROWCOUNT 函数。

当 SET NOCOUNT 为 ON 时,将不给客户端发送存储过程中的每个语句的 DONE_IN_PROC 信息。当使用 Microsoft® SQL Server™ 提供的实用工具执行查询时,在 Transact-SQL 语句(如 SELECT、INSERT、UPDATE 和 DELETE)结束时将不会在查询结果中显示"nn rows affected"。

如果存储过程中包含的一些语句并不返回许多实际的数据,则该设置由于大量减少了网络流量,因此可显著提高性能。

SET NOCOUNT 设置是在执行或运行时设置,而不是在分析时设置。

权限

SET NOCOUNT 权限默认授予所有用户。

示例

下例在 osql 实用工具或 SQL Server 查询分析器中执行时,可防止显示有关受影响的行数的信息。

USE pubs
GO
-- Display the count message.
SELECT au_lname 
FROM authors
GO
USE pubs
GO
-- SET NOCOUNT to ON and no longer display the count message.
SET NOCOUNT ON
GO
SELECT au_lname 
FROM authors
GO
-- Reset SET NOCOUNT to OFF.
SET NOCOUNT OFF
GO

 

请参见

@@ROWCOUNT

SET

抱歉!评论已关闭.