00:00
接着前面的逻辑,接下来我们来编写库存的锁定功能,只要我们这个订单保存成功,我们就应该为此订单锁定库存,防止我们这个订单支付成功以后我们还没有库存,那么这个锁定功能呢,们在远程的这个仓库服务,我们这道y SQ ctrler在这呢,们有这个锁定库存的方法,点进来来实现一下我们的锁定库存,那么先来看一个锁定库存的简单逻辑,简单逻辑呢是这样。我们来要锁定库存,诶增强版的逻辑我们来先盖住,我们把这块忽略了,那想要锁定库存呢?那么接下来所有我们想要的买的商品,123,那么都要去锁库存,所以呢,每一个商品都要尝试锁库存,只有我们所有的商品全部锁定成功,那么整个库存呢才算锁定成功,那么就算是锁定成功了,你就可以返回,如果有一个商品锁定库存失败,它的库存不足,那么整个订单呢都算失败,那么这一块呢就要全部回滚,而且我们呢用事物自制,也就是说我们的扫库存方法是一个本身就是一个事物,有一个失败,我们可以抛一个异常,让以前锁了的人全部借回滚出去,所以我们现在来看我们的所库存方法能先用一个最简单的,那我们以前呢,应该所库存是这样子的。
01:17
我们以前下订单,我们要为此订单所库存,我们的所有库存我们都存在了,这张表叫WMSVSQ,这张表里边呢,保存了每一个商品在哪个仓库存了多少件,当前锁定了多少件,那这两个意见,那就是还剩多少件能买,那现在呢。由于我们一个商品可能在很多仓库都有库存,包括呢,一个仓库会拥有很多商品的库存,所以我们在这儿要锁库存的话,我们可以先来尝试,比如我们下了一个订单本呢,我们应该按照我们这个下的单的收货地址本应该按照下单的收货地址。然后呢,我们找到一个就近仓库,找到一个就近仓库,这个就近仓库,然后呢,我们来给它锁定库存,锁定库存,但是我们现在呢,就不做这么复杂的逻辑了,我现在就用最简单的,我们现在只要我们想要锁这些商品的库存,我们就看哪个仓库有这个库存来挨个锁,看谁能锁成功,我们就用谁的,所以我们现在呢要做的第一件事情,我们先来找到每个商品,每个商品在哪个仓库都有库存,都有库存好,我们现在呢就想来完成这个事情,我们现在想要所库存的商品有这么多,来get一个有一个locks,这是我们将要锁的所有商品,每一个商品呢,有这个商品ID,我们先要按照他查查我们在哪有库存,好我们现在来写一个locks,点一个stream,我们就来查,来写一个map map呢把当前商品来拿来,然后我们。
02:59
最终返回一个什么,我们先放到这们,现在呢,准备返回这么一个数据,我们先来return一个,那我们当前要锁的商品是这个样子,我们艾em,这是我们想要锁的商品,Get一个SQID,那我们先来找一下这个商品在哪里都有库存,然后呢,最终找到每一个商品都在哪有库存,那这个呢,我们可以来写一个内部类来封装我们的这个数据,这个class我们就叫SKU。
03:30
Hasto,我们这个仓库拥有库存的这个数据,那这个数据呢,我们就封装两个属性,第一个我们当前商品的ID,然后第二个我们都在哪些仓库有库存,我们来写一个list类型的浪。好,我们list类型,这是一个long类型,Long类型呢,保存我们这个仓库的ID,那这样我们把这个get set方法我们也来加上,然后我们来写这个数据,那最终呢,就想要返回我们这个类型的数据,你有一个SQ where handsto。
04:08
只要我们来找到每一个仓库都有哪些商品的库存,也就是说这个商品在哪些仓库有库存,我们点一个collect,我来涂一个list,把它们收集出来,然后呢,我们就挨个商品来扣库存,好,那现在呢,商品我们找到了,接下来我们就要找这个商品在哪里都有库存,那先来点一个sto,点一个set SQ ID,这是我们当前的SQID,然后呢,我们要查询这个商品,这个商品在哪里有库存,那这个怎么查询呢?非常简单,来调用我们库存的这个service,就是我们这个VRSQ,这个do,那就是它,我们直接用它,直接用它呢来写一个方法,这个do。我们希望呢,能查出一些数据,而且我们只要我们仓库的ID,所以我们来写一个select,我们叫where ID,我们来选择仓库的ID,因为呢可能有很多,那么就来写一个方法叫list,来列出所有仓库的ID,然后呢,谁has SQ stock,由我们指定SQ的库存stock,好,我们指定的SQ是谁呢?那就是这个SQ,我希望他给我们返回一个list类型的所有仓库的ID就行了。好,我们来写一个浪。
05:30
我们就叫VID,好,这是我们希望会拥有这么一个方法,好那我们把这个方法呢,我们创建出来走来创建出这个方法,我们也创建出它的实现们给ma配置文件中,我们创建出这个statement,这是一个集合查询,那么来查这个库存,这个怎么查。来,比如我们在这儿来写一个例子,那现在想查二号这个商品来,或者是一号这个商品都在哪个仓库里边有库存,然后呢,我们就按照这个仓库直接来扣就行了,那么怎么查呢?你就来写一个select,那么不行,因为我们只要仓库的ID,我们就仓库ID,然后from from哪张表呢,就是这张库存表,然后呢,Where where,条件就是我们当前的这个商品得有库存,Where SKU ID得等于我们当前的商品不是一号,并且呢,它得有库存,有库存呢就是我们sto减去锁定的这个大于零就行了,说TOTO减我们to lock大于零。
06:41
这是我们来写的这个查询方法,我们来运行一下走,好我们发现呢,现在我们要查的这个一号商品只是在二号仓库有库存,那实际上我们来看一下走,那确实一号商品呢,二号仓库它有足够的库存,在我们这个七号,不是七号仓库,在这个一号仓库是第七条记录,它呢只有我们一个库存,而且这个库存还被我们之前锁定了,所以这就是我们的这个方法,把这个方法ctrl a ctrl c来找到,好现在呢,我们把这个circleq语句来粘贴到这,这是我们来找所有的仓库ID,那么现在找到了这些仓库以后,好,我们来运行回来,只不过我们这一块商品的ID应该等于井号,达克号,我们传过来的这个商品ID,好,我们给它让它命名上一个参数SQID,我们直接用P封装好,现在呢,就是SQID在这来写也有提示。
07:38
我们查这个商品在哪个仓库都有库存,那找到以后,然后来到我们这一块的调用,那service,现在我们就找到了我们这个商品哪些仓库都有库存,把它呢保存起来,Stock点一个set,我们的where ID,这是我们能有库存的这些仓库,那接下来们找到了这些仓库,第二个接下来就来锁定库存,那这个库存怎么锁定呢?我们这是所有商品都在哪个仓库有库存,我们应该便利它,点一个for each们使用增强for便利,现在呢,我们先来便利到我们的这些商品,这些商品呢,我们来点一个get SQ ID,现在我们知道是这个商品都在哪些仓库有库存,在这里边呢,还有一个get where ID都在这些仓库有库存,所以接下来我们就得扣,从这些仓仓库里边挨个扣,哪个扣成功了,那直接跳出扣。
08:38
大一个SQ,所以我们继续来for,写一个for循环,我们这个for循环呢,现在来遍历的是我们的VSQID,我们这个VID,然后呢,它便利出我们的long类型的仓库ID,我们就叫VID来我们这个叫v ids比较合适,好现在我们来便利每一个仓库,当然在便利之前,如果if,如果说我们这个商品拥有库存的这个仓库都是空的,如果它等等,那。
09:09
或者说我们这个仓库的ids点一个size等等零,也就说我们没有仓库有库存,没有任何仓库,有这个商品的库存,那么也就没必要再扣其他商品了,相当于这个商品都没有,你把其他商品扣了,你还得折回去,因为整个订单都失败了,所以我们为了模拟快速失败,我们给他抛一个异常,我们有一个叫库存不足的异常,那这个异常呢,我们就直接来写到我们自己的这个方法里边来写一个包,就叫异常exception,好,我们这个exception呢,就叫noto exception我们没有。这个库存的异常好,那现在呢,让他来继承运行时异常runtime exception。
10:00
然后接下来来写上它的构造器public the noto exception来他给我们的这个异常提示来super,那整个提示呢,就是没有足够的。足够的库存吧,哪个商品没有足够的库存了?当然我们也可以封装一下这个商品的IDSKUID,那么在构造的时候呢,你必须给我传一个SQID,让我得知道是这个商品没有库存了,所以我们在这就来提示是它没有足够的商库存了,我们就叫商品。ID是这个的人没有足够的库存了啊。ID它没有足够的库存了,然后呢,接下来我们当然这个商品ID我们来get set方法们也可以来写上set的这个方法啊,那么现在呢,有我们这么一个异常,只要没有库存了,我们就来抛出这个异常,Noto,没有库存的这个异常,当然没库存的异常我们必须传入SKU的ID是哪个SQ没库存了,那就是它我们正在便利的它他呢没有一个仓库,有它库存我们直接跑异常,我们所有的for也不做了,那么这一块呢,也都不做了,有任何人有问题抛异常,那接下来来到这,如果没有问题,我就挨个仓库来进行扣减crl all代码整理一下们来扣减每一个仓库,那么希望呢,就有一个扣库存的方法,V sqdao点一个我们就叫lock,我们的SQ锁定我们这个SQ的库存,那这个锁定库存我们就得知道你要锁哪个SQ,你给我传一个squ的ID,当。
11:45
你是要锁哪个仓库的,我们现在要锁这个仓库的,我们要锁几件,相当于我们要买几个商品,我们也得知道我们在这儿封装的时候啊,当前这个SK到底有没哪些仓库,有库存,包括呢?那要锁多少件,我们最好呢,在这也一封装,那这样我们来到这一块,我们查询当前商品,在这一块呢,有库存是这个商品,包括他要锁几件,Set一个number,我们也准备好要锁几件呢?那都是从这里边获取出来的,那当时SK买几件我们就锁几件,好现在来到这儿,我们的这个汉字to,我们就知道是这个商品,这个商品现在要锁几件,那就在这儿点一个get number,我们希望呢,有这么一个方法给我们返回锁库存,当然库存锁定的SQL语句应该是这样子的。
12:36
假设呢,我们现在来找到了我们的二号商品,二号商品在我们二号仓库有库存,我们库存锁定的这一块就不应该默认是,那我们来修改一下数据库,来改变掉,我们让所有的这个锁定了的库存,我们给它默认值是一个零,那这样即使我们新插入的记录进来,那么的这些默认值都是零,来打开我们把这一块的那来给它改掉,现在呢,大家进来呢都是零,以后插入的记录这一块呢,都是零,那现在假设我们的这个二号商品在二号仓库,我们现在呢,有库存们正在尝试二号仓库,我要锁,那就应该是正锁,应该是一个更新操作,Update,因为我们相当于要把它的数量往上加,所以呢,Update我们这张表,然后set set,我们要锁定的这个数量等于什么呢?等于它加上,我们现在想要买两件,那就它加上二,所以呢,它是一个自加的过程。
13:36
然后接下来well条件是什么?条件呢?就是我们指定的这个SQID,因为我们现在要锁这个商品SQID,比如我们现在要锁二号商品,并且呢,我们是来锁二号仓库的,锁where杠一杠ID等于啊那这样呢,这是我们的SQL语句来走运行好,只要运行成功,我们就会返回一行受影响,但是呢,我们这个条件还不完全,因为我们现在如果运行成功,我们在这一块呢就加量了,那加到什么时候为止,我们现在呢,想要锁库存给它加上去,但最终的条件应该是这样,并且,并且就是说我们的这个库存量sto减去我们现在呢锁定的这个量,因为这个where条件优先,那么这个量呢,减去这个量必须大于,大于几呢?如果我们是大于零,那就是我们永远锁定的量不能大于这个库存量。那我们来看一下能锁。
14:36
几次走,我们这又锁了一次,影响成功,我来刷新增到四条,然后呢,我们走又锁一次,来刷新,我们增到六条,我们再来锁一次,走我们现在来刷新,我们增大八条,我们再来锁一次。走,那现在来刷新,那现在增到十条,能不能再来锁一次呢?走。发现呢,这一块零行受影响,我们就不能再锁了,但是我们这个大于零其实是有问题的,如果正好能锁住等于零也行,那如果我们写了一个等于零条件,我们能锁不能锁走,好我们发现呢,一行数成功走,我们居然锁到了12个,所以我们这一块呢,到底应该大于等于几,应该是大于等于二,我现在想买两个商品,你目前锁定的这个数量和你的这个数量两个一减要大于我想要购买的数量,那我能才能购买,所以我们这一块把它重新改回来,那我们想要锁库存呢,就应该是这条锁扣,我们把这条色扣复制过来,好我们来到这儿,我们希望呢,这个方法能锁库存,因为这个方法呢,最终返回了是影响多少行,那么就来写一个浪,那么影响多少行,我们有一个记录数,而且怎么样就锁定成功了,就是我们影响的这个行数,我们会发现我们一直在锁,假设呢,我们现在已经锁了九条了,我们已经锁了九个记录了。我再想要买两件,我。
15:58
来运行,我们发现呢,银行受影响相当于没锁成功,但是呢,如果我们买一个,我们现在呢就买一个,那么买一个的话呢,我们来运行,我们发现呢,它是一行受影响,那就是运行成功,所以呢,我们最终其实是根据那这一个circle运行成功是几行受影响,我们来判断它是锁成功了还是没锁成功,我们这个成功成功就返回一否则,否则是零,我们这个记录没被更新,那就是零,否则就是零,所以我们希望有这么一个所库存的方法,把这个方法呢创建出来,创建到我们这个do里边,好,接下来我们要为这些方法先创建上我们这个power,为每一个属性呢标上这个and power,那再来创建上它的statement,走,我们创建出一个statement,这个statement呢,是一个更新操作好,我们在这呢就创建好了一个更新。
16:54
叫look s puto,好,那这个更新操作呢,它的锁口语句我们拿过来,Ctrl a ctrl c,我们复制到这,然后呢,我们把所有的其他东西我们来填充过来,我们这个数量要加几个,那要加的呢,应该是井号大括号,我们当前想要购买的数量,然后呢,是哪个商品,那就应该是井号大括号,是我们当前这个商品在哪个仓库所在,这个井号大括号我们指定的这个仓储库锁,包括呢,我们这个减去的数量应该大于等于几,那应该是这样,井号大括号大于等于我们想要购买的数量,这样呢才行,这是我们锁库存的方法,好,锁库存的方法呢,我们就在这儿写好了,来到service,所以我们在这儿来判断if,如果countt count。
17:45
然后呢,等等零等等零,说明我们所失败了,那所失败我们就应该继续重试下一个仓库,所以呢,当前仓库,当前仓库锁失败所失败,那重试重试下一个仓库,如果等等一说明我们这个呢就锁成功了,Else,这就是失败,然后接下来就是成功,而且这个成功失败我们必须来感知的,那现在要锁所有商品的库存,好,我们写下来一个全局的标志量,我们就叫布尔,我们就叫o lock全部是不是都锁定了呢?我们来默认是一个fo法。
18:27
我们可以默认是一个处,只要有一个没被锁定,我们就会出现问题,所以呢,我们要锁哪个,这个呢是我们要锁的商品,我们要锁的这个商品呢,我们给它里边也给一个标志位,比如呢skuto,好,我们默认呢等于true,相当于呢它被锁住了,我们应该是默认等于force,默认呢它没被锁住,然后呢,接下来我们就尝试每一个仓库来进行锁,我们在下边来进行锁的时候,那就应该是这样,如果等等一说明锁住了,锁住了呢,我们当前这个SQ stock,那就是等等处就等于处,那相当于把它就锁住了,而且呢,我们这一块如果它锁成功了,就没有有必要再来试其他仓库了,所以我来写一个break break呢我们这个for循环就跳出了,那这个一跳出,相当于我们当前的这个SQ,我们就锁完了,然后我们来锁下一个SQ。而如。
19:28
如果说我们整个for循环执行完了,我们都没有锁住,因为只要呢,锁住了我们这一块呢,就是处,我们这儿呢就跳出了,跳出以后呢,执行下边的代码,但如果我们一直没锁住,没有人把它置为处,那们所有的仓库都尝试完了,都没有人锁住,没有人锁住呢,那它就是一个false,它一是force,那就代表那当前商品没锁住,那当前商品没锁住,那其他商品也就不用锁了,和我们在这儿来判断一下,如果我们这个当前商品等等force等等false,那就是我们这个当前商品没锁住,当前商品所有仓库都没锁住,所有仓库都没有锁住,那都没有锁住怎么办呢?那接下来就可以直接给他抛异常,告诉你当前这个商品呢,没库存了,那其他的商品呢,也不用往下锁了,那只要我们整个for循环运行完成,期间没有抛硬任何异常,那我们整个肯定都。
20:28
不是全部所成功的,所以呢,能走到下一行,能走到这儿,那能走到这儿我们就是肯定全部都是锁定成功的,那只要这一块呢,锁定成功,我们就给他返回全局这个锁定成功,那锁定失败,你要成都成,要败呢都败,所以呢,我们现在只要我们能走到这儿,我们就给他return一个处,只要我们不return处,那肯定就是失败的,所以我们整个锁库存呢,我就不返回这个list了,那最终就给它返一个锁定成功还是失败的这个结果,来返一个布,那么同样的把接口我们来也修改一下SQ的这个service这个接口,那锁库存成功还是失败,那在这order lookto在这来锁返回一个布尔,那这个布尔呢,那就代表们锁成功还是失败了,只要失败,我们肯定是抛异常的失败,而且一抛一常。假如前边两个都锁成功了,后一。
21:28
一个失败了,那前面还会跟着回滚,所以我们为了让它回滚来抛一个transition,好,我们来说这是一个transition,而且呢,我来明显指定action有一个属性叫roll bank for,就是呢,我们什么一定要回滚,哪个东西回滚呢?我们只要没有库存,No stock exception,我们都要进行回滚,所以呢,它点一个class,这个呢是一定要回滚的,其实我们如果默认不标,它也是回滚的,因为默认只要是运行时异常都会回滚,默认只要是运行时异常都会回滚。
22:04
好,那现在呢,我们这个锁库存的方法,我们就做完了,来看一下谁掉,那我们的这一块呢,就来调了锁库存的方法。好,那么最终调完锁库存的方法返回的是一个true false,那么就直接给它放true false代表是锁成了还是锁败了,所以我们在这就来判断一下,我们来写一个sto,如果我们来是所成功的,这块是所成功的,我们就来给它返回ROK,那就一切成功r.OK我们是一切成功的,如果是失败了,Else,因为我们这一块呢,所失败就是我们这一块抛出了异常,所以我们可以把它TRY看一下,来执行我们的业务代码。业务代码呢,有可能会给我们抛出异常,只要抛出了我们这个异常,而且我们这个异常呢,一定是no stock。Exception没有库存的这个异常,那一切正常,我们就应该是这样,我return能返回到这肯定都是处们就返回,OK,那如果有异常你就给他返回失败,而且告诉他是哪个商品库存呢,有问题了,R点一个,我们可以来写一个file a我们这个失败呢,就来给一个失败的状态码,那这个状态码我们以前的业务状态码我们也写了很多,有一个叫来看一下叫杯斯扣的枚举,这个枚举呢我们来看,假设我们的库存服务是。
23:33
21 21呢是我们这个库存,然后呢,我们就会给他返回一个异常,我就叫no stock stock exception没有库存的异常,然后呢,我们的这一块码来写上,我们是二一。000,那现在呢,三个码000,那就是没有库存,商品库存,不足商品库存库存,那么接下来我们就来给它返回,如果有异常杯子code枚举,点一个noto,没有库存的异常状态码呢,就是这个,然后我们要用的异常信息就是base code,点一个no stock,点一个get message,这就是没有库存的信息。
24:21
我们把这一块呢,就返回过去。这是我们编写的所库存方法,那下节课我们就可以对这个方法呢进行一个调试。
我来说两句