【问题标题】:Catch startup exception in Grails if Hibernate database connection fails如果 Hibernate 数据库连接失败,则在 Grails 中捕获启动异常
【发布时间】:2014-01-02 17:43:45
【问题描述】:

我们正在使用 Grails 2.0.4、GORM 和 Hibernate 构建应用程序。当数据库不可用时,Grails 不会初始化,启动失败。我们认为我们的池设置可以防止启动失败,但事实并非如此。

如果单独的池设置不能解决这个问题,是否可以在resources.groovy 中捕获异常,如果无法初始化数据库服务,则暂时切换到基于文件的服务?像这样的...

resources.groovy

try{

   myDataService(PostgresDatabaseServiceImpl){}

}catch(Exception e){
   //if database connect failed, use local service instead
   myDataService(FileBasedServiceImpl){}
}

即使以上是可能的,它也会产生一个新的问题;一旦数据库可用,如何动态切换回来。我们尝试了上面的 try/catch,但没有任何影响,启动问题仍然存在:

创建名为“transactionManagerPostProcessor”的 bean 时出错: bean初始化失败

如果仅通过池设置就可以避免启动失败,我们当然可以在应用程序尝试使用错误的数据库连接时在运行时管理 SQL 异常,但我们无法管理启动失败。

DataSource.groovy(池设置)

dataSource {
    pooled = true
    driverClassName = "org.postgresql.Driver"
    properties {
       maxActive = 20
       minEvictableIdleTimeMillis=1800000
       timeBetweenEvictionRunsMillis=1800000
       numTestsPerEvictionRun=3
       testOnBorrow=true
       testWhileIdle=true
       testOnReturn=true
       validationQuery="SELECT 1"
    }
}
hibernate {
    cache.use_second_level_cache = false
    cache.use_query_cache = false
    cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory'
} 

【问题讨论】:

    标签: java spring hibernate grails grails-orm


    【解决方案1】:

    我们尝试了上述 try/catch,但没有任何影响,启动问题仍然存在:

    所以您似乎已经回答了是否可以在resources.groovy 中为(可能)不可用的数据库注册 Spring bean。

    作为替代方案,您可以尝试在运行时为数据库注册一个 Spring bean。这种方法的优势在于,即使注册 bean 失败,您也可以捕获错误并改用基于文件的服务。如何在运行时注册 DataSource bean 的示例是 show here

    要使用这种方法,只需在 resources.groovy 中为基于文件的服务注册一个 bean

    myDataService(FileBasedServiceImpl)
    

    那么当你需要访问数据源时:

    class DataSourceService implements ApplicationContextAware {
    
      def myDataService
      ApplicationContext applicationContext
    
      private static PG_BEAN = 'postgres'
    
      def getDataSource() {
    
        try {
          getPostgresService()
    
        } catch (ex) {
          myDataService
        }
      }
    
      private getPostgresService() {
        def postgres
    
        if (applicationContext.containsBean(PG_BEAN)) {
          postgres = applicationContext.getBean(PG_BEAN)
    
        } else {
          // register a bean under the name 'postGres' and store a reference to it in postgres
          // https://stackoverflow.com/a/20634968/2648
        }            
    
        checkPostgres(postgres)
      }
    
      private checkPostres(postgresBean) {
        // check that the database is available, throw an exception if it's not, return 
        // postgresBean if it is
      }
    }
    

    【讨论】:

    • 这看起来很有趣,应该可以解决我的问题,会尝试一下,
    • 这已经过时了,但我很想知道它是如何工作的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 2018-06-03
    • 2019-03-24
    • 1970-01-01
    相关资源
    最近更新 更多