下一篇:工作流Activiti異常積累
在Spring學習之整合Activiti(一)的測試環(huán)節(jié)進入modeler.html創(chuàng)建模型頁面時需要傳modelId,那么這些Id是如何生成的(Activiti中的所有的id:act_ge_bytearray、act_re_deployment等等中的主鍵生成基本一致)?
在本章節(jié),我們跟著源碼查看一下:
一、ModelService.createModel方法
進新建模型頁面首先調(diào)用ModelService(示例中的類)中的createModel()方法獲取modelId:

如上在兩處打印
modelData.getId(),很容易得知,modelId是在repositoryService.saveModel(modelData)中生成的
二、RepositoryServiceImpl.saveModel方法
我們進入repositoryService.saveModel方法:

該方法實際調(diào)用的是SaveModelCmd類中的execute方法
三、SaveModelCmd.execute方法
我們進入SaveModelCmd類:

新建模型時,model.getId()是為null的,所以這里調(diào)用的是:
commandContext.getModelEntityManager().insertModel(model);
四、ModelEntityManager.insertModel方法
ModelEntityManager的insertModel方法代碼如下:

五、DbSqlSession.insert方法
繼續(xù)進入DbSqlSession.insert方法查看:

dbSqlSessionFactory.getIdGenerator().getNextId()調(diào)用的是DbIdGenerator中的getNextId方法
六、DbIdGenerator.getNextId方法

可以看到,modelId生成邏輯主要在該類中,
在getNextId方法中,判斷lastId是否小于nextId,而這個條件中的lastId和nextId只是一個成員變量,在DbIdGenerator實例銷毀后,lastId和nextId就會被重置,說明重啟服務(wù)后lastId和nextId就會被重置,
會執(zhí)行getNewBlock方法重新生成lastId和nextId,最后返回nextId;
在getNewBlock方法,我們看看第一句IdBlock是怎么生成的,調(diào)用GetNextIdBlockCmd類的execute方法
七、GetNextIdBlockCmd.execute方法
進入GetNextIdBlockCmd類:

該execute方法中:
首先獲取act_ge_property表中的next.dbid字段的值,傳給oldValue;
idBlockSize:為2500,然后通過oldValue和newValue-1生成IdBlock
八、IdBlock類

九、遇到的坑
以上生成id的邏輯,在不手動操作數(shù)據(jù)庫是沒有問題,比如,所有的流程模型都是在網(wǎng)頁上新建的,但是如果某些模型數(shù)據(jù)是直接操作數(shù)據(jù)庫,插入時會報主鍵重復(fù):
場景:
在測試環(huán)境的網(wǎng)頁上新建模型,并導(dǎo)出該模型的數(shù)據(jù)記錄,然后導(dǎo)入到生產(chǎn)環(huán)境的數(shù)據(jù)庫中,這里可能出現(xiàn)的情況是:
生產(chǎn)服務(wù)啟動服務(wù)后會部署流程模型,而此時部署id是act_ge_property表中的next.dbid字段的值;而部署后也會往act_ge_bytearray表插入數(shù)據(jù),從上面的源碼可以看出:act_ge_bytearray表中的id是act_ge_property表中的next.dbid字段的值nextId+1
而由于測試環(huán)境的modelid也有可能是act_ge_property表中的next.dbid字段的值(啟動服務(wù)后直接新建模型),新建模型時會將模型的xml文件插入到act_ge_bytearray表,此時act_ge_bytearray表中的該模型的id是act_ge_property表中的next.dbid字段的值nextId+1,如此便與生產(chǎn)服務(wù)的部署id沖突!
針對上述問題,我們模擬一下:準備一張表:init_activities_20190321.sql (生產(chǎn)上的sql)
9.1、模擬生產(chǎn)環(huán)境
首先我們模擬生產(chǎn)環(huán)境:
我們往數(shù)據(jù)庫中導(dǎo)入init_activities_20190321.sql
隨便部署一個模型,調(diào)用deploy方法,數(shù)據(jù)變化結(jié)果如下:
頁面效果:

數(shù)據(jù)庫變化:

9.1、模擬測試環(huán)境新增模型
然后模擬測試環(huán)境:往數(shù)據(jù)庫中導(dǎo)入init_activities_20190321.sql三張表的結(jié)果如下:

然后啟動服務(wù),新增兩條模型,數(shù)據(jù)庫變化如下:

可以看到,測試環(huán)境的act_ge_bytearray中新增的模型中有兩條數(shù)據(jù)的id與生產(chǎn)環(huán)境的act_ge_bytearray中的兩個數(shù)據(jù)的id一致,這樣的,如果將測試環(huán)境該三個表中的新增的模型數(shù)據(jù)導(dǎo)出來,命名為update_activities_20190517.sql;在生產(chǎn)環(huán)境運行,就會報主鍵沖突。
解決方案可查看工作流Activiti異常積累 異常4部分
下一篇:工作流Activiti異常積累