写博客总结的基本上都是工作中碰到的痛点,这次解决了一直想解决的问题,就是springboot启动服务的时候,自动去创建数据库的问题
用nodejs+mongodb开发网站的时候,如果没有在mongodb里创建数据库的时候,启动项目,nodejs服务会自动创建数据库,但java程序里确不行,总是报错,特别是 spring-boot 这样的项目,启动默认自动配置 dataSource
所以在程序启动之前要先把数据库创建好,虽然借助工具可以很方便的创建数据库,但哪有自动创建爽
默认启动时调用初始化方法,具体代码如下
@Configuration public class DataSourceHelper { private Logger log = LoggerFactory.getLogger(DataSourceHelper.class); @Value("${datasource_driver}") private String driver; // com.mysql.cj.jdbc.Driver @Value("${datasource_url}") private String url; // jdbc:mysql://localhost:3306/pybbs?useSSL=false&characterEncoding=utf8 @Value("${datasource_username}") private String username; // root @Value("${datasource_password}") private String password; // password @PostConstruct public void init() { try { Class.forName(driver); URI uri = new URI(url.replace("jdbc:", "")); String host = uri.getHost(); int port = uri.getPort(); String path = uri.getPath(); Connection connection = DriverManager.getConnection("jdbc:mysql://" + host + ":" + port, username, password); Statement statement = connection.createStatement(); statement.executeUpdate("CREATE DATABASE IF NOT EXISTS `" + path.replace("/", "") + "` DEFAULT CHARACTER SET = `utf8` COLLATE `utf8_general_ci`;"); statement.close(); connection.close(); } catch (URISyntaxException | ClassNotFoundException | SQLException e) { log.error(e.getMessage()); } } }
原理也很简单,程序启动的时候,首先让它执行这段代码,创建一个不指定数据库的连接,然后执行创建数据库的sql,最后把连接关闭即可
但是!!!如果能这么简单我就不写博客了,都知道spring-boot启动时会自动配置dataSource,它内置了一个自动配置类 DataSourceAutoConfiguration
这就麻烦了,这货的执行优先级还挺高,程序启动后上面我们自己创建的用于创建数据库的类还没执行, DataSourceAutoConfiguration
这货就开始初始化了,然后就去连接配置的数据库,结果就是报错,错误信息就是没有 xx 数据库
怎么办?往下看
既然spring-boot内置的数据源启动的时候就初始化了,那我不用它了,总没事了吧,首先把这个自动初始化给去掉
// 不用默认配置的数据源,自己配置 @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) public class PybbsApplication { public static void main(String[] args) { SpringApplication.run(PybbsApplication.class, args); } }
这个去掉后,程序再启动就没有数据源了,这时候我们就可以自己创建自己的数据源了
既然spring-boot里内置了 HikariDataSource
数据源,这货网上说号称是性能最高的数据源,那我们就继续用它,具体代码如下
@Configuration public class DataSourceConfig { @Value("${datasource_driver}") private String driver; @Value("${datasource_url}") private String url; @Value("${datasource_username}") private String username; @Value("${datasource_password}") private String password; private HikariDataSource dataSource; public HikariDataSource instance() { if (dataSource != null) return dataSource; HikariConfig config = new HikariConfig(); config.setDriverClassName(driver); config.setJdbcUrl(url); config.setUsername(username); config.setPassword(password); config.addDataSourceProperty("cachePrepStmts", true); config.addDataSourceProperty("prepStmtCacheSize", 500); config.addDataSourceProperty("prepStmtCacheSqlLimit", 2048); config.setConnectionTestQuery("SELECT 1"); config.setAutoCommit(true); //池中最小空闲链接数量 config.setMinimumIdle(10); //池中最大链接数量 config.setMaximumPoolSize(50); dataSource = new HikariDataSource(config); return dataSource; } @Bean(name = "dataSource") @DependsOn("dataSourceHelper") public DataSource dataSource() { return instance(); } }
可以看到 dataSource()
方法上面加上了个注解 @DependsOn("dataSourceHelper")
这个注解的意思就是这个数据源要依赖于 dataSourceHelper
这个类初始化后才能初始化,所以这就解决了执行先后的问题了
至此完美解决了程序启动之前还要自己创建数据库的问题了
原文链接: