网络上查了一下,很多人发现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