Grails 2 множественных динамических источника данных в сервисах

Я работаю над приложением Grails, где мне нужно получить доступ к нескольким источникам данных. Источники данных определены в базе данных по умолчанию (т.е. они хранятся там, и я должен позвонить в базу данных по умолчанию, чтобы получить список имен источников данных, к которым я должен подготовиться для подключения). Когда сервер загружается, я извлекаю список баз данных, создаю компоненты источника данных и внедряю их. Все динамически добавленные базы данных структурно идентичны (т. Е. Имеют одинаковую структуру таблицы и объекта домена).

Этот вопрос ближе всего к полезному коду, но это не совсем то, что мне нужно.

Issue #1 When I register the datasource beans, they show up where I expect, but Grails does not pick them up.

Вот как я их добавляю:

// Register datasource bean
def beanName = 'dataSource_devDB1'

BeanBuilder bb = new BeanBuilder()
bb.beans {
    "${beanName}"(BasicDataSource) { 
        url = "jdbc:h2:devDB1Db;MVCC=TRUE"
        pooled = true
        driverClassName = "org.h2.Driver"
        username = "sa"
        password = ""            
    }
}

bb.registerBeans(grailsApplication.mainContext)

// check that it registered
def ctx = grailsApplication.mainContext
def ctxlist = ctx2.beanDefinitionNames.findAll{it.contains( 'dataSource' )}

log.info "ctxlist = " + ctxlist

Это печатает:

[dataSource, dataSourceUnproxied, dataSource_devDB1]

Когда я делаю это, я могу выполнять операции с источником данных по умолчанию, и это все.

Issue #2 If I declare all my datasources as part of the Datasource.groovy file, then I can execute operations on all my databases, but not as advertised by the documentation

Это работает, если я делаю статическое отображение на моих объектах домена:

static mapping = {datasources(['devDB1', 'devDB2', 'DEFAULT')] or datasource = 'ALL'

но я хочу выполнить все это как часть службы и объявить объекты моего домена для использования ВСЕХ источников данных.

Объявление источника данных в службе не работает:

class secureDBService{

  static datasource = "devDB1"

  def readWriteMethod(){
   .....
  // this always uses the default datasource ignoring the static property above.
  // the only time it uses devDB1 is if I declare it as part of the domain datasource
  // mapping
  }
}

Это всегда будет использовать источник данных по умолчанию, несмотря ни на что. Единственный раз, когда он использует правильный источник данных, это если в доменном объекте я перечисляю соответствующий источник данных.

Итак, есть кто-нибудь:

tried adding dynamic datasources and succeeded?

switched between datasources using grails services?

(and this would be a fantastic extra , as a "cherry on top") had success using multiple datasource with spring security core? How do you switch the datasource for the security plugin?

Спасибо

--

 Sérgio Michels06 дек. 2012 г., 14:47
Ты это решил?
 Thomas Farvour23 сент. 2013 г., 05:27
Мне также нужна помощь по очень похожему сценарию.
 Lalit Agarwal03 июл. 2014 г., 09:43
@ Kyle Удалось ли решить проблему переключения источников данных в сервисах Grails?
 Kyle04 июн. 2012 г., 19:17
На данный момент я почти согласен на то, что кто-то скажет мне, что они успешно запустили Grails в мультитенантном режиме (с несколькими источниками данных), используя службы Grails для определения БД. Кто угодно? Если да, то как?
 moskiteau20 мар. 2013 г., 14:24

Ответы на вопрос(3)

в котором приложение должно получать список источников данных (строк подключения) из базы данных по умолчанию, подключаться к каждому источнику данных и выполнять операции с использованием кварцевых заданий.

Я реализовал это, как, подключиться к каждому источнику данных в приложении (не из DataSorce.groovy) и писать SQL, а не 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
    }
}

Получитьsql соединение из приведенного выше кода и выполнение SQL-запросов с помощьюsql.execute "SQL STATEMENT" и закройsql соединение.Во этоSql учебная документация.

лучать к ним доступ в службах.

Сначала вам нужно добавить основные источники данных в resources.groovy.

first import BasicDataSource

import org.apache.commons.dbcp.BasicDataSource;

Зате

    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;

}

Так же, как вы можете добавить больше источников данных, приведенный выше код предоставит вам еще один источник данных для доступа, отличный от источника по умолчанию. Я использовал switch для настройки одного и того же источника данных для разных сред, таким же образом можно добавить больше.

и в сервисе он может быть доступен в сервисах как:

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

и тогда можно использовать объект подключения.

Думаю, это должно помочь

 Thomas Farvour20 сент. 2013 г., 22:02
Это не поможет ответить на исходный вопрос. Ему нужно динамически создавать бины источника данных из другого соединения с базой данных, а не из простого файла. У меня та же проблема. Не похоже, что у Grails есть хороший «дружественный» способ перезагрузки доменных классов с bean-компонентами dataSource основного контекста. Надеюсь, кто-нибудь ответит на наши вопросы.
 Saurabh Dixit21 сент. 2013 г., 06:26
хммм может быть .. я думал, что это может помочь .. потому что публиковать все это в комментариях было бы неуместно ..

работающих с Grails 2.3.11. Я использую один источник данных для моей базы данных H2 и другой для базы данных Oracle. Мне пришлось использовать Hibernate 4 с Grails 2.3. В моемBuildConfig.groovy Я указал зависимость от спящего режима 4:

runtime ":hibernate4:4.3.5.4"

В моемDataSource.groovy файл Я использовал следующие настройки кэширования Hibernate:

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
}

(Боковое примечание: без настроек кэша я получаю следующую ошибку CacheManager: «В той же виртуальной машине уже существует другой безымянный CacheManager». Наhttps: //jira.grails.org/browse/GPCACHEEHCACHE-1, но как только я установил настройки на место, ошибка исчезла.)

затем я определил свои источники данных:

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
            }
        }
    }
}

По умолчанию, мои классы Домена используют базу данных H2, и я указываю свой источник данных Oracle как:

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)
        ...
    }
}

Выше я разрешаю внедрение зависимостей для предоставления сервиса с источником данных oracle,def dataSource_oracle. Если я хочу использовать источник данных H2, я объявляю источник данных какdef dataSource и разрешить DI ввести другой источник данных.

Я не смог заставить работать два источника данных, как указано в документации вhttp: //grails.github.io/grails-doc/2.3.11/guide/conf.html#multipleDatasource. Объявляя источники данных как dataSource и dataSource_lookup, затем используя их как:

class DataService {
   static datasource = 'lookup'

   void someMethod(...) {
      …
   }
} 

но Я смог заставить его работать с решением, описанным выше.

Ваш ответ на вопрос