Kyle
Kyle

Reputation: 167

Grails multiple DBs - use services to select the datasource does not work

I have tried asking this in another question, but I may have put too many details.

I am using Grails and multiple datasources. If you want to use services to declare the datasource, that does NOT work at all for me.

static datasource = "db1"

No matter what, this has not worked for me in Grails Services

Thank you for any help/suggestions.

== I am editing this to include my Datasource.groovy

Now, this works fine if I use the static mapping on the domain object for my second database. However, I want the service to decide what database must be written to, therefore I was hoping that the service datasource attribute works as in the documentation.

  1. If I declare that my domain object uses "ALL" datasources, the service will write to the default datasource, despite the fact that I set the

    static datasource = "db21"

  2. If I declare that my domain object uses "db1" datasource, the service will write to the db1 datasource

    1. If I declare 2,3...N datasources, it looks like the service will only write to the default datasource or the datasource I had declared in the domain groovy file. The documentation says I should be able to use services to choose the datasource.

=============== edit ==============

dataSource {
    pooled = true
    driverClassName = "org.h2.Driver"
    username = "sa"
    password = ""
}

hibernate {
    cache.use_second_level_cache = true
    cache.use_query_cache = true
    cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory'
}
// environment specific settings
environments {
    development {
        dataSource {
            dbCreate = "validate"
            url = "jdbc:h2:devDb;MVCC=TRUE"
        }
    dataSource_db1 {
        dbCreate = "validate"
        url = "jdbc:h2:dev1Db;MVCC=TRUE"
        pooled = true
        driverClassName = "org.h2.Driver"
        username = "sa"
        password = ""
    }
    }
    test {
        dataSource {
            dbCreate = "update"
            url = "jdbc:h2:mem:testDb;MVCC=TRUE"
        }
    }
    production {
        dataSource {
            dbCreate = "update"
            url = "jdbc:h2:prodDb;MVCC=TRUE"
            pooled = true
            properties {
               maxActive = -1
               minEvictableIdleTimeMillis=1800000
               timeBetweenEvictionRunsMillis=1800000
               numTestsPerEvictionRun=3
               testOnBorrow=true
               testWhileIdle=true
               testOnReturn=true
               validationQuery="SELECT 1"
            }
        }

    }
}

Upvotes: 2

Views: 1627

Answers (1)

EricD
EricD

Reputation: 67

We have used multiple datasources in our Grails applications and have had success switching the datasource in the Service using the approach that you indicated above...

static datasource = "db1"

However, the difference is that in all of our domain objects we have defined which datasource the domain object belongs to. I am not sure if it is possible to do without defining the non-default datasource in the mapping.

static mapping = { datasource 'db1' }

In some cases, we will have 2 different domain classes that have the same name but point to different datasources. In order to keep this clean, we will put the 2 domain classes in different packages and the service that uses those domain classes/datasources in the same package.

for example...

//Domain Classes
package com.yourcompany
class Student {
    static mapping = {
       //if you don't indicate the datasource it will use the default                      
    }
}

package com.yourcompany.db1
class Student {
    static mapping = {
       datasource 'db1'                     
    }
}

//Services
package com.yourcompany
class DefaultDbService {
   def getStudents() {
      //This will query the default datasource           
      Student.findAll()
   }
}

package com.yourcompany.db1
class Db1Service {
   static datasource = "db1"

   def getStudents() {
       //This will query the 'db1' datasource           
       Student.findAll()
   }
}

You might try this approach and see if it gets you the result that you are looking for.

Upvotes: 1

Related Questions