Using a Database as a Central Configuration Center in SpringBoot

This article analyzes the problems of scattered property configuration in SpringBoot projects, designs a database table to store configuration items, implements a configuration loader that injects database values into the Spring environment, and demonstrates testing and best‑practice considerations for a robust backend configuration solution.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Using a Database as a Central Configuration Center in SpringBoot

Introduction

In recent work the author frequently encountered chaotic property configuration in SpringBoot back‑end projects, where values were scattered across property files, database tables, and hard‑coded fields. To unify configuration, the author proposes using a database as a central configuration center.

The article starts from the existing problems, designs a database schema, modifies the property injection mechanism, and finally validates the approach at runtime.

Messy Property Configuration

Because the original framework lacked a unified standard for property configuration, different developers adopted various implementations, leading to bloated and hard‑to‑maintain settings.

Currently three forms of configuration exist in the SpringBoot project:

SpringBoot property files
Database configuration table
Hard‑coded fields

SpringBoot Property Files

These properties are stored in the standard SpringBoot configuration files, often containing sensitive data in plain text.

# 阿里云
aliyun.accessKeyId=LT***uao
aliyun.accessKeySecret=0Qhe***byr1f

Database Configuration Table

Properties are read from a database table and loaded into cache or used directly.

Hard‑coded Fields

These are constant values directly written in code, often containing sensitive information.

public class WechatConfig {

    public static final class MINI {
        public static String APP_ID = "wx2***dd5";
        public static String APP_SECRET = "38f***9c74";
    }
}

Configuration Separation Strategy

Separating configuration from code improves robustness, maintainability, and allows changes without code modifications or application restarts.

Not all configurations need separation; they must first be classified.

Classification of Property Configurations

Framework‑level Spring settings (e.g., server.port, mybatis.mapper-locations) remain in application[-ENV].properties.

Service‑level settings (e.g., logback-spring.xml, logging.path) stay in their original locations.

Third‑party platform settings (e.g., Alibaba Cloud OSS, WeChat Mini‑program) are moved to the database configuration center.

The first two categories are left unchanged; the focus is on the third category.

Database Table Design

The table stores each configuration as a key‑value pair, with optional group and namespace fields for categorisation and environment separation. data_key and data_value hold the key‑value pair. data_group groups related configurations (e.g., aliyun.oss). namespace distinguishes environments or tenants.

Table definition:

CREATE TABLE `admin_data_config` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增Id',
  `create_time` bigint(20) DEFAULT '0' COMMENT '创建时间',
  `create_user` bigint(20) DEFAULT '0' COMMENT '创建者',
  `update_time` bigint(20) DEFAULT '0' COMMENT '更新时间',
  `update_user` bigint(20) DEFAULT '0' COMMENT '更新者',
  `is_del` tinyint(4) DEFAULT '0' COMMENT '是否删除:1.是 0.否',
  `data_key` varchar(100) DEFAULT '' COMMENT '键',
  `data_value` varchar(100) DEFAULT '' COMMENT '值',
  `description` varchar(50) DEFAULT '' COMMENT '描述',
  `data_group` varchar(50) DEFAULT 'default_group' COMMENT '分组',
  `namespace` varchar(50) DEFAULT 'public' COMMENT '命名空间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='配置中心';

Sample data (illustrated in the following image) stores WeChat Mini‑program credentials.

Implementation Code

Core Configuration Class

The class reads all rows from admin_data_config at startup, converts them into a MapPropertySource, and adds it to the highest‑priority position of MutablePropertySources using @PostConstruct.

@Configuration
public class DBPropertyDataConfig {

    @Resource
    private ConfigurableEnvironment configurableEnvironment;

    @Resource
    private AdminDataConfigMapper adminDataConfigMapper;

    @PostConstruct
    public void init() {
        MutablePropertySources mutablePropertySources = configurableEnvironment.getPropertySources();
        List<AdminDataConfig> dataConfigList = adminDataConfigMapper.list(null);
        if (dataConfigList == null || dataConfigList.size() == 0) {
            return;
        }
        Map<String, Object> propertyMap = dataConfigList.stream()
                .collect(Collectors.toMap(AdminDataConfig::getDataKey, AdminDataConfig::getDataValue));
        MapPropertySource mapPropertySource = new MapPropertySource("db_data_config", propertyMap);
        mutablePropertySources.addFirst(mapPropertySource);
    }
}

Data Injection Example

Existing configuration classes need their setters annotated with @Value so that Spring injects values from the new property source. For static fields, injection must happen via a setter method.

@Configuration
public class WechatConfig {

    public static final class MINI {
        public static String APP_ID;
        public static String APP_SECRET;
    }

    @Value("${wechat.mini.app-id}")
    public void setAppId(String appId) {
        MINI.APP_ID = appId;
    }

    @Value("${wechat.mini.app-secret}")
    public void setAppSecret(String appSecret) {
        MINI.APP_SECRET = appSecret;
    }
}

Important Notes

Member variables must not be declared final.

Mark the class with @Configuration so that it becomes a Spring bean.

Static variables require injection on their setter methods.

Do not perform injection inside inner classes.

Ensure DBPropertyDataConfig loads before beans that depend on its properties, using @DependsOn if necessary.

Example of enforcing load order:

@Service
@DependsOn("DBPropertyDataConfig")
public class BlackBoxFacade {
    @Value("${black-box.company}")
    public String SYS_COMPANY;
}

Testing and Verification

Data Preparation

INSERT INTO `admin_data_config`
(`data_key`, `data_value`, `description`, `data_group`, `namespace`)
VALUES
('wechat.mini.app-id', 'wx2***', '微信小程序 appid', 'wechat.mini', 'public'),
('wechat.mini.app-secret', '38f***', '微信小程序 app secret', 'wechat.mini', 'public');

API Test

URL: http://localhost:8080/app/account/login Method: POST Content‑Type: form-data Parameter:

data : {"jsCode":"FFF"}

Breakpoint Observation

Set breakpoints in the source code (see images) and verify that the injected values are correctly loaded from the database.

Conclusion and Extensions

The database‑based configuration center is now functional. The core code is limited to the configuration loader; most effort lies in refactoring existing configuration classes. After successful testing, the solution has been rolled out to all production projects.

While a database can serve as a simple configuration store, alternatives like Nacos provide richer features. The database approach requires no additional services, making it suitable for small projects.

Future work will explore dynamic refresh of configuration values to achieve even more flexible property management.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendJavadatabaseConfigurationSpringBootPropertyInjection
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.