網絡上查了一下,很多人發現activiti的id在不同情況下會造成id生成會重複。
上代碼,先看看生成規則
引擎配置實現
ProcessEngineConfigurationImpl.initIdGenerator
// id generator
// /////////////////////////////////////////////////////////////
public void initIdGenerator() {
if (idGenerator == null) {
CommandExecutor idGeneratorCommandExecutor = null;
if (idGeneratorDataSource != null) {
ProcessEngineConfigurationImpl processEngineConfiguration = new StandaloneProcessEngineConfiguration();
processEngineConfiguration.setDataSource(idGeneratorDataSource);
processEngineConfiguration.setDatabaseSchemaUpdate(DB_SCHEMA_UPDATE_FALSE);
processEngineConfiguration.init();
idGeneratorCommandExecutor = processEngineConfiguration.getCommandExecutor();
} else if (idGeneratorDataSourceJndiName != null) {
ProcessEngineConfigurationImpl processEngineConfiguration = new StandaloneProcessEngineConfiguration();
processEngineConfiguration.setDataSourceJndiName(idGeneratorDataSourceJndiName);
processEngineConfiguration.setDatabaseSchemaUpdate(DB_SCHEMA_UPDATE_FALSE);
processEngineConfiguration.init();
idGeneratorCommandExecutor = processEngineConfiguration.getCommandExecutor();
} else {
idGeneratorCommandExecutor = getCommandExecutor();
}
DbIdGenerator dbIdGenerator = new DbIdGenerator();
dbIdGenerator.setIdBlockSize(idBlockSize);
dbIdGenerator.setCommandExecutor(idGeneratorCommandExecutor);
dbIdGenerator.setCommandConfig(getDefaultCommandConfig().transactionRequiresNew());
idGenerator = dbIdGenerator;
}
}
入口在
DbIdGenerator dbIdGenerator = new DbIdGenerator();
dbIdGenerator.setIdBlockSize(idBlockSize);
這段代碼,採用DbIdGenerator的方式
再看源碼
public class DbIdGenerator implements IdGenerator {
protected int idBlockSize;
protected long nextId;
protected long lastId = -1;
protected CommandExecutor commandExecutor;
protected CommandConfig commandConfig;
public synchronized String getNextId() {
if (lastId < nextId) {
getNewBlock();
}
long _nextId = nextId++;
return Long.toString(_nextId);
}
protected synchronized void getNewBlock() {
IdBlock idBlock = commandExecutor.execute(commandConfig, new GetNextIdBlockCmd(idBlockSize));
this.nextId = idBlock.getNextId();
this.lastId = idBlock.getLastId();
}
public int getIdBlockSize() {
return idBlockSize;
}
public void setIdBlockSize(int idBlockSize) {
this.idBlockSize = idBlockSize;
}
public CommandExecutor getCommandExecutor() {
return commandExecutor;
}
public void setCommandExecutor(CommandExecutor commandExecutor) {
this.commandExecutor = commandExecutor;
}
public CommandConfig getCommandConfig() {
return commandConfig;
}
public void setCommandConfig(CommandConfig commandConfig) {
this.commandConfig = commandConfig;
}
}
getNextId()這裏是每個業務記錄生成id的方法
再看GetNextIdBlockCmd(idBlockSize)
public class GetNextIdBlockCmd implements Command<IdBlock> {
private static final long serialVersionUID = 1L;
protected int idBlockSize;
public GetNextIdBlockCmd(int idBlockSize) {
this.idBlockSize = idBlockSize;
}
public IdBlock execute(CommandContext commandContext) {
PropertyEntity property = (PropertyEntity) commandContext.getPropertyEntityManager().findById("next.dbid");
long oldValue = Long.parseLong(property.getValue());
long newValue = oldValue + idBlockSize;
property.setValue(Long.toString(newValue));
return new IdBlock(oldValue, newValue - 1);
}
}
每次從數據庫中act_ge_property取出next.dbid計算出block的區間【min,max】
每個業務在獲取id的時候通過getNextId 從當前ID值+1,id從區間的最小值開始;
那麼ID爲什麼會重複呢,就是在idBlockSize這裏,這個值是在代碼中固化的2500,當流程中元素過多的時候會造成生成的id數量大於2500,就會造成id重複了,解決方案就是替換成uuid的生成方式,activiti已提供支持;
idBlockSize固化代碼
public abstract class ProcessEngineConfiguration {
/**
* Checks the version of the DB schema against the library when the process engine is being created and throws an exception if the versions don't match.
*/
public static final String DB_SCHEMA_UPDATE_FALSE = "false";
/**
* Creates the schema when the process engine is being created and drops the schema when the process engine is being closed.
*/
public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop";
/**
* Upon building of the process engine, a check is performed and an update of the schema is performed if it is necessary.
*/
public static final String DB_SCHEMA_UPDATE_TRUE = "true";
/** The tenant id indicating 'no tenant' */
public static final String NO_TENANT_ID = "";
protected String processEngineName = ProcessEngines.NAME_DEFAULT;
protected int idBlockSize = 2500;
protected String history = HistoryLevel.AUDIT.getKey();
protected boolean asyncExecutorActivate;
以下是next.dbid 以40001 做爲基數進行測試的id增長順序
act_re_deployment 40001
act_ge_bytearray 40002 40003
act_re_procdef 40004
act_hi_identitylink 40005 40006 40009 40015 40016
act_hi_procinst 40007 40008
act_hi_actinst 40010 40013
act_hi_varinst 40011 40012
act_ru_task 40014