Spring Service层调用Oracle存储过程保证同一事务

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Spring Service层调用Oracle存储过程保证同一事务

在一个标记了@Transactional注解的Spring Service层bean方法里调用了一

个存储过程处理数据,后续还执行一系列的程序代码来处理数据,需要保证后面的程序代码报错后让存储过程插入更新的数据也回滚,即使用的数据库Connection为同一个,也就是说事务要是同一个。

经多次测试发现,通过dataSource获取Connection或者SessionFactory的方式获取Connection,都不是同一个connection,因为连接池返回的不是同一个接连。但通过DataSourceUtil工具获取的连接为同一个connection,因为它是将连接通过TreadLocal的方式绑定在线程本地变量里,使得在整个线程的过程中都使用的是同一个数据库连接,而事务是基于同一个数据库连接的。

例子:亲测可行!!!

存储过程如下:

create or replace procedure PRC_TEST(jkdmxx in varchar2,pclywid in number, flag out number) is

v_ErrorCode NUMBER;

v_ErrorTextVARCHAR2(2000);

begin

insert into T_JFRXX(JFR_ID,JFR_MC,DLYHMC,JFZH,DW_ID,ZT,CJSJ)

values(10000,'成功测试','成功测试

123','033432-180********',10135,'100',sysdate);

flag :=1;

exception

when others then

flag :=0;

v_ErrorCode := SQLCODE;

v_ErrorText := SUBSTR(SQLERRM, 1, 200);

rollback;

insert into T_JFRXX(JFR_ID,JFR_MC,DLYHMC,JFZH,DW_ID,ZT,CJSJ)

values(10001,'失败测试','失败测试

123','033432-180********',10135,'1',sysdate);

commit;

RAISE_APPLICATION_ERROR(-20001, '单机文件存储过程处理异常'); --抛出异常让程序捕获

end PRC_TEST;

注意:存储过程正常业务逻辑代码里,不能有显示的commit;

程序代码如下:

@Override

@Transactional(rollbackFor = Throwable.class, readOnly = false)

public void handleFmData(Listpclwids) throws SQLException { Connection connection = null;

CallableStatementcstm = null;

try {

connection =

DataSourceUtils.getConnection(dataSource);

booleanisConnectionTransactional = DataSourceUtils.isConnectionTransactional(connection, dataSource);

System.out.println(isConnectionTransactional);

cstm = connection.prepareCall("{call

prc_test(?,?,?)}");

cstm = connection.prepareCall("{call

prc_test(?,?,?)}");

cstm.setString(1, Constant.JKXX_FMLXKPWJ_DSDJ);

cstm.setInt(2, 1);

cstm.registerOutParameter(3,

java.sql.Types.INTEGER);

cstm.executeUpdate();

Integer retValue = cstm.getInt(3);

System.out.println("存储过程返回值: " + retValue);

JfrxxjfrxxDB = jfrxxRep.findById(10000L);

BizException.throwWhenNull(jfrxxDB,"无法找到对象");//检查存储过程是否插入数据成功

//后续的程序逻辑代码

Jfrxxjfrxx = new Jfrxx();

jfrxx.setZt("1");

jfrxx.setCjsj(TimeUtils.getSystemDateTime());

jfrxx.setDlyhmc("后台代码");

jfrxx.setDwId(10135L);

jfrxx.setJfrMc("后台代码测试插入");

jfrxx.setJfzh("033532-180********");

jfrxxRep.save(jfrxx);

} catch (Exception e) {

logger.error(ExceptionUtils.getStackTrace(e));

throw new BizException(e);//只有这里抛出异常到事务方法外,才会回滚

} finally {

JdbcUtils.closeStatement(cstm);

DataSourceUtils.releaseConnection(connection, dataSource);

}

}

相关文档
最新文档