如果Hibernate数据库连接失败,则在Grails中捕获启动异常

时间:2014-01-02 17:43:46

标签: java spring hibernate grails gorm

我们正在使用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'
} 

1 个答案:

答案 0 :(得分:2)

  

我们尝试了上面的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
  }
}