在应用程序启动时运行MyBatis

时间:2019-04-26 09:51:04

标签: mybatis spring-mybatis

我为我的帐户设置了myBatis设置。通过在命令行(在Jenkins中)使用migration命令来实现。现在,我想将此与应用程序本身集成(春季启动)。目前,我使用@Undo和up sql代码使用了不同的sql文件。

因此,当我启动Sping引导应用程序时,我想运行migration up命令而不更改已经拥有的sql文件吗?在MyBatis和Spring中有可能吗?

2 个答案:

答案 0 :(得分:1)

大约是MyBatis-Migrations,对吧?
Spring Boot不提供开箱即用的支持,但是,似乎可以编写自定义的DatabasePopulator

这是一个简单的实现。
它使用了Migrations的Runtime Migration功能。

import java.io.File;
import java.net.URL;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.migration.ConnectionProvider;
import org.apache.ibatis.migration.FileMigrationLoader;
import org.apache.ibatis.migration.MigrationException;
import org.apache.ibatis.migration.operations.UpOperation;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.ScriptException;
import org.springframework.jdbc.datasource.init.UncategorizedScriptException;

public class MyBatisMigrationsPopulator implements DatabasePopulator {
  private final DataSource dataSource;
  private final String scriptsDir;
  private final Properties properties;
  private final DatabaseOperationOption options;

  public MyBatisMigrationsPopulator(DataSource dataSource, String scriptsDir,
      Properties properties, DatabaseOperationOption options) {
    super();
    this.dataSource = dataSource;
    this.scriptsDir = scriptsDir;
    this.properties = properties;
    this.options = options;
  }

  @Override
  public void populate(Connection connection) throws SQLException, ScriptException {
    try {
      new UpOperation().operate(new DataSourceConnectionProvider(dataSource),
        createMigrationsLoader(), options, null);
    } catch (MigrationException e) {
      throw new UncategorizedScriptException("Migration failed.", e.getCause());
    }
  }

  protected FileMigrationLoader createMigrationsLoader() {
    URL url = getClass().getClassLoader().getResource(scriptsDir);
    File dir = new File(url.getFile());
    return new FileMigrationLoader(dir, "utf-8", properties);
  }
}

DataSourceInitializer的示例bean定义:

@Bean
public DataSourceInitializer dataSourceInitializer(DataSource dataSource) {
  // the directory that contains SQL scripts
  String scriptsDir = "scripts";
  String CHANGELOG_TABLE = "databaseChangelog";
  Properties properties = new Properties();
  properties.setProperty("changelog", CHANGELOG_TABLE);
  DatabaseOperationOption options = new DatabaseOperationOption();
  options.setChangelogTable(CHANGELOG_TABLE);
  MyBatisMigrationsPopulator populator = 
    new MyBatisMigrationsPopulator(dataSource, scriptsDir, properties, options);
  DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
  dataSourceInitializer.setDataSource(dataSource);
  dataSourceInitializer.setDatabasePopulator(populator);
  return dataSourceInitializer;
}

这里是可执行文件demo project
您可能需要修改application.properties中的数据源设置。

希望这会有所帮助!

答案 1 :(得分:0)

对于春季:

import java.io.File;
import java.net.URL;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;

import org.apache.ibatis.migration.ConnectionProvider;
import org.apache.ibatis.migration.FileMigrationLoader;
import org.apache.ibatis.migration.operations.UpOperation;
import org.apache.ibatis.migration.options.DatabaseOperationOption;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.init.DataSourceInitializer;
import org.springframework.jdbc.datasource.init.DatabasePopulator;
import org.springframework.jdbc.datasource.init.ScriptException;

@Configuration
public class MyBatisMigrationRuntimeConfiguration {

    private static final String CHANGELOG_TABLE = "changelog";
    private static final String MIGRATION_SCRIPTS = "migration/scripts";

    @Bean
    public DataSourceInitializer dataSourceInitializer(DataSource dataSource) {
        DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
        dataSourceInitializer.setDataSource(dataSource);
        dataSourceInitializer.setDatabasePopulator(new Populator());
        return dataSourceInitializer;
    }

    private DatabaseOperationOption getOption() {
        DatabaseOperationOption options = new DatabaseOperationOption();
        options.setChangelogTable(CHANGELOG_TABLE);
        return options;
    }

    private Properties getProperties() {
        Properties properties = new Properties();
        properties.setProperty("changelog", CHANGELOG_TABLE);
        return properties;
    }

    private File getScriptDir() {
        URL url = getClass().getClassLoader().getResource(MIGRATION_SCRIPTS);
        if (url == null) {
            throw new IllegalArgumentException("file is not found!");
        } else {
            return new File(url.getFile());
        }
    }

    private class Populator implements DatabasePopulator {
        @Override
        public void populate(Connection connection) throws SQLException, ScriptException {
            new UpOperation().operate(
                    new SimplyConnectionProvider(connection),
                    new FileMigrationLoader(getScriptDir(), "utf-8", getProperties()),
                    getOption(),
                    System.out
            );
        }
    }

    private static class SimplyConnectionProvider implements ConnectionProvider {
        private final Connection connection;

        public SimplyConnectionProvider(Connection connection) {
            this.connection = connection;
        }

        public Connection getConnection() {
            return connection;
        }
    }
}