Spring事务 - 在Sybase过程

时间:2017-09-20 07:21:04

标签: java spring stored-procedures sybase spring-transactions

我在项目中的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)在程序内部创建临时表是否会启动隐式事务?

1 个答案:

答案 0 :(得分:1)

如果没有关于你的proc(w / temp表)如何失败的更多细节,我会猜测这个问题......

  • 创建proc之后执行sp_procxmode / chained,这意味着proc应该以链式事务模式运行(即,proc将在事务中调用)
  • proc没有#temp表
  • 就运行正常
  • 尝试创建#temp表时proc'失败';我猜'失败'意味着你得到一条错误信息......某些事情......“无法在交易中创建#temp表”
  • 我将假设这是Sybase ASE ......

缺省情况下,Sybase ASE不允许在事务中使用DDL;这包括不允许在事务中创建#temp表。

您的应用程序似乎可能在链式事务模式下运行;这意味着所有数据库调用总是在一个事务中,包括尝试创建#temp表的存储过程执行,即proc正在尝试在事务内创建一个#temp表。

由于事务中不允许使用DDL(例如,#temp表创建),因此proc执行失败(ASE生成错误,基本上表明您无法在事务中创建#temp表)。

查看Spring的 NOT_SUPPORTED 选项的文档,(对我来说)这会导致proc在任何事务控制之外执行(例如,切换到unchained模式);最终结果是,由于proc不在事务中,现在可以创建#temp表。

我也猜测通过切换到 NOT_SUPPORTED ,你可能会破坏一个更大的事务(无法从这个代码的小花絮中真正告诉你;你必须要看看在你的整体交易模型中,看看这是好事还是坏事。)

如果我的假设/猜测是正确的,您将不得不(重新)访问您的应用程序的事务模型,以确保在事务内部确保您不发布DDL(例如,创建#temp表)。