代码之家  ›  专栏  ›  技术社区  ›  Daniel Wosch

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

  •  0
  • Daniel Wosch  · 技术社区  · 7 年前

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

    我需要实现的目标:

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

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

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

    据我所知,如果数据库不存在,spring boot和Hibernate会在启动时自动创建db。到现在为止,一直都还不错。现在我需要检查数据库是否损坏。我考虑在数据库上执行查询,如果出现异常,我会重新创建数据库。

    数据库是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 回复  |  直到 7 年前
        1
  •  0
  •   Matthias    7 年前

    可以覆盖数据源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
    }
    
        2
  •  0
  •   Daniel Wosch    7 年前

    我尝试向spring boot应用程序添加几个侦听器,例如:

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

    但在spring应用程序的启动过程中,我从未遇到过这种侦听器。作为SpringApplication。run似乎初始化了整个spring上下文,当应用程序在SpringApplication中停止时,也不可能注入或获取配置环境来获取连接字符串。在数据库损坏时运行。

    我假设spring尝试初始化hibernate等,但由于数据库损坏,无法创建数据库连接

        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中发生。运行上下文。之前,我没有机会检查数据库是否损坏,如果损坏,请删除数据库。