我在项目中的DAO方法上应用了spring transaction,如下所示
@Transactional(readOnly=false, propagation=Propagation.REQUIRED)
public String updateUser(Integer userId, String address)
{
//calling sybase procedure to update user address
}
Sybase程序
CREATE PROCEDURE sp_update_user_address
@user_id numeric(9,0),
@address varchar(500)
AS
BEGIN
UPDATE users
SET address = @address,
WHERE user_id = @user_id
and user_status <> 'I'
END
go
EXEC sp_procxmode 'sp_update_user_address', 'chained'
该过程执行精细更新users表中的记录。但是,当我们在程序中创建临时表时,失败(记录未更新),如下所示
//creating temporary table in procedure for some logic
CREATE TABLE #usertemp
(
id int null,
address varchar(500)
)
1)为什么在程序中创建临时表会导致事务(更新操作)失败?。我通过使用 Propagation.NOT_SUPPORTED 注释方法解决了这个问题。
2)为什么 Propagation.REQUIRED 没有成功执行程序(有临时表)?
3)在程序内部创建临时表是否会启动隐式事务?
答案 0 :(得分:1)
如果没有关于你的proc(w / temp表)如何失败的更多细节,我会猜测这个问题......
sp_procxmode / chained
,这意味着proc应该以链式事务模式运行(即,proc将在事务中调用)缺省情况下,Sybase ASE不允许在事务中使用DDL;这包括不允许在事务中创建#temp表。
您的应用程序似乎可能在链式事务模式下运行;这意味着所有数据库调用总是在一个事务中,包括尝试创建#temp表的存储过程执行,即proc正在尝试在事务内创建一个#temp表。
由于事务中不允许使用DDL(例如,#temp表创建),因此proc执行失败(ASE生成错误,基本上表明您无法在事务中创建#temp表)。
查看Spring的 NOT_SUPPORTED 选项的文档,(对我来说)这会导致proc在任何事务控制之外执行(例如,切换到unchained模式);最终结果是,由于proc不在事务中,现在可以创建#temp表。
我也猜测通过切换到 NOT_SUPPORTED ,你可能会破坏一个更大的事务(无法从这个代码的小花絮中真正告诉你;你必须要看看在你的整体交易模型中,看看这是好事还是坏事。)
如果我的假设/猜测是正确的,您将不得不(重新)访问您的应用程序的事务模型,以确保在事务内部确保您不发布DDL(例如,创建#temp表)。