SpringBoot启动执行sql脚本

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

SpringBoot启动执行sql脚本

AtongWood   2022-05-23 我要评论

背景

项目里后端需要计算坐标距离,想用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接口。我们不必这么做,前两种做法更好。

Springboot自动执行sql文件

在springboot1.5及以前的版本,要执行sql文件只需在applicaion文件里指定sql文件的位置即可。但是到了springboot2.x版本,

如果只是这样做的话springboot不会自动执行sql文件,还需在applicaion文件里加入如下配置

initialization-mode: always

这样springboot就会帮我们自动执行sql了

注意:!!!

建表完成后如果不再需要使用sql文件的话要把sql文件删除,否则springboot会重新建表,这样原来表中的内容就没有了!!!

总结

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们