检查h2数据库是否已损坏,如果损坏则创建新数据库

时间:2018-02-20 09:41:52

标签: java spring-boot h2

我是C#开发人员,需要维护使用spring boot框架开发的现有Java Service应用程序。负责任的开发人员不久前离开了公司,所以我没有可能得到一些帮助...... 到目前为止,我没有使用Java和使用过的spring引导框架的经验。

我需要做什么:

  • 检查使用的h2数据库是否已损坏
  • 如果已损坏:删除数据库并创建一个新的空数据

我想我需要在主要入口点实施检查和娱乐

 public static void main(String[] args) {
        SpringApplication.run(MessageServiceApplication.class, args);
    }

据我所知spring-boot,如果数据库不存在,Hibernate会在启动时自动创建数据库。到现在为止还挺好。现在我需要检查数据库是否已损坏。我考虑过对数据库执行查询,如果我得到异常,我会重新创建数据库。

数据库是一个h2文件数据库。

希望我能得到一些帮助。

编辑#1 我想过实现一个在启动时调用的utils类:

public class H2DbUtils {

public boolean IsH2FileDatabaseCorrupted()
{
    boolean isCorrupted = false;

    // Implement Logic to determine if db is corrupted

    return isCorrupted;
}

public boolean ReCreateH2DatabaseFile()
{
    boolean reCreated = false;
    // Implement Logic to recreate db

    return reCreated;
}

}

在启动时调用此类

 public static void main(String[] args) {

        H2DbUtils h2DbUtils = new H2DbUtils();
        if(h2DbUtils.IsH2FileDatabaseCorrupted()) {
            h2DbUtils.ReCreateH2DatabaseFile();
        }

        SpringApplication.run(MessageServiceApplication.class, args);
    }

更新2018-03-20

目前找到以下解决方案来实现这一目标:

@Configuration
@Component

public class DataSourceBean {

    @Autowired
    private Environment currentEnvironment;
    private final Logger logInstance = LoggerFactory.getLogger(this.getClass());

    @Bean
    @Primary
    public DataSource dataSource()
    {
        DataSource dataSource = null;

        try
        {
            // We try to get the Meta Data out of the database.
            // If this fails the database is corrupted or has an other problem
            // All in all this means we need to delete the current database file
            // to avoid further problems.
            dataSource = this.getDataSource();
            dataSource.getConnection().getMetaData();
            return dataSource;
        }
        catch (Exception ex)
        {
            logInstance.error("The h2 database file '{}' seems to be corrupted! Error: {}",
                                currentEnvironment.getProperty("dataBaseFile"),
                                ex.getMessage());

        // dataBaseFile=./db/mydatabase.db           
            String databaseFilePath = String.format("%s.%s", currentEnvironment.getProperty("dataBaseFile"), "h2.db");
            databaseFilePath = databaseFilePath.replace("/", "\\");

            File databaseFile = new File(databaseFilePath);

            if (databaseFile.exists()) {


                File parentDirectory = new File(databaseFile.getParent());
                if (parentDirectory.isDirectory()) {
                    try {

                        FileUtils.deleteDirectory(parentDirectory);
                    } catch (Exception fex) {

                        logInstance.error("Error occurred deleting the folder {}. Error: {}",
                                            parentDirectory.getAbsolutePath(),
                                            fex.getMessage());
                    }
                }
            }

            dataSource = this.getDataSource();
        }
        finally {

            return dataSource;
        }
    }

    @ConfigurationProperties(prefix = "spring.datasource")
    private DataSource getDataSource() {
        return DataSourceBuilder.create()
                .url(currentEnvironment.getProperty("spring.datasource.url"))
                .driverClassName(currentEnvironment.getProperty("spring.datasource.driverClassName"))
                .username(currentEnvironment.getProperty("spring.datasource.username"))
                .password(currentEnvironment.getProperty("spring.datasource.password"))
                .build();
    }

2 个答案:

答案 0 :(得分:0)

我试图在spring启动应用程序中添加几个侦听器,例如:

    SpringApplication springApplication = new SpringApplication(testApplication.class);
    springApplication.addListeners(new FailedEvent(testApplication.class));
    SpringApplication.run(testApplication.class, args);

但是我从未在spring应用程序的启动中找到其中一个监听器。由于SpringApplication.run似乎初始化整个spring上下文,因此当db已损坏时,当应用程序在SpringApplication.run中停止时,也无法注入或获取配置环境以获取连接字符串。

我认为spring试图初始化hibernate等等,并且因为db损坏而无法创建数据库连接

    org.h2.jdbc.JdbcSQLException: Allgemeiner Fehler: "java.lang.RuntimeException: rowcount remaining=2 SYS"
General error: "java.lang.RuntimeException: rowcount remaining=2 SYS" [50000-196]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:345) ~[h2-1.4.196.jar:1.4.196]
    at org.h2.message.DbException.get(DbException.java:168) ~[h2-1.4.196.jar:1.4.196]
    at org.h2.message.DbException.convert(DbException.java:295) ~[h2-1.4.196.jar:1.4.196]
    at org.h2.engine.Database.openDatabase(Database.java:307) ~[h2-1.4.196.jar:1.4.196]
    at org.h2.engine.Database.<init>(Database.java:270) ~[h2-1.4.196.jar:1.4.196]
    at org.h2.engine.Engine.openSession(Engine.java:64) ~[h2-1.4.196.jar:1.4.196]
    at org.h2.engine.Engine.openSession(Engine.java:176) ~[h2-1.4.196.jar:1.4.196]
    at org.h2.engine.Engine.createSessionAndValidate(Engine.java:154) ~[h2-1.4.196.jar:1.4.196]
    at org.h2.engine.Engine.createSession(Engine.java:137) ~[h2-1.4.196.jar:1.4.196]
    at org.h2.engine.Engine.createSession(Engine.java:27) ~[h2-1.4.196.jar:1.4.196]
    at org.h2.engine.SessionRemote.connectEmbeddedOrServer(SessionRemote.java:354) ~[h2-1.4.196.jar:1.4.196]
    at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:116) ~[h2-1.4.196.jar:1.4.196]
    at org.h2.jdbc.JdbcConnection.<init>(JdbcConnection.java:100) ~[h2-1.4.196.jar:1.4.196]
    at org.h2.Driver.connect(Driver.java:69) ~[h2-1.4.196.jar:1.4.196]

这发生在SpringApplicatio.run上下文中。之前我发现没有机会检查数据库是否已损坏,如果是,请删除数据库。

答案 1 :(得分:0)

可以覆盖DataSource bean并检查数据库文件

@Bean
@Primary // this will override the datasource autoconfiguration and use your own everywhere
public DataSource dataSource() {
    // Open Connection
    // Check Database
    // Close Connection
    // IF File corrupted delete files
    // create regular data source
}