事务嵌套,你懂多少

Spring事务的嵌套的详细理解,以及事务失效的场景解惑 Spring事务、Spring事务的传播属性、事务的嵌套、以及Spring事务失效的场景举例 阅读详情

关于事务嵌套,以前了解一些,但总是属于模棱两可,平时处理这种问题时候也是依照前人的经验,但至于为什么这么做,还真是“知其然不知其所以然”。

  今天一个同事问我关于事务的问题,我就用代码给他举例测试,在测试的过程中我遇到了一点小问题,但在继续测试的时候,我解决了这个问题,也让我对事务的嵌套有了更加深刻的认识。

  废话不再多说了,开始正题。

  本文的目的是跟大家讨论一下关于嵌套事务的相关问题,所以有关事务的基础知识和概念,本文假设读者已经了解。

  嵌套事务一般的使用场景是一些公用的,最小单元的业务逻辑,这些业务逻辑很多情况下都是被另外一些更加复杂,更加完整的业务逻辑调用。

  为了更加贴近实际,本文的例子尽量接近真实业务,在此我们拿一个电子商务网站的订单支付来进行举例,具体例子如下

  提交订单之后,支付订单(扣除账户余额)并更新订单的状态。

  根据业务,我们创建三个表

  会员表

  账户变动记录表

  订单表

  建表语句如下: 

?
CREATE TABLE T_Users(   
     Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL , --自增编号
     UserName NVARCHAR(50) NOT NULL , --用户名,保持唯一
     UserMoney DECIMAL (9,2) NOT NULL DEFAULT 0 --用户账户余额,不能小于
)
CREATE TABLE T_MoneyLog(
     Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL , --自增编号
     UserName NVARCHAR(50) NOT NULL , --用户名
     ChangeType INT NOT NULL , --账户变动类型(1支付订单,发送短信,提交参会申请)
     MoneyBefore DECIMAL (9,2) NOT NULL DEFAULT 0, --会员账户变动前余额
     ChangeMoney DECIMAL (9,2) NOT NULL DEFAULT 0, --变动的金额
     MoneyAfter DECIMAL (9,2) NOT NULL DEFAULT 0, --会员账户变动后余额
     Remark NVARCHAR(100), --账户变动备注
     AddTime DATETIME NOT NULL DEFAULT GETDATE() --变动时间
)
CREATE TABLE T_Order(
     Id INT IDENTITY(1,1) NOT NULL , --自增编号
     OrderId VARCHAR (20) NOT NULL PRIMARY KEY , --订单号
     SumMoney DECIMAL (9,2) NOT NULL DEFAULT 0, --订单总共需要支付费用
     OrderStatus INT NOT NULL DEFAULT 0, --订单状态(未支付,已支付)
     AddTime DATETIME NOT NULL DEFAULT GETDATE(), --订单提交时间
     PayTime DATETIME NULL --订单支付时间   
)

  注:因为是测试,所以这里简化了这些表。

  因为扣除账户余额是一个公用的,最小单元的业务逻辑,所以我们专门建立一个存储过程来执行该过程。代码如下: 

?
Create Proc [dbo].[Sp_UserMoneyLess]
@UserName NVARCHAR(50),     --用户名
@ChangeMoney DECIMAL (9,2),  --变动金额
@ChangeType INT ,            --账户变动类型
@Result INT OUTPUT ,         --输出参数,执行结果
@Msg NVARCHAR(100) OUTPUT   --执行结果描述
AS
--为输出参数设置默认值
SET @Result = 1 
SET @Msg = '执行成功'
DECLARE @before DECIMAL (9,2),@ after DECIMAL (9,2)
--开启事务
BEGIN TRAN UserMoneyLess
SELECT @before=tu.UserMoney FROM T_Users tu WHERE tu.UserName=@UserName
SET @ after =@before-@ChangeMoney
IF @ after <0
BEGIN
     SET @Result=-1
     SET @Msg = '账户余额不足'
     ROLLBACK TRAN UserMoneyLess
     RETURN
END
--更新会员账户余额
UPDATE T_Users SET UserMoney = @ after WHERE UserName = @UserName
IF @@ERROR<>0
BEGIN
     SET @Result = -2
     SET @Msg = '更新账户余额发生异常,异常信息:' + ERROR_MESSAGE()
     ROLLBACK TRAN UserMoneyLess
     RETURN
END
--产生账户变动记录
INSERT INTO T_MoneyLog
(
     UserName,
     ChangeType,
     MoneyBefore,
     ChangeMoney,
     MoneyAfter,
     Remark,
     AddTime
)
VALUES
(
     @UserName,
     @ChangeType,
     @before,
     @ChangeMoney,
     @ after ,
     '支付订单扣除账户余额' ,
     GETDATE()
)
IF @@ERROR<>0
BEGIN
     SET @Result = -3
     SET @Msg = '产生账户变动记录发生异常,异常信息:' + ERROR_MESSAGE()
     ROLLBACK TRAN UserMoneyLess
END
COMMIT TRAN UserMoneyLess

  现在我们来测试一下我们的Sp_UserMoneyLess,在测试之前,我们插入一些测试数据:

?
INSERT INTO T_Users
(
     UserName,
     UserMoney
)
VALUES
(
     'Geodon' ,
     100
)
INSERT INTO T_Order
(
     -- Id -- this column value is auto-generated
     OrderId,
     UserName,
     SumMoney,
     OrderStatus,
     AddTime
)
VALUES
(
     '20130303160545612' ,
     'Geodon' ,
     120,
     0,
     GETDATE()
)

  好了,测试数据已经准备完毕。现在我们可以开始我们的测试了,执行下面的测试代码:

?
DECLARE @Result INT ,@Msg NVARCHAR(200)
EXEC Sp_UserMoneyLess 'Geodon' ,120,1,@Result OUTPUT ,@Msg OUTPUT
SELECT @Result,@Msg

  运行结果:

  

  Ok没问题,是我们想要的结果。

  再进行一次测试,测试余额足够的情况,执行下面的测试代码:

?
DECLARE @Result INT ,@Msg NVARCHAR(200)
EXEC Sp_UserMoneyLess 'Geodon' ,10,1,@Result OUTPUT ,@Msg OUTPUT
SELECT @Result,@Msg

  运行结果:

    

  我们查询一下执行结果

   

  Ok没问题,正常执行。

  接下来我们再为订单支付创建一个存储过程,代码如下:

?
CREATE PROC Sp_PayOrder
@OrderId VARCHAR (20),       --订单号
@UserName NVARCHAR(50),     --用户名
@Result INT OUTPUT ,         --支付结果
@Msg NVARCHAR(100) OUTPUT   --支付结果描述
AS
--为输出参数设置默认值
SET @Result=1
SET @Msg= '执行成功'
--查询订单需要支付的金额,如果订单号不存在或者该订单支付过,返回-1,停止执行
DECLARE @orderMoney DECIMAL (9,2)
SELECT @orderMoney = to1.SumMoney FROM T_Order to1 WHERE to1.OrderId=@OrderId AND to1.OrderStatus=0 AND to1.UserName=@UserName
IF @orderMoney IS NULL
BEGIN
     SET @Result=-1
     SET @Msg= '订单号不存在或者该订单支付过'
     RETURN 
END
--开启事务
BEGIN TRAN PayOrder
  
--扣除会员账户余额
EXEC Sp_UserMoneyLess @UserName,@orderMoney,1,@Result OUTPUT ,@Msg OUTPUT
IF @Result<>1
BEGIN
     SET @Result=-2
     ROLLBACK TRAN PayOrder
     RETURN
END
--更新订单支付状态
UPDATE T_Order SET OrderStatus = 1 WHERE OrderId=@OrderId AND OrderStatus=0
COMMIT TRAN PayOrder

  这个存储过程包含了一个事务,而且在事务的内部又调用了Sp_UserMoneyLess,而Sp_UserMoneyLess这个存储过程内部又包含了一个事务,这就出现了事务嵌套的场景,这也正是本文要讨论的内容。

  我们现在进行测试,执行如下测试代码:

?
DECLARE @Result INT ,@Msg NVARCHAR(200)
EXEC Sp_PayOrder '20130303160545612' , 'Geodon' ,@Result OUTPUT ,@Msg OUTPUT
SELECT @Result,@Msg

  运行结果如下:

   

  大家可以看到,执行存储过程出现了错误

  我们先来看一下第一个错误

   

  可以看的出,这个错误是在内部事务回滚带有名称的事务的时候,发现没有该名称的事务或保存点,因为会引发这个异常,为什么会这样呢?大家看一下微软的解释:

  ROLLBACK TRANSACTION 语句的 transaction_name 参数引用一组命名嵌套事务的内部事务是非法的,transaction_name 只能引用最外部事务的事务名称。

  哦!原来Sql Server不允许我们在内部的事务中包含事务名称。那好,我们现在就把这个事务名称去掉,代码修改如下:

?
ALTER PROC [dbo].[Sp_UserMoneyLess]
@UserName NVARCHAR(50),     --用户名
@ChangeMoney DECIMAL (9,2),  --变动金额
@ChangeType INT ,            --账户变动类型
@Result INT OUTPUT ,         --输出参数,执行结果
@Msg NVARCHAR(100) OUTPUT   --执行结果描述
AS
--为输出参数设置默认值
SET @Result = 1 
SET @Msg = '执行成功'
DECLARE @before DECIMAL (9,2),@ after DECIMAL (9,2)
--开启事务
BEGIN TRAN
SELECT @before=tu.UserMoney FROM T_Users tu WHERE tu.UserName=@UserName
SET @ after =@before-@ChangeMoney
IF @ after <0
BEGIN
     SET @Result=-1
     SET @Msg = '账户余额不足'
     ROLLBACK TRAN
     RETURN
END
--更新会员账户余额
UPDATE T_Users SET UserMoney = @ after WHERE UserName = @UserName
IF @@ERROR<>0
BEGIN
     SET @Result = -2
     SET @Msg = '更新账户余额发生异常,异常信息:' + ERROR_MESSAGE()
     ROLLBACK TRAN
     RETURN
END
--产生账户变动记录
INSERT INTO T_MoneyLog
(
     UserName,
     ChangeType,
     MoneyBefore,
     ChangeMoney,
     MoneyAfter,
     Remark,
     AddTime
)
VALUES
(
     @UserName,
     @ChangeType,
     @before,
     @ChangeMoney,
     @ after ,
     '支付订单扣除账户余额' ,
     GETDATE()
)
IF @@ERROR<>0
BEGIN
     SET @Result = -3
     SET @Msg = '产生账户变动记录发生异常,异常信息:' + ERROR_MESSAGE()
     ROLLBACK TRAN
END
COMMIT TRAN

 再次执行测试代码:

?
DECLARE @Result INT ,@Msg NVARCHAR(200)
EXEC Sp_PayOrder '20130303160545612' , 'Geodon' ,@Result OUTPUT ,@Msg OUTPUT
SELECT @Result,@Msg

   

  从结果中我们发现除了上次的第二个错误之外,又产生了另外一个错误:

   

  为什么又出现了这个错误呢?从这个错误我们可以分析出错误的原因是在外部的事务中回滚事务的时候没有找到对应的Begin Tran,可我们的代码中明明有 Begin Tran PayOrder啊,为什么还会出现这个错误呢?在此我找到了微软的解释:

  如果在一组嵌套事务的任意级别执行使用外部事务名称的 ROLLBACK TRANSACTION transaction_name 语句,那么所有嵌套事务都将回滚。如果在一组嵌套事务的任意级别执行没有transaction_name 参数的 ROLLBACK WORK 或 ROLLBACK TRANSACTION 语句,那么所有嵌套事务都将回滚,包括最外部事务。

  原来内部的事务中如果执行了没有事务名称的回滚,会将所有的嵌套事务,包括最外层的事务都回滚。那怎么办呢?难道我们不能使用嵌套事务?你可以能会说:不可能啊,应该是可以的啊!呵呵,是的,我们当然可以使用嵌套事务。解决这个问题有两种方法:

  第一种:利用Commit Tran的原理,内部事务任何时候进行Commit tran,不管数据异常与否,如果出现异常数据,返回异常数据提示就可以。

  这种方法来源于微软的一段解释:

  SQL Server 数据库引擎将忽略内部事务的提交。根据最外部事务结束时采取的操作,将提交或者回滚内部事务。如果提交外部事务,也将提交内部嵌套事务。如果回滚外部事务,也将回滚所有内部事务,不管是否单独提交过内部事务。

  也就是说,最终的事务是否提交,决定权在外部的事务,即使内部事务进行了提交,只要外部事务根据内部返回的值来决定提交或者回滚,就可以把外部和所有嵌套的事务都提交或者回滚。

  好了,我们把代码修改如下:

?
ALTER PROC [dbo].[Sp_UserMoneyLess]
@UserName NVARCHAR(50),     --用户名
@ChangeMoney DECIMAL (9,2),  --变动金额
@ChangeType INT ,            --账户变动类型
@Result INT OUTPUT ,         --输出参数,执行结果
@Msg NVARCHAR(100) OUTPUT   --执行结果描述
AS
--为输出参数设置默认值
SET @Result = 1 
SET @Msg = '执行成功'
DECLARE @before DECIMAL (9,2),@ after DECIMAL (9,2)
--开启事务
BEGIN TRAN
SELECT @before=tu.UserMoney FROM T_Users tu WHERE tu.UserName=@UserName
SET @ after =@before-@ChangeMoney
IF @ after <0
BEGIN
     SET @Result=-1
     SET @Msg = '账户余额不足'
     COMMIT TRAN
     RETURN
END
--更新会员账户余额
UPDATE T_Users SET UserMoney = @ after WHERE UserName = @UserName
IF @@ERROR<>0
BEGIN
     SET @Result = -2
     SET @Msg = '更新账户余额发生异常,异常信息:' + ERROR_MESSAGE()
     COMMIT TRAN
     RETURN
END
--产生账户变动记录
INSERT INTO T_MoneyLog
(
     UserName,
     ChangeType,
     MoneyBefore,
     ChangeMoney,
     MoneyAfter,
     Remark,
     AddTime
)
VALUES
(
     @UserName,
     @ChangeType,
     @before,
     @ChangeMoney,
     @ after ,
     '支付订单扣除账户余额' ,
     GETDATE()
)
IF @@ERROR<>0
BEGIN
     SET @Result = -3
     SET @Msg = '产生账户变动记录发生异常,异常信息:' + ERROR_MESSAGE()
END
COMMIT TRAN

  然后我们再次执行订单支付的模拟:

?
DECLARE @Result INT ,@Msg NVARCHAR(200)
EXEC Sp_PayOrder '20130303160545612' , 'Geodon' ,@Result OUTPUT ,@Msg OUTPUT
SELECT @Result,@Msg

  运行结果

   

  Ok,出现了我们想要的结果。

  第二种,利用事务保存点来解决。

  该方法利用在内部嵌套中增加一个事务保存点(Save Tran savepoint_name),然后在内部嵌套中需要进行回滚的地方执行Rollback Tran savepoint_name这样,就可以把事务回滚到savepoint_name这个保存点,好了,了解了原理,我们修改代码如下:

?
ALTER PROC [dbo].[Sp_UserMoneyLess]
@UserName NVARCHAR(50),     --用户名
@ChangeMoney DECIMAL (9,2),  --变动金额
@ChangeType INT ,            --账户变动类型
@Result INT OUTPUT ,         --输出参数,执行结果
@Msg NVARCHAR(100) OUTPUT   --执行结果描述
AS
--为输出参数设置默认值
SET @Result = 1 
SET @Msg = '执行成功'
DECLARE @before DECIMAL (9,2),@ after DECIMAL (9,2)
--开启事务
SAVE TRAN UserMoneyLess
SELECT @before=tu.UserMoney FROM T_Users tu WHERE tu.UserName=@UserName
SET @ after =@before-@ChangeMoney
IF @ after <0
BEGIN
     SET @Result=-1
     SET @Msg = '账户余额不足'
     ROLLBACK TRAN UserMoneyLess
     RETURN
END
--更新会员账户余额
UPDATE T_Users SET UserMoney = @ after WHERE UserName = @UserName
IF @@ERROR<>0
BEGIN
     SET @Result = -2
     SET @Msg = '更新账户余额发生异常,异常信息:' + ERROR_MESSAGE()
     ROLLBACK TRAN UserMoneyLess
     RETURN
END
--产生账户变动记录
INSERT INTO T_MoneyLog
(
     UserName,
     ChangeType,
     MoneyBefore,
     ChangeMoney,
     MoneyAfter,
     Remark,
     AddTime
)
VALUES
(
     @UserName,
     @ChangeType,
     @before,
     @ChangeMoney,
     @ after ,
     '支付订单扣除账户余额' ,
     GETDATE()
)
IF @@ERROR<>0
BEGIN
     SET @Result = -3
     SET @Msg = '产生账户变动记录发生异常,异常信息:' + ERROR_MESSAGE()
     ROLLBACK TRAN UserMoneyLess
END

  大家可以看到我们在原来事务起始的地方,增加了一个事务保存点SAVE  TRAN UserMoneyLess,然后在下面回滚的地方,加上了保存点名称。

  再次执行测试代码:

?
DECLARE @Result INT ,@Msg NVARCHAR(200)
EXEC Sp_PayOrder '20130303160545612' , 'Geodon' ,@Result OUTPUT ,@Msg OUTPUT
SELECT @Result,@Msg

  结果:

   

  Ok,是我们想要的结果。

  上面两种方法解决了事务嵌套的问题。当然用上述的两种方法所创建的嵌套存储过程如果想要单独使用,必须在外层嵌套一层事务或者在业务层调用这种存储的时候,加上事务,各个ORM中都有事务的功能,如果你还在用DbHelper,也可以自己封装一个事务处理类,在业务逻辑层进行事务处理。

  本文转载自:http://www.hello-code.com

Spring 事务嵌套及传播行为:深入理解与最佳实践 事务嵌套是指在一个事务中调用其他带事务的方法。当我们在一个事务中调用另一个有事务控制的方法时,Spring 会根据方法上配置的事务传播行为来决定如何处理这些事务。这种嵌套事务的管理机制,实际上是通过事务的。 阅读详情

相关推荐

SqlServer嵌套事务机制了解

SQL Server 中的嵌套事务提供了一种将复杂事务逻辑分解为多个部分的方法,但它的实际行为并不如某些其他数据库那样独立管理每个事务,而是依赖于最外层事务的提交和回滚。正确地使用嵌套事务有助于简化事务管理和错误处理,但也需要注意其局限性,尤其是在回滚和提交的行为上。在 SQL Server 中,子事务回滚不会自动导致外层事务回滚。只有在外层事务中显式调用时,所有嵌套事务才会被回滚。子事务的回滚仅影响子事务内部的操作,而不影响外层事务的状态,除非外层事务遇到错误并选择回滚。

极客神殿 1358

【spring】spring 的事务(transaction) 四 嵌套事务PROPAGATION_NESTED

文章目录1. 什么是嵌套事务PROPAGATION_NESTED2. PROPAGATION_NESTED 与PROPAGATION_REQUIRES_NEW的区别2.1 验证PROPAGATION_REQUIRES_NEW内层事务执行完就立即提交2.2 验证PROPAGATION_NESTED 内层事务执行完未立即提交2.3 验证PROPAGATION_NESTED 内层事务回滚 相关文章 spring 的事务(transaction) 一 基础概念介绍 spring 的事务(transaction) 二

m0_45406092的博客 1万+

sqlite事务嵌套

sqlite本身的事务并不支持嵌套,而savepoint方法虽然支持嵌套,但是,使用起来比较复杂。下面,提供一种针对线程数据库连接的事务嵌套模式,如果是在单线程中操作数据库,则可以进一步简化实现 (采用静态变量保存事务计数即可)。     在代码中,使用了windows下的线程槽的概念,其是针对每个线程保留单独的一份数据。 #include "sqlite3.h" /** * @class

James的专栏 3113

Spring事务嵌套--七大场景

外部方法和内部方法业务的事务嵌套不同组合,导致出现的结果不同因素

weixin_50160384的博客 830

大事务拆分项目应用-再看事务嵌套

一、何为事务嵌套最简单的事务嵌套情况:开启了一个事务的情况下,再开启一个事务2。或者:在t1、t2分别为两个事务操作,而外层t3事务包含t1(t2),t3跟t1(t2)         OR          例如在支付系统中,在进行支付校验时,事务1负责更新账单状态&amp;插入历史表,事务2负责创建支付记录及明细,如果假设更新账单状态成功,二创建支付记录失败,则导致账单状态与支付状态丢失数据一...

Think In JAVA—Max 3352

Android SQLite 支持嵌套事务吗?

Android SQLite相关java源码中多次提到支持 nested transaction。 而SQLite本身不支持嵌套事务,只能使用 savepoint 代替。 https://www.sqlite.org/lang_savepoint.html 嵌套事务即是类似于 BEGIN BEGIN ...... 也许没有太多人会直接这样写,更多情况是,一个程序执行

E飞 5758

关于 Spring 中事务的嵌套,你了解多少?

5.1 事务方法访问修饰符不是public,导致事务失效比如下图中的代码其实如果是JDK的动态代理 就不允许这种情况,因为JDK动态代理需要有接口,而接口中是不能有 私有方法的,如果是CGLIB动态代理的话也是不允许的代理private方法的5.2 如果事务方法是static、final的,同样无法通过动态代理,事务也是不会生效的。Spring的声明式事务是基于动态代理实现的,我们无法重写final修饰的方法;

2301_77463738的博客 769

mysql嵌套事务的坑

表结构:CREATE TABLE `t1` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `c1` int(11) NOT NULL,  `c2` int(11) NOT NULL,  `c3` int(11) NOT NULL,  PRIMARY KEY (`id`),  KEY `c1` (`c1`)) ENGINE=InnoDB AUTO_INCREME...

laiyijian的博客 3378

Spring事务嵌套机制

Spring 事务机制回顾 Spring事务一个被讹传很广说法是:一个事务方法不应该调用另一个事务方法,否则将产生两个事务.结果造成开发人员在设计事务方法时束手束脚,生怕一不小心就踩到地雷。 其实这是不认识Spring事务传播机制而造成的误解,Spring对事务控制的支持统一在TransactionDefinition类中描述,该类有以下几个重要的接口方法: int ge...

sun82111的专栏 1万+

Spring 事务 - 基本使用、传播机制、失效场景、嵌套事务多回滚解决

带你一次学懂:编程式事务、声明式事务、事务的传播机制!

CYK_byte的博客 5335

mysql 事务嵌套

通过对mysql事务进行测试,还原了事务嵌套带来的后果,同时,引申出了利用savepoint来实现对事务进行部分提交的特性。

csdntestuser1的博客 4467

java 事务嵌套_Java事务以及嵌套事务

最近遇到事务的处理,嵌套事务,自己研究,整理一下。1 先看结论1、在Java事务中,事务的嵌套,如果有事务成功,那么则都成功,否则都不会成功。2、如果事务中存在异常,只要对异常进行捕获和处理,都为执行成功,否则都不会执行成功。2 Propagation取值REQUIRED(默认值):在有transaction状态下执行;如当前没有transaction,则创建新的transaction;SUPPO...

weixin_39633171的博客 3211

简单搭建 可视化日志+链路追踪

JAVA 可视化日志、链路追踪、plumeLog、Tlog、Logback

qq_39535439的博客 1204

Spring 中事务的嵌套详解

5.1 事务方法访问修饰符不是public,导致事务失效比如 下图中的代码其实如果是JDK的动态代理 就不允许这种情况,因为JDK动态代理需要有接口,而接口中是不能有 私有方法的,如果是CGLIB动态代理的话也是不允许的代理private方法的5.2 如果事务方法是static、final的,同样无法通过动态代理,事务也是不会生效的。Spring的声明式事务是基于动态代理实现的,我们无法重写final修饰的方法;

a984171281的博客 2544

NXP S32K3 Safety软件生态全解析:RTD、SPD、SAF、SCST到底怎么选?

本文深入解析NXP S32K3系列MCU的安全软件生态,详细对比RTD、SPD、SAF和SCST四大组件的功能定位与选型策略。针对不同ASIL等级需求,提供从架构设计到工程实践的完整解决方案,帮助开发者高效实现功能安全认证,优化汽车电子系统的安全性与可靠性。

weixin_42524226的博客 323

分数计算器(C++课设)

需求概述 (1)设计一个分数计算器,进行分数的算术运算和逻辑运算。 (2)能够像使用基本数据的对象一样,对分数进行“+”、“-”、“*”和“/”等算术运算和比较两个分数的大小。 (3)以a/b的形式输入输出分数,允许输入输出整数这种特殊形式。 (4)对不是约化型的分数进行约化,避免分母为负数。 (5)如果分数的分母为0、除数为0或输入时格式有错,采用异常处理机制解决。 输入 以分数的形式输入。(如1/2) 若分母为0会抛出异常,重新输入。 菜单页面 RationalNumber.h(头文件) #ifnd

sadnessss的博客 8769

Oracle 嵌套事务 VS 自治事务

一、概念 嵌套事务(Nested Transaction):指在主事务(MT)中嵌套的一个或多个子事务,并且子事务与主事务相互影响。 自治事务(Autonomous Transaction):由主事务调用但又独立于主事务,子事务对commit和rollback进行自治管理,不影响主事务执行效果。常用于写入LOG或TRACE信息便于查找错误。 二、嵌套事务 1.预备Create Table createtableTEST_POLICY ( POLICY_CODE...

Hehuyi_In的博客 2826

matinal:SAP 采购中形成的差异

如果库存足够会影响到物料。

matinal 當冬夜漸暖 。公众号:matinal 820

浅谈spring的嵌套事务

因为两个方法是一个事务,在方法B中报错了,抛出异常,用户和日志的数据库操作都将回滚。可以看到确实是两个事务,但两个事务都rollback了。这里的事务同步器是一个Arraylist,它的执行顺序即是arraylist的遍历顺序,仅仅只代表加入的先后,并不代表事务真正commit/rollback的顺序。同时,根据1,在嵌套事务中使用事务同步器要特别小心,在检查点的时候并不会执行同步器,同时会掩盖真正的操作。相当于在方法A的时候会开启一个新的事务,在调用方法B的时候,会在方法A之后方法B之前创建一个检查点。

Java技术攻略的博客 2173

【CIC-IDS数据集+机器学习】实现网络流量异常检测

本项目基于CIC-IDS数据集,使用多种机器学习算法实现网络流量异常检测系统。项目采用了完整的机器学习工作流程,从数据预处理到模型部署,实现了高精度的网络入侵检测。

XiaoMu_001的博客 1935

华为云HCS解决方案笔记HUAWEI CLOUD Stack【面试篇】

华为云解决方案介绍、华为云服务介绍,华为云网络平面规划等

weixin_48375618的博客 1万+

Spring事务的嵌套

事务嵌套

zuokaopuqingnian的博客 1468

Bert+CNN文本分类(含代码实现)

一、什么是CNN? CNN的特点: (1)特定特征位移不变性 (2)特征缩放不变性 2. CNN模型构造过程 2.1 Convolution(卷积) (1)获取关键特征(减少参数) (2)共享权重(再次减少参数) 2.2 Max Pooling(池化) 2.3 Flatten 向量转换为如图所示可以进入全连接层的向量模式 3. TextCNN 上图可理解为: 通过不同的size(如上图2、3、4等),上图红色代表 size=2,黄色...

Python,数据分析,机器学习,深度学习 1万+

mysql嵌套事务

drop table t; create table t(a int, primary key(a)); begin; insert into t(a) values(1); SAVEPOINT s; insert into t(a) values(2); ROLLBACK to SAVEPOINT s; commit; 表中只有1个元素,值是1 drop table t; create tab...

mingwulipo的博客 6213

基于C++和Qt开发IEC104规约主站调试软件(第二章)

本章节主要讲解iec104主站软件界面设计和从站的连接功能以及部分功能代码的展示。

半青年的博客 860

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

上一篇: SQL Server高级内容之子查询和表链接
下一篇: C#中方法的参数四种类型(值参数、ref、out、params)详解
普通网友
博客等级 码龄14年 0粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值