SpringBoot启动执行sql脚本的三种方式

it2022-05-05  111

目录

背景配置application.yml文件自定义DataSourceInitializer Bean启动时执行方法

背景

项目里后端需要计算坐标距离,想用sql实现算法,然后通过执行一个sql脚本,创建一个函数供各业务调用。我们需要在springboot项目启动时执行sql脚本,在网上一顿搜索,总结了有三种做法:

配置application.yml文件自定义DataSourceInitializer Bean启动时执行方法

第一种做法最方便简洁,是首选方案,但是由于种种原因项目里不能用,只能选择使用第二种做法。第三种做法不推荐,这里只当是记录一下做过的工作。 开发调测sql脚本的时候,推荐使用这个驱动,可以让我们看到sql执行日志,有没有执行?报了什么异常?

spring datasource driver-class-name: net.sf.log4jdbc.DriverSpy <dependency> <groupId>com.googlecode.log4jdbc</groupId> <artifactId>log4jdbc</artifactId> <version>1.2</version> <scope>runtime</scope> </dependency>

同时,spring.datasource.url的配置应该如下起头

spring datasource url: 'jdbc:log4jdbc:mysql://XXXXX'

配置application.yml文件

spring: datasource: username: root password: root driver-class-name: net.sf.log4jdbc.DriverSpy url: jdbc:log4jdbc:mysql://localhost:3306/springboot schema: - classpath:sql/function.sql - classpath:sql/procedure.sql initialization-mode: ALWAYS separator:\\

自定义存储过程或者函数时,可能需要使用delimiter设置断句分隔符,但是delimiter在springboot执行的sql脚本里不可用。springboot提供了spring.datasource.separator配置解决这个问题,如上配置之后,不必执行delimiter \\,我们在脚本里可以直接使用\\作为分隔符。

以下两种情况会导致启动时sql脚本不执行: 1.启动类上的注解如果配置了exclude={DataSourceAutoConfiguration.class},sql脚本将不被执行。

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})

2.如果开启了druid连接池的防火墙,sql脚本将不被执行。

spring datasource druid filter wall enabled: true

自定义DataSourceInitializer Bean

参考博文:Spring Boot中自动执行sql脚本

import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.core.io.Resource; import org.springframework.jdbc.datasource.init.DataSourceInitializer; import org.springframework.jdbc.datasource.init.DatabasePopulator; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; import javax.sql.DataSource; public class CustomizeDataSourceInitializer { @Value("classpath:sql/function.sql") private Resource functionScript; @Bean public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) { final DataSourceInitializer initializer = new DataSourceInitializer(); // 设置数据源 initializer.setDataSource(dataSource); initializer.setDatabasePopulator(databasePopulator()); return initializer; } private DatabasePopulator databasePopulator() { final ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); populator.addScripts(functionScript); populator.setSeparator("$$"); return populator; } }

populator.setSeparator("$$")的作用和配置spring.datasource.separator一样。

启动时执行方法

参考博文:springboot启动前执行方法的几种方式 三种实现方式:

第一种 @PostConstruct注解 第二种 实现InitializingBean接口 第三种 实现BeanPostProcessor接口

这种做法思路就是启动时调用MyBatis接口,但是受限于Mybatis的用法规则,不能完美的满足需求,比如,执行的sql脚本只能有一条语句,这样的话,如果我要创建两个存储过程,需要先后调用两个MyBatis接口。我们不必这么做,前两种做法更好。


最新回复(0)