diff --git a/pom.xml b/pom.xml
index 05bae52..8445636 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,8 +25,9 @@
providers/yaml
providers/gson
-
-
+ providers/hocon
+ providers/sql
+ providers/mongodb
demo
diff --git a/providers/mongodb/pom.xml b/providers/mongodb/pom.xml
new file mode 100644
index 0000000..ec26ee8
--- /dev/null
+++ b/providers/mongodb/pom.xml
@@ -0,0 +1,95 @@
+
+
+
+ easyconfiguration-parent
+ cc.carm.lib
+ 4.0.0
+ ../../pom.xml
+
+ 4.0.0
+
+ ${project.jdk.version}
+ ${project.jdk.version}
+ UTF-8
+ UTF-8
+
+ 2.24.3
+
+ easyconfiguration-mongodb
+
+
+
+
+ ${project.parent.groupId}
+ easyconfiguration-core
+ ${project.parent.version}
+ compile
+
+
+
+ ${project.parent.groupId}
+ easyconfiguration-gson
+ ${project.parent.version}
+ compile
+
+
+
+ org.mongodb
+ mongodb-driver-sync
+ 5.3.0
+
+
+
+ ${project.parent.groupId}
+ easyconfiguration-demo
+ ${project.parent.version}
+ test
+
+
+
+ org.apache.logging.log4j
+ log4j-api
+ ${log4j.version}
+ test
+
+
+
+ org.apache.logging.log4j
+ log4j-core
+ ${log4j.version}
+ test
+
+
+
+ org.apache.logging.log4j
+ log4j-slf4j-impl
+ ${log4j.version}
+ test
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+
+
+
+
\ No newline at end of file
diff --git a/providers/mongodb/src/main/java/cc/carm/lib/configuration/source/mongodb/MongoSource.java b/providers/mongodb/src/main/java/cc/carm/lib/configuration/source/mongodb/MongoSource.java
new file mode 100644
index 0000000..c915857
--- /dev/null
+++ b/providers/mongodb/src/main/java/cc/carm/lib/configuration/source/mongodb/MongoSource.java
@@ -0,0 +1,4 @@
+package cc.carm.lib.configuration.source.mongodb;
+
+public class MongoSource {
+}
diff --git a/providers/mongodb/src/test/resources/log4j2.xml b/providers/mongodb/src/test/resources/log4j2.xml
new file mode 100644
index 0000000..f06fcad
--- /dev/null
+++ b/providers/mongodb/src/test/resources/log4j2.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/providers/sql/README.md b/providers/sql/README.md
index c2b19fd..6724c5a 100644
--- a/providers/sql/README.md
+++ b/providers/sql/README.md
@@ -6,15 +6,16 @@ SQL database implementation, support for MySQL or MariaDB.
```mysql
CREATE TABLE IF NOT EXISTS conf
(
- `namespace` VARCHAR(32) NOT NULL, # 命名空间 (代表其属于谁,类似于单个配置文件地址的概念)
- `path` VARCHAR(96) NOT NULL, # 配置路径 (ConfigPath)
- `type` TINYINT UNSIGNED NOT NULL DEFAULT 0, # 数据类型 (Integer/Byte/List/Map/...)
- `value` MEDIUMTEXT, # 配置项的值 (可能为JSON格式)
- `usage` TEXT, # 配置项的用法,本质是行内注释
- `descriptions` MEDIUMTEXT, # 配置项的描述,本质是顶部注释
- `version` INT UNSIGNED NOT NULL DEFAULT 0, # 配置项的版本
- `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, # 创建时间
- `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `namespace` VARCHAR(32) NOT NULL, # 命名空间 (代表其属于谁,类似于单个配置文件地址的概念)
+ `path` VARCHAR(96) NOT NULL, # 配置路径 (ConfigPath)
+ `type` TINYINT UNSIGNED NOT NULL DEFAULT 0, # 数据类型 (Integer/Byte/List/Map/...)
+ `value` MEDIUMTEXT, # 配置项的值 (可能为JSON格式)
+ `inline_comment` TEXT, # 配置项的用法,本质是行内注释
+ `header_comment` MEDIUMTEXT, # 配置项的描述,本质是顶部注释
+ `footer_comment` MEDIUMTEXT, # 配置项的描述,本质是顶部注释
+ `version` INT UNSIGNED NOT NULL DEFAULT 0, # 配置项的版本
+ `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, # 创建时间
+ `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`namespace`, `path`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4;
diff --git a/providers/sql/pom.xml b/providers/sql/pom.xml
index dd35069..cc0f363 100644
--- a/providers/sql/pom.xml
+++ b/providers/sql/pom.xml
@@ -2,13 +2,13 @@
+ 4.0.0
easyconfiguration-parent
cc.carm.lib
- 3.9.1
+ 4.0.0
../../pom.xml
- 4.0.0
${project.jdk.version}
${project.jdk.version}
@@ -27,6 +27,26 @@
${project.parent.version}
compile
+
+ ${project.parent.groupId}
+ easyconfiguration-feature-commentable
+ ${project.parent.version}
+ compile
+
+
+
+ ${project.parent.groupId}
+ easyconfiguration-feature-section
+ ${project.parent.version}
+ compile
+
+
+
+ ${project.parent.groupId}
+ easyconfiguration-feature-versioned
+ ${project.parent.version}
+ compile
+
com.google.code.gson
diff --git a/providers/sql/src/main/java/cc/carm/lib/configuration/EasyConfiguration.java b/providers/sql/src/main/java/cc/carm/lib/configuration/EasyConfiguration.java
deleted file mode 100644
index c027e5d..0000000
--- a/providers/sql/src/main/java/cc/carm/lib/configuration/EasyConfiguration.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package cc.carm.lib.configuration;
-
-import cc.carm.lib.configuration.sql.SQLConfigProvider;
-import cc.carm.lib.easysql.api.SQLManager;
-import org.jetbrains.annotations.NotNull;
-
-public class EasyConfiguration {
-
- private EasyConfiguration() {
- }
-
- public static SQLConfigProvider from(@NotNull SQLManager sqlManager, @NotNull String tableName, @NotNull String namespace) {
- SQLConfigProvider provider = new SQLConfigProvider(sqlManager, tableName, namespace);
- try {
- provider.initializeConfig();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return provider;
- }
-
- public static SQLConfigProvider from(@NotNull SQLManager sqlManager, @NotNull String tableName) {
- return from(sqlManager, tableName, "base");
- }
-
-}
diff --git a/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLOptions.java b/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLOptions.java
new file mode 100644
index 0000000..2777d98
--- /dev/null
+++ b/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLOptions.java
@@ -0,0 +1,6 @@
+package cc.carm.lib.configuration.source.sql;
+
+public interface SQLOptions {
+
+
+}
diff --git a/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLSource.java b/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLSource.java
new file mode 100644
index 0000000..4307766
--- /dev/null
+++ b/providers/sql/src/main/java/cc/carm/lib/configuration/source/sql/SQLSource.java
@@ -0,0 +1,136 @@
+package cc.carm.lib.configuration.source.sql;
+
+import cc.carm.lib.configuration.source.ConfigurationHolder;
+import cc.carm.lib.configuration.source.section.ConfigureSource;
+import cc.carm.lib.configuration.source.section.MemorySection;
+import cc.carm.lib.easysql.api.SQLManager;
+import cc.carm.lib.easysql.api.SQLTable;
+import cc.carm.lib.easysql.api.enums.IndexType;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+
+public class SQLSource extends ConfigureSource, SQLSource> {
+
+ protected static final @NotNull Gson DEFAULT_GSON = new GsonBuilder()
+ .serializeNulls().disableHtmlEscaping().setPrettyPrinting()
+ .create();
+
+ protected final @NotNull Gson gson;
+ protected final @NotNull SQLManager sqlManager;
+ protected final @NotNull String namespace;
+ protected final @NotNull SQLTable table;
+
+ protected final @NotNull Set updated = new HashSet<>();
+ protected MemorySection rootSection;
+
+ public SQLSource(@NotNull ConfigurationHolder extends SQLSource> holder, long lastUpdateMillis,
+ @NotNull Gson gson, @NotNull SQLManager sqlManager, @NotNull String tableName, @NotNull String namespace) {
+ super(holder, lastUpdateMillis);
+ this.gson = gson;
+ this.sqlManager = sqlManager;
+ this.namespace = namespace;
+ this.table = SQLTable.of(tableName, builder -> {
+
+ builder.addColumn("namespace", "VARCHAR(32) NOT NULL");
+ builder.addColumn("path", "VARCHAR(96) NOT NULL");
+
+ builder.addColumn("type", "TINYINT NOT NULL DEFAULT 0");
+ builder.addColumn("value", "TEXT");
+
+ builder.addColumn("inline_comment", "TEXT");
+ builder.addColumn("header_comments", "MEDIUMTEXT");
+ builder.addColumn("footer_comments", "MEDIUMTEXT");
+
+ builder.addColumn("version", "MEDIUMINT UNSIGNED NOT NULL DEFAULT 0");
+
+ builder.addColumn("create_time", "TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP");
+ builder.addColumn("update_time", "TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP");
+
+ builder.setIndex(
+ IndexType.PRIMARY_KEY, "pk_" + tableName.toLowerCase(),
+ "namespace", "path"
+ );
+ builder.setTableSettings("ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
+ });
+ }
+
+ @Override
+ protected SQLSource self() {
+ return this;
+ }
+
+ @Override
+ public @NotNull Map, ?> original() {
+ return section().data();
+ }
+
+ @Override
+ public @NotNull MemorySection section() {
+ return Objects.requireNonNull(this.rootSection, "Root section is not initialized.");
+ }
+
+ @Override
+ public void save() throws Exception {
+ if (this.updated.isEmpty()) return; // Nothing to save
+
+ Date date = new Date(); // Update time
+ List