如何在应用程序启动时运行SQL脚本并获取数据?

问题描述 投票:18回答:5

我正在开发一个Spring Boot应用程序。目前,我的一些配置是硬编码的(例如Hystrix属性)。

所以我想在应用程序启动时或刚启动后获取这些配置。

使用Spring Boot可以做到这一点吗?我的意思是在启动时运行SQL脚本并获取数据。

在我的应用程序中应该如何检索和存储propertiesconfigs?

我正在使用MyBatis和Oracle DB。

java sql spring spring-boot sql-scripts
5个回答
34
投票

默认情况下,Spring-Boot会加载 data.sqldata-${platform}.sql.

然而,请记住,脚本将在每次启动时加载,所以我认为更有意义的是(至少对生产而言),只是让数据库中已经存在的值,而不是在每次启动时重新插入。我个人在使用内存数据库时,只把数据库初始化用于testdev目的。 不过,这是Spring-Boot提供的功能。

来源:Spring-boot-howto-databate spring-boot-howto-database-initialization(数据库初始化):

Spring JDBC有一个DataSource初始化器功能。Spring Boot默认启用它,并从标准位置schema.sql和data.sql(在classpath的根目录下)加载SQL。此外,Spring Boot 还会加载 schema-${platform}.sql 和 data-${platform}.sql 文件(如果存在)。

srcmainresourcesdata-oracle.sql。

insert into...
insert into...
  • 你可以用以下方式定义平台: spring.datasource.platform=oracle.
  • 你可以用以下方法改变要加载的sql脚本的名称。spring.datasource.data=myscript.sql.
  • data.sql,Spring-boot也会加载 schema.sql (之前 data.sql).
  • 你也可以在data.sql中设置一个 "update或insert "的逻辑。oracle sql: update if exists else insert

2
投票

对我有用的是使用 DataSourceInitializer:

@Bean
public DataSourceInitializer dataSourceInitializer(@Qualifier("dataSource") 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;
}

用于在初始化时设置数据库,在销毁时清理数据库。

https:/docs.spring.iospring-frameworkdocscurrentjavadoc-apiorgspringframeworkjdbcdatasourceinitDataSourceInitializer.html。


1
投票

如果你想基于一些业务逻辑来插入数据,我建议你使用事件监听器。所以基本上在应用程序启动时,"OnApplicationEvent",因为它被注解为@EventListener方法将被自动调用。

另外,在你的案例中,你需要获取数据,你只需要使用你的仓库对象来获取数据即可。

这里有一个例子,如果你从application.properties文件中获取数据,那么你只需要使用你的仓库对象来获取数据。

@Component
public class OnApplicationStartUp {

   @Autowired
   private ServiceRepository repository;


   @EventListener
   public void onApplicationEvent(ContextRefreshedEvent event) {

       //Write your business logic here.
       if (repository.findAll().size() <= 0) {
           preloadData();
       }else{
           fetchData();
       }
   }

    private void preloadData() {

       List<Service> services = new ArrayList<>();
       Service someService= new Service("name", "type");
       services.add(someService);
       ...
       ...
       repository.saveAll(services);
   }
}

0
投票

如果你从application.properties文件中获取数据 你可以使用Environment类,就像这样。

Autowired
private Environment environment;
...
environment.getProperty("propertyName")

或者你可以定义你自己的属性文件,然后你可以用 @PropertySource(name = "myProperties", value = "example.properties") 注释

你需要使用@Value注解来从你定义的属性文件中获取一个特定的值。

@Value("${propertyNameInYourPropertFile}")
private String url;

如果你想在Application刚刚启动的时候启动一些东西,你可以在一个方法之前使用这个方法。

@EventListener(ApplicationReadyEvent.class)

但需要使用@Service或@Component Annotation,哪个Class有这个方法。

完全可以用这个方法。

example.properties :

url=yourValue
userName=yourDBUserName
password=yourDBPassword

example.properties : example类。

@Service
@PropertySource(name = "myProperties", value = "example.properties")
public class Start{

    @Value("${url}")
    private String url;

    @Value("${userName}")
    private String userName;

    @Value("${password}")
    private String password;


    //Run this method when application started
    @EventListener(ApplicationReadyEvent.class)
    public ResultSet getConnection()
    {

        //Connect to Database
        Connection connection = null;
        String QUERY="your sql query";
        try {
            DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
            connection = DriverManager.getConnection(url, userName, password );
        } catch (SQLException e) {
        }


        //Run your query
        Statement stmt = null;
        try {
            stmt = connection.createStatement();
        } catch (SQLException e1) {
            e1.printStackTrace();
        }
        ResultSet rs = null;
        try {
            rs = stmt.executeQuery(QUERY);
        } catch (SQLException e1) {
            e1.printStackTrace();
        }

        return rs;
    }

}

0
投票
  1. 定义一个Spring Bean(例如GlobalConfigurationBean)的Scope。@Scope(scopeName = WebApplicationContext.SCOPE_APPLICATION) 这个Bean将负责在Bean初始化时从你的数据库表中获取数据(维护配置属性)。

  2. 使用 @PostConstruct 注释一个方法。 这个方法将具有从你的数据库表中获取配置参数的逻辑。

  3. 这个Bean的范围将确保所需的Configurations只从数据库表中获取一次(例如使用Hibernate查询或纯本地SQL),并且对同一应用程序中不同上下文的所有Bean都可用。

现在只需在您希望使用这些配置属性或参数的任何地方注入此Bean即可。 或者使用:。Apache Commons DatabaseConfiguration <-- 注意::它不支持缓存。但我想你不需要缓存,因为数据库配置属性应该只被加载一次,在应用程序启动时。 或者Trandational老方法。通过扩展 "PropertyPlaceHolderConfigurer "定义一个自定义实现,并将其定义为Spring Bean。这个实现应该有逻辑从你的数据库表中获取数据,该表拥有配置属性。


0
投票

使用基本SQL脚本初始化数据库

当只使用基本 SQL 脚本时,Spring Boot 会自动创建嵌入式 DataSource 的模式。这种行为可以通过使用 spring.datasource.initialization-mode 属性进行自定义。例如,如果您希望始终初始化 DataSource,而不管其类型如何。

spring.datasource.initialization-mode=always
© www.soinside.com 2019 - 2024. All rights reserved.