Activiti5.22 ID到底是怎麼生成的,每次都不一樣,會不會有什麼問題?

網絡上查了一下,很多人發現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 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章