springboot 启动时初始化数据库的步骤

作者:鲸冬香 时间:2024-01-26 18:32:57 

问题描述

在spring-boot启动时,希望能执行相应的sql文件来初始化数据库。

使用配置文件初始化数据库

可以在spring-boot的配置文件application.yml中设置要初始化的sql文件。这是最简单的方法,只需要添加属性就可以实现。

首先设置spring.datasource.initialization-mode=always表示任何类型数据库都进行数据库初始化,默认情况下,spring-boot会自动加载data.sql或data-${platform}.sql文件来初始化数据库。可以通过设置不同的数据库平台来改变启动的脚本名称。

例如设置spring.datasource.platform=mysql,就会加载data-mysql.sql的数据库脚本。把数据库脚本文件放在resources路径下即可。

如果项目使用的是flyway管理数据库的话,可以直接在flyway路径下添加一个新版本的sql文件,flyway也会自动执行sql文件并记录版本信息。

通过代码初始化数据库

如果通过配置文件不能满足需求,可以通过代码来初始化数据库。
只需要提供DataSourceInitializer这个bean,spring-boot启动时就会根据DataSourceInitializer来初始化数据库了。


@Bean
public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) {
 ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
 resourceDatabasePopulator.addScript(new ClassPathResource("/data.sql"));
 DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
 dataSourceInitializer.setDataSource(dataSource);
 dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);
 return dataSourceInitializer;
}

在此基础上,我们可以自定义注解,通过获取注解上的sql文件路径,来达到通过注解初始化数据库目的,这样更方便简洁。
首先定义注解InitDataSource:


/**
* 用于补充:Hibernate无法自动创建视图的缺陷。
* 系统启动时(hibernate根据entity创建完基本的数据表后),开始执行本注解下的sql文件中的SQL语言。
* 使用方法:
* @InitDataSource("sql文件路径(相对于resources路径下)") ---- 注解到对应的类上
* 比如:@InitDataSource("db/view/createView.sql)")
* 使用示例请参见:ResourceApplication.java
* 预了解详细的实现过程请参考:WebConfig.java 的 dataSourceInitializer方法
* @author huangtingxiang
*/
@Target({ElementType.TYPE})   // 该注解用于类上
@Retention(RetentionPolicy.RUNTIME) // 在运行时起作用
@Component
public @interface InitDataSource {
 String\[\] value();
}

然后通过ClassPathScanningCandidateComponentProvider这个类来扫描spring组件上InitDataSource注解的值,将值取出,添加到DataSourceInitializer的初始化脚本中:


@Bean
public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) {
 ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
 // 扫描com.mengyunzhi.measurement 包 找到InitDataSource注解的类(注解需使用到实现类上)
ClassPathScanningCandidateComponentProvider provider
     = new ClassPathScanningCandidateComponentProvider(false);
 provider.addIncludeFilter(new AnnotationTypeFilter(InitDataSource.class)); //添加包含的过滤信息
for (BeanDefinition beanDef : provider.findCandidateComponents("com.mengyunzhi.measurement")) {
   Class<?> cl = null;
   try {
     cl = Class.forName(beanDef.getBeanClassName());
     InitDataSource initDataSource = cl.getAnnotation(InitDataSource.class);
     String\[\] sqlFiles = initDataSource.value();
     for (String sql: sqlFiles) {
       // 如果sql文件存在 加入数据库初始化中 否则抛出异常终止执行
ClassPathResource resource = new ClassPathResource("/" + sql);
       if (resource.exists()) {
         resourceDatabasePopulator.addScript(resource);
       } else {
         throw new DataSourceInitializerException("未找到资源文件:" + sql, cl);
       }
     }
   } catch (ClassNotFoundException e) {
     e.printStackTrace();
   }
 }
 DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
 dataSourceInitializer.setDataSource(dataSource);
 dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);
 return dataSourceInitializer;
}

这样一来,只需要在spring-boot类上使用@InitDataSource({"data.sql"})注解,就可以自动进行数据库的初始化操作了。

来源:https://segmentfault.com/a/1190000021705562

标签:springboot,初始化,数据库
0
投稿

猜你喜欢

  • Python xlrd读取excel日期类型的2种方法

    2021-06-28 02:12:53
  • 解决vue单页面多个组件嵌套监听浏览器窗口变化问题

    2024-04-27 15:48:29
  • 如何安装SQL Server 2012群集

    2024-01-14 23:35:09
  • Golang与python线程详解及简单实例

    2023-03-13 18:55:25
  • python连接sql server数据库的方法实战

    2024-01-22 03:28:38
  • CSS实例教程:复合型CSS条状图表(下)

    2010-01-23 12:52:00
  • vue 解决异步数据更新问题

    2024-04-30 10:45:28
  • oracle 多个字符替换实现

    2009-10-23 17:50:00
  • 如何通过Python实现定时打卡小程序

    2023-10-20 14:11:33
  • Python实现发送QQ邮件的封装

    2022-10-08 21:19:56
  • Sql Server中的非聚集索引详细介

    2024-01-26 15:57:56
  • python将邻接矩阵输出成图的实现

    2022-11-12 01:58:39
  • python追加元素到列表的方法

    2023-07-08 14:29:47
  • 如何优化SQL语句的心得浅谈

    2024-01-24 00:39:09
  • OAuth 2.0授权协议详解

    2023-06-15 03:54:43
  • python命名空间(namespace)简单介绍

    2022-06-21 23:26:53
  • Mysql按条件计数多种实现方法详解

    2024-01-18 09:43:35
  • Python操作sqlite3快速、安全插入数据(防注入)的实例

    2022-04-22 16:38:14
  • python多进程实现文件下载传输功能

    2022-06-27 02:22:41
  • Python通过类的组合模拟街道红绿灯

    2021-04-13 02:00:24
  • asp之家 网络编程 m.aspxhome.com