diff --git a/kernel-d-db/db-api/src/main/java/cn/stylefeng/roses/kernel/db/api/exception/enums/FlywayExceptionEnum.java b/kernel-d-db/db-api/src/main/java/cn/stylefeng/roses/kernel/db/api/exception/enums/FlywayExceptionEnum.java new file mode 100644 index 000000000..66669ae95 --- /dev/null +++ b/kernel-d-db/db-api/src/main/java/cn/stylefeng/roses/kernel/db/api/exception/enums/FlywayExceptionEnum.java @@ -0,0 +1,42 @@ +package cn.stylefeng.roses.kernel.db.api.exception.enums; + +import cn.stylefeng.roses.kernel.db.api.constants.DbConstants; +import cn.stylefeng.roses.kernel.rule.abstracts.AbstractExceptionEnum; +import cn.stylefeng.roses.kernel.rule.constants.RuleConstants; +import lombok.Getter; + +/** + * Flyway相关异常枚举 + * + * @author fengshuonan + * @date 2021/1/18 22:59 + */ +@Getter +public enum FlywayExceptionEnum implements AbstractExceptionEnum { + + /** + * 获取不到application.yml中的数据库配置 + */ + DB_CONFIG_ERROR(RuleConstants.BUSINESS_ERROR_TYPE_CODE + DbConstants.DB_EXCEPTION_STEP_CODE + "01", "获取不到application.yml中的数据库配置,无法为flyway创建数据库链接"), + + /** + * flyway执行迁移异常 + */ + FLYWAY_MIGRATE_ERROR(RuleConstants.BUSINESS_ERROR_TYPE_CODE + DbConstants.DB_EXCEPTION_STEP_CODE + "02", "脚本错误,flyway执行迁移异常"); + + /** + * 错误编码 + */ + private final String errorCode; + + /** + * 提示用户信息 + */ + private final String userTip; + + FlywayExceptionEnum(String errorCode, String userTip) { + this.errorCode = errorCode; + this.userTip = userTip; + } + +} diff --git a/kernel-d-db/db-sdk-flyway/pom.xml b/kernel-d-db/db-sdk-flyway/pom.xml new file mode 100644 index 000000000..cb0cc76eb --- /dev/null +++ b/kernel-d-db/db-sdk-flyway/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + + cn.stylefeng.roses + kernel-d-db + 1.0.0 + ../pom.xml + + + db-sdk-flyway + + jar + + + + + + cn.stylefeng.roses + db-api + 1.0.0 + + + + + org.flywaydb + flyway-core + + + + diff --git a/kernel-d-db/db-sdk-flyway/src/main/java/cn/stylefeng/roses/kernel/db/flyway/FlywayInitListener.java b/kernel-d-db/db-sdk-flyway/src/main/java/cn/stylefeng/roses/kernel/db/flyway/FlywayInitListener.java new file mode 100644 index 000000000..48ea59a5d --- /dev/null +++ b/kernel-d-db/db-sdk-flyway/src/main/java/cn/stylefeng/roses/kernel/db/flyway/FlywayInitListener.java @@ -0,0 +1,104 @@ +package cn.stylefeng.roses.kernel.db.flyway; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.stylefeng.roses.kernel.db.api.exception.DaoException; +import cn.stylefeng.roses.kernel.db.api.exception.enums.FlywayExceptionEnum; +import lombok.extern.slf4j.Slf4j; +import org.flywaydb.core.Flyway; +import org.springframework.boot.context.event.ApplicationContextInitializedEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.core.Ordered; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.jdbc.datasource.DriverManagerDataSource; + +/** + * 初始化flyway配置 + *

+ * 当spring装配好配置后开始初始化 + * + * @author liuhanqing + * @date 2021/1/17 21:14 + */ +@Slf4j +public class FlywayInitListener implements ApplicationListener, Ordered { + + private static final String FLYWAY_LOCATIONS = "classpath:db/migration"; + + @Override + public void onApplicationEvent(ApplicationContextInitializedEvent applicationEnvironmentPreparedEvent) { + + + ConfigurableEnvironment environment = applicationEnvironmentPreparedEvent.getApplicationContext().getEnvironment(); + + // 获取数据库连接配置 + String dataSourceUrl = environment.getProperty("spring.datasource.url"); + String dataSourceUsername = environment.getProperty("spring.datasource.username"); + String dataSourcePassword = environment.getProperty("spring.datasource.password"); + + // flyway的配置 + String locations = environment.getProperty("spring.flyway.locations"); + String baselineOnMigrateStr = environment.getProperty("spring.flyway.baseline-on-migrate"); + String outOfOrderStr = environment.getProperty("spring.flyway.out-of-order"); + + // 如果有为空的配置,终止执行 + if (ObjectUtil.hasEmpty(dataSourceUrl, dataSourceUsername, dataSourcePassword)) { + throw new DaoException(FlywayExceptionEnum.DB_CONFIG_ERROR); + } + + // 如果未设置flyway路径,则设置为默认flyway路径 + if (StrUtil.isBlank(locations)) { + locations = FLYWAY_LOCATIONS; + } + + // 当迁移时发现目标schema非空,而且带有没有元数据的表时,是否自动执行基准迁移,默认false. + boolean baselineOnMigrate = false; + if (StrUtil.isNotBlank(baselineOnMigrateStr)) { + baselineOnMigrate = Boolean.parseBoolean(baselineOnMigrateStr); + } + + // 是否允许无序的迁移 开发环境最好开启, 生产环境关闭 + boolean outOfOrder = false; + if (StrUtil.isNotBlank(outOfOrderStr)) { + outOfOrder = Boolean.parseBoolean(outOfOrderStr); + } + + DriverManagerDataSource dmDataSource = null; + try { + assert dataSourceUrl != null; + // 手动创建数据源 + dmDataSource = new DriverManagerDataSource(); + dmDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); + dmDataSource.setUrl(dataSourceUrl); + dmDataSource.setUsername(dataSourceUsername); + dmDataSource.setPassword(dataSourcePassword); + + // flyway配置 + Flyway flyway = Flyway.configure() + .dataSource(dmDataSource) + + // 迁移脚本的位置 + .locations(locations) + + // 当迁移时发现目标schema非空,而且带有没有元数据的表时,是否自动执行基准迁移 + .baselineOnMigrate(baselineOnMigrate) + + // 是否允许无序的迁移 开发环境最好开启 , 生产环境关闭 + .outOfOrder(outOfOrder) + .load(); + + // 执行迁移 + flyway.migrate(); + + } catch (Exception e) { + log.error(">>> flyway初始化失败", e); + throw new DaoException(FlywayExceptionEnum.FLYWAY_MIGRATE_ERROR); + } + } + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } + +} diff --git a/kernel-d-db/db-spring-boot-starter/pom.xml b/kernel-d-db/db-spring-boot-starter/pom.xml index cf3ab8d1c..9f1f11403 100644 --- a/kernel-d-db/db-spring-boot-starter/pom.xml +++ b/kernel-d-db/db-spring-boot-starter/pom.xml @@ -31,6 +31,13 @@ 1.0.0 + + + cn.stylefeng.roses + db-sdk-flyway + 1.0.0 + + diff --git a/kernel-d-db/db-spring-boot-starter/src/main/resources/META-INF/spring.factories b/kernel-d-db/db-spring-boot-starter/src/main/resources/META-INF/spring.factories index b252d308b..dd6a20463 100644 --- a/kernel-d-db/db-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ b/kernel-d-db/db-spring-boot-starter/src/main/resources/META-INF/spring.factories @@ -3,3 +3,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ cn.stylefeng.roses.kernel.db.starter.GunsDruidPropertiesAutoConfiguration,\ cn.stylefeng.roses.kernel.db.starter.GunsMyBatisPlusAutoConfiguration,\ cn.stylefeng.roses.kernel.db.starter.GunsDbInitListenerAutoConfiguration +org.springframework.context.ApplicationListener=\ + cn.stylefeng.roses.kernel.db.flyway.FlywayInitListener diff --git a/kernel-d-db/pom.xml b/kernel-d-db/pom.xml index 1d60855cc..056d6bd25 100644 --- a/kernel-d-db/pom.xml +++ b/kernel-d-db/pom.xml @@ -17,6 +17,7 @@ db-api + db-sdk-flyway db-sdk-init db-sdk-mp db-spring-boot-starter