@Override
    public Model add(Class<?> aClass, int scopeId, Storage storage) throws StorageException {
        // Check this scope id is valid.
        DefaultScopeDefine.nameOf(scopeId);

        List<ModelColumn> modelColumns = new ArrayList<>();
        SeriesIDChecker seriesIDChecker = new SeriesIDChecker();
        ShardingKeyChecker shardingKeyChecker = new ShardingKeyChecker();
        SQLDatabaseModelExtension sqlDBModelExtension = new SQLDatabaseModelExtension();
        BanyanDBModelExtension banyanDBModelExtension = new BanyanDBModelExtension();
        ElasticSearchModelExtension elasticSearchModelExtension = new ElasticSearchModelExtension();
        retrieval(
            aClass, storage.getModelName(), modelColumns, scopeId, seriesIDChecker, shardingKeyChecker, sqlDBModelExtension,
            banyanDBModelExtension
        );
        // Add extra column for additional entities
        if (aClass.isAnnotationPresent(SQLDatabase.ExtraColumn4AdditionalEntity.class)
            || aClass.isAnnotationPresent(SQLDatabase.MultipleExtraColumn4AdditionalEntity.class)) {
            Map<String/*parent column*/, List<String>/*tables*/> extraColumns = new HashMap<>();
            if (aClass.isAnnotationPresent(SQLDatabase.MultipleExtraColumn4AdditionalEntity.class)) {
                for (SQLDatabase.ExtraColumn4AdditionalEntity extraColumn : aClass.getAnnotation(
                    SQLDatabase.MultipleExtraColumn4AdditionalEntity.class).value()) {
                    List<String> tables = extraColumns.computeIfAbsent(
                        extraColumn.parentColumn(), v -> new ArrayList<>());
                    tables.add(extraColumn.additionalTable());
                }
            } else {
                SQLDatabase.ExtraColumn4AdditionalEntity extraColumn = aClass.getAnnotation(
                    SQLDatabase.ExtraColumn4AdditionalEntity.class);
                List<String> tables = extraColumns.computeIfAbsent(extraColumn.parentColumn(), v -> new ArrayList<>());
                tables.add(extraColumn.additionalTable());
            }

            extraColumns.forEach((extraColumn, tables) -> {
                if (!addExtraColumn4AdditionalEntity(sqlDBModelExtension, modelColumns, extraColumn, tables)) {
                    throw new IllegalStateException(
                        "Model [" + storage.getModelName() + "] defined an extra column  [" + extraColumn + "]  by @SQLDatabase.ExtraColumn4AdditionalEntity, " +
                            "but couldn't be found from the parent.");
                }
            });
        }
        //Add timestampColumn for BanyanDB
        if (aClass.isAnnotationPresent(BanyanDB.TimestampColumn.class)) {
            String timestampColumn = aClass.getAnnotation(BanyanDB.TimestampColumn.class).value();
            banyanDBModelExtension.setTimestampColumn(timestampColumn);
        }

        if (aClass.isAnnotationPresent(BanyanDB.StoreIDAsTag.class)) {
            banyanDBModelExtension.setStoreIDTag(true);
        }

        if (aClass.isAnnotationPresent(BanyanDB.IndexMode.class)) {
            banyanDBModelExtension.setIndexMode(true);
        }

        if (aClass.isAnnotationPresent(BanyanDB.Group.class)) {
            BanyanDB.StreamGroup streamGroup = aClass.getAnnotation(BanyanDB.Group.class).streamGroup();
            banyanDBModelExtension.setStreamGroup(streamGroup);
        }

        // Set routing rules for ElasticSearch
        elasticSearchModelExtension.setRouting(storage.getModelName(), modelColumns);

        seriesIDChecker.check(storage.getModelName());
        shardingKeyChecker.check(storage.getModelName());

        Model model = new Model(
            storage.getModelName(),
            modelColumns,
            scopeId,
            storage.getDownsampling(),
            isSuperDatasetModel(aClass),
            aClass,
            storage.isTimeRelativeID(),
            sqlDBModelExtension,
            banyanDBModelExtension,
            elasticSearchModelExtension
        );

        this.followColumnNameRules(model);
        models.add(model);

        for (final CreatingListener listener : listeners) {
            listener.whenCreating(model);
        }
        return model;
    }
StorageModels manages all models detected by the core.
oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/StorageModels.java