diff --git a/CHANGES.md b/CHANGES.md index d4038478ad1..e0d83c9f574 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,6 +26,7 @@ Apollo 2.2.0 * [Add a configuration config-service.cache.key.ignore-case to control whether the cache key is case-sensitive](https://github.com/apolloconfig/apollo/pull/4820) * [feat: check port use by another process or not when startup](https://github.com/apolloconfig/apollo/pull/4656) * [Bump springboot version from 2.7.9 to 2.7.11](https://github.com/apolloconfig/apollo/pull/4828) +* [[Multi-Database Support][h2] Support run on h2](https://github.com/apolloconfig/apollo/pull/4851) ------------------ All issues and pull requests are [here](https://github.com/apolloconfig/apollo/milestone/13?closed=1) \ No newline at end of file diff --git a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/BizDBPropertySource.java b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/BizDBPropertySource.java index 66b198c3289..17128cd51bf 100644 --- a/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/BizDBPropertySource.java +++ b/apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/service/BizDBPropertySource.java @@ -28,8 +28,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.core.env.Profiles; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils; +import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; import org.springframework.stereotype.Component; +import javax.annotation.PostConstruct; +import javax.sql.DataSource; import java.util.Map; import java.util.Objects; @@ -43,17 +51,27 @@ public class BizDBPropertySource extends RefreshablePropertySource { private final ServerConfigRepository serverConfigRepository; - public BizDBPropertySource(final String name, - final Map source, - final ServerConfigRepository serverConfigRepository) { - super(name, source); - this.serverConfigRepository = serverConfigRepository; - } + private final DataSource dataSource; + + private final Environment env; @Autowired - public BizDBPropertySource(final ServerConfigRepository serverConfigRepository) { + public BizDBPropertySource(final ServerConfigRepository serverConfigRepository, DataSource dataSource, + final Environment env) { super("DBConfig", Maps.newConcurrentMap()); this.serverConfigRepository = serverConfigRepository; + this.dataSource = dataSource; + this.env = env; + } + + @PostConstruct + public void runSqlScript() throws Exception { + if (env.acceptsProfiles(Profiles.of("h2"))) { + Resource resource = new ClassPathResource("jpa/init.h2.sql"); + if (resource.exists()) { + DatabasePopulatorUtils.execute(new ResourceDatabasePopulator(resource), dataSource); + } + } } String getCurrentDataCenter() { diff --git a/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/config/BizConfigTest.java b/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/config/BizConfigTest.java index 4e722725692..2922ef27610 100644 --- a/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/config/BizConfigTest.java +++ b/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/config/BizConfigTest.java @@ -24,8 +24,11 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; import org.springframework.test.util.ReflectionTestUtils; +import javax.sql.DataSource; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -42,11 +45,14 @@ public class BizConfigTest { @Mock private ServerConfigRepository serverConfigRepository; + @Mock + private DataSource dataSource; + private BizConfig bizConfig; @Before public void setUp() throws Exception { - bizConfig = new BizConfig(new BizDBPropertySource(serverConfigRepository)); + bizConfig = new BizConfig(new BizDBPropertySource(serverConfigRepository, dataSource, environment)); ReflectionTestUtils.setField(bizConfig, "environment", environment); } diff --git a/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/service/BizDBPropertySourceTest.java b/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/service/BizDBPropertySourceTest.java index 01d5036d720..e42fcab3a12 100644 --- a/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/service/BizDBPropertySourceTest.java +++ b/apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/service/BizDBPropertySourceTest.java @@ -28,7 +28,9 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mock; +import org.springframework.core.env.Environment; +import javax.sql.DataSource; import java.util.List; import static org.junit.Assert.assertEquals; @@ -43,6 +45,13 @@ public class BizDBPropertySourceTest extends AbstractUnitTest { @Mock private ServerConfigRepository serverConfigRepository; + + @Mock + private DataSource dataSource; + + @Mock + private Environment environment; + private BizDBPropertySource propertySource; private String clusterConfigKey = "clusterKey"; @@ -54,7 +63,7 @@ public class BizDBPropertySourceTest extends AbstractUnitTest { @Before public void initTestData() { - propertySource = spy(new BizDBPropertySource(serverConfigRepository)); + propertySource = spy(new BizDBPropertySource(serverConfigRepository, dataSource, environment)); List configs = Lists.newLinkedList(); diff --git a/apollo-configservice/src/main/resources/jpa/init.h2.sql b/apollo-configservice/src/main/resources/jpa/init.h2.sql new file mode 100644 index 00000000000..c7c19f0c12e --- /dev/null +++ b/apollo-configservice/src/main/resources/jpa/init.h2.sql @@ -0,0 +1,23 @@ +-- +-- Copyright 2023 Apollo Authors +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +INSERT INTO "ServerConfig" ("Key", "Cluster", "Value", "Comment", "DataChange_CreatedBy", "DataChange_CreatedTime") +VALUES + ('eureka.service.url', 'default', 'http://localhost:8080/eureka/', 'Eureka服务Url,多个service以英文逗号分隔', 'default', '1970-01-01 00:00:00'), + ('namespace.lock.switch', 'default', 'false', '一次发布只能有一个人修改开关', 'default', '1970-01-01 00:00:00'), + ('item.key.length.limit', 'default', '128', 'item key 最大长度限制', 'default', '1970-01-01 00:00:00'), + ('item.value.length.limit', 'default', '20000', 'item value最大长度限制', 'default', '1970-01-01 00:00:00'), + ('config-service.cache.enabled', 'default', 'false', 'ConfigService是否开启缓存,开启后能提高性能,但是会增大内存消耗!', 'default', '1970-01-01 00:00:00'); +CREATE ALIAS IF NOT EXISTS UNIX_TIMESTAMP FOR "com.ctrip.framework.apollo.common.jpa.H2Function.unixTimestamp"; diff --git a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/PortalDBPropertySource.java b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/PortalDBPropertySource.java index a7bd3f55836..b5431bcb1e6 100644 --- a/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/PortalDBPropertySource.java +++ b/apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/PortalDBPropertySource.java @@ -25,9 +25,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.core.env.Profiles; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils; +import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; import org.springframework.stereotype.Component; -import java.util.Map; +import javax.annotation.PostConstruct; +import javax.sql.DataSource; import java.util.Objects; @@ -40,16 +47,27 @@ public class PortalDBPropertySource extends RefreshablePropertySource { private final ServerConfigRepository serverConfigRepository; - public PortalDBPropertySource(final String name, - final Map source, - final ServerConfigRepository serverConfigRepository) { - super(name, source); - this.serverConfigRepository = serverConfigRepository; - } + private final DataSource dataSource; + + private final Environment env; + @Autowired - public PortalDBPropertySource(final ServerConfigRepository serverConfigRepository) { + public PortalDBPropertySource(final ServerConfigRepository serverConfigRepository, DataSource dataSource, + final Environment env) { super("DBConfig", Maps.newConcurrentMap()); this.serverConfigRepository = serverConfigRepository; + this.dataSource = dataSource; + this.env = env; + } + + @PostConstruct + public void runSqlScript() throws Exception { + if (env.acceptsProfiles(Profiles.of("h2"))) { + Resource resource = new ClassPathResource("jpa/init.h2.sql"); + if (resource.exists()) { + DatabasePopulatorUtils.execute(new ResourceDatabasePopulator(resource), dataSource); + } + } } @Override diff --git a/apollo-portal/src/main/resources/jpa/init.h2.sql b/apollo-portal/src/main/resources/jpa/init.h2.sql new file mode 100644 index 00000000000..5e22d656906 --- /dev/null +++ b/apollo-portal/src/main/resources/jpa/init.h2.sql @@ -0,0 +1,59 @@ +-- +-- Copyright 2023 Apollo Authors +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +CREATE TABLE SPRING_SESSION +( + PRIMARY_ID VARCHAR(255) NOT NULL, + SESSION_ID VARCHAR(255) NOT NULL, + CREATION_TIME BIGINT NOT NULL, + LAST_ACCESS_TIME BIGINT NOT NULL, + MAX_INACTIVE_INTERVAL INT NOT NULL, + EXPIRY_TIME BIGINT NOT NULL, + PRINCIPAL_NAME VARCHAR(100), + CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID) +); + +CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID); +CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME); +CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME); + +CREATE TABLE SPRING_SESSION_ATTRIBUTES +( + SESSION_PRIMARY_ID VARCHAR(255) NOT NULL, + ATTRIBUTE_NAME VARCHAR(200) NOT NULL, + ATTRIBUTE_BYTES BLOB NOT NULL, + CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME), + CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION (PRIMARY_ID) ON DELETE CASCADE +); + +INSERT INTO "ServerConfig" ("Key", "Value", "Comment", "DataChange_CreatedBy", "DataChange_CreatedTime") +VALUES + ('apollo.portal.envs', 'dev', '可支持的环境列表', 'default', '1970-01-01 00:00:00'), + ('organizations', '[{"orgId":"TEST1","orgName":"样例部门1"},{"orgId":"TEST2","orgName":"样例部门2"}]', '部门列表', 'default', '1970-01-01 00:00:00'), + ('superAdmin', 'apollo', 'Portal超级管理员', 'default', '1970-01-01 00:00:00'), + ('api.readTimeout', '10000', 'http接口read timeout', 'default', '1970-01-01 00:00:00'), + ('consumer.token.salt', 'someSalt', 'consumer token salt', 'default', '1970-01-01 00:00:00'), + ('admin.createPrivateNamespace.switch', 'true', '是否允许项目管理员创建私有namespace', 'default', '1970-01-01 00:00:00'), + ('configView.memberOnly.envs', 'pro', '只对项目成员显示配置信息的环境列表,多个env以英文逗号分隔', 'default', '1970-01-01 00:00:00'), + ('apollo.portal.meta.servers', '{}', '各环境Meta Service列表', 'default', '1970-01-01 00:00:00'); + +INSERT INTO "Users" ("Username", "Password", "UserDisplayName", "Email", "Enabled") +VALUES + ('apollo', '$2a$10$7r20uS.BQ9uBpf3Baj3uQOZvMVvB1RN3PYoKE94gtz2.WAOuiiwXS', 'apollo', 'apollo@acme.com', 1); + +INSERT INTO "Authorities" ("Username", "Authority") +VALUES + ('apollo', 'ROLE_user'); +CREATE ALIAS IF NOT EXISTS UNIX_TIMESTAMP FOR "com.ctrip.framework.apollo.common.jpa.H2Function.unixTimestamp";