Grails 2 multiple dynamic datasources in services

前端 未结 4 1001
情歌与酒
情歌与酒 2020-12-14 22:37

I am working on a Grails application where I must access several datasources. The datasources are defined in the default database (ie. they are stored there and I must make

相关标签:
4条回答
  • 2020-12-14 22:58

    I worked on similar project where the application has to retrieve list of datasources (connection strings) from the default database, and connect to each datasource and perform operations using quartz jobs.

    I implemented it like, connect to each datasource within the application (not from DataSorce.groovy) and write SQL rather tahn HQL.

    import groovy.sql.Sql
    
    class SqlService{
        Sql getDbConnection(String connectionString, String dbUser, String dbPassword){
            def sql = Sql.newInstance(connectionString, dbUser, dbPassword, "driver_class")
            return sql
        }
    }
    

    Get sql connection from the above code and execute SQL queries using sql.execute "SQL STATEMENT" and close the sql connection. Here is the Sql class documentation.

    0 讨论(0)
  • 2020-12-14 23:09

    Use sharding plugin for grails that will address your issue

    0 讨论(0)
  • 2020-12-14 23:10

    You can add multiple data sources in a single application, and access them in the services.

    Firstly you need to add basic data sources in the resources.groovy.

    first import BasicDataSource

    import org.apache.commons.dbcp.BasicDataSource;
    

    Then

        switch (grails.util.GrailsUtil.environment) {
        case "development":
            firstDataSource( BasicDataSource ) {
                driverClassName = "net.sourceforge.jtds.jdbc.Driver"
                url = "jdbc:jtds:sqlserver://localhost:1433;DatabaseName=<Db_name>"
                username = "sa"
                password = "root"
                String SqlServerInstance = "SQLEXPRESS";
                url = url + ";" + SqlServerInstance;
            }
            break
    
        case "test":
            firstDataSource( BasicDataSource ) {
    
                driverClassName = "net.sourceforge.jtds.jdbc.Driver"
                url = "jdbc:jtds:sqlserver://localhost:1433;DatabaseName=<Db_name>"
                username = "sa"
                password = "root"
                String SqlServerInstance = "SQLEXPRESS";
                url = url + ";" + SqlServerInstance;            }
            break;
    
    }
    

    In the same way you can add more data sources, above code will give you one more datasource to access other than the default one. I used switch to configure same data source for the different environments, same way more can be added.

    and in the service it can be accessed in the services as:

    BasicDataSource firstDataSource;
    Connection con = firstDataSource.getConnection();
    

    and then connection object can be used.

    I think it should help

    0 讨论(0)
  • 2020-12-14 23:12

    I've got two different datasources working with Grails 2.3.11. I'm using 1 datasource for my H2 database and another for an Oracle db. I had to use Hibernate 4 with Grails 2.3. In my BuildConfig.groovy I specified the dependency on hibernate 4:

    runtime ":hibernate4:4.3.5.4"
    

    In my DataSource.groovy file I used the following Hibernate caching settings:

    hibernate {
        cache.use_second_level_cache = true
        cache.use_query_cache = false
        cache.region.factory_class = 'org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory'
        singleSession = true // configure OSIV singleSession mode
    }
    

    (SIDE NOTE: without the cache settings, I was getting following CacheManager error, "Another unnamed CacheManager already exists in the same VM". There's an open bug report on this at https://jira.grails.org/browse/GPCACHEEHCACHE-13, but once I put the settings in place the error was gone.)

    then I defined my datasources:

    environments {
        development {
            dataSource_oracle {
                pooled = true
                dialect = org.hibernate.dialect.Oracle10gDialect
                driverClassName = 'oracle.jdbc.OracleDriver'
                username = 'user'
                password = 'pass'
                url = 'jdbc:oracle:thin:@(serverName):(port):(SID)'
                dbCreate = 'validate'
            }
            dataSource {
                dbCreate = "update"
                url = "jdbc:h2:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE"
                properties {
                   jmxEnabled = true
                   initialSize = 5
                   maxActive = 50
                   minIdle = 5
                   maxIdle = 25
                   maxWait = 10000
                   maxAge = 10 * 60000
                   timeBetweenEvictionRunsMillis = 5000
                   minEvictableIdleTimeMillis = 60000
                   validationQuery = "SELECT 1"
                   validationQueryTimeout = 3
                   validationInterval = 15000
                   testOnBorrow = true
                   testWhileIdle = true
                   testOnReturn = false
                   jdbcInterceptors = "ConnectionState"
                   defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED
                }
            }
        }
    }
    

    By default, my Domain classes use the H2 db and I specify my Oracle datasource as:

    class MyService {
    
        def dataSource_oracle
        static transactional = true
    
        def getMethod() {
            assert dataSource_oracle != null, "dataSource is null! Please check your configuration!"
            def sql = Sql.newInstance(dataSource_oracle)
            ...
        }
    }
    

    Above, I allow the dependency injection to provide the service with the oracle datasource, def dataSource_oracle. If I want to use the H2 datasource, I declare the datasource as def dataSource and allow the DI to inject my other datasource.


    I could not get the two datasources to work as specified in the documentation at http://grails.github.io/grails-doc/2.3.11/guide/conf.html#multipleDatasources. By declaring the datasources as dataSource and dataSource_lookup then using it as:

    class DataService {
       static datasource = 'lookup'
    
       void someMethod(...) {
          …
       }
    } 
    

    but I was able to get it working with the solution described above.


    0 讨论(0)
提交回复
热议问题