Подтвердить что ты не робот

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

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

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

Проблема № 1

  • Когда я регистрирую источник данных beans, они появляются там, где я ожидаю, но Grails их не забирает.

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

// 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]

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

Проблема №2

  • Если я объявляю все свои источники данных как часть файла Datasource.groovy, тогда я могу выполнять операции во всех моих базах данных, но не как рекламируется документация

Он работает, если я статично сопоставляю объекты моего домена:

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

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


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

  • попытался добавить динамические источники данных и преуспеть?

  • переключается между источниками данных с использованием сервисов grails?

  • (и это было бы фантастическим дополнением, так как "вишня сверху" ) имела успех с использованием нескольких источников данных с spring ядром безопасности? Как переключить источник данных для плагина безопасности?

Спасибо

-

4b9b3361

Ответ 1

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

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

Ответ 2

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

runtime ":hibernate4:4.3.5.4"

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

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-13, но как только я установил настройки, ошибка исчезла.)

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

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

По умолчанию в моих классах домена используется db 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#multipleDatasources. Объявляя источники данных как dataSource и dataSource_lookup, используя его как:

class DataService {
   static datasource = 'lookup'

   void someMethod(...) {
      …
   }
} 

но мне удалось заставить его работать с описанным выше решением.


Ответ 3

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

Во-первых, вам нужно добавить основные источники данных в ресурсы .groovy.

сначала импортировать файл 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;

}

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

и в сервисе он может быть доступен в службах следующим образом:

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

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

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

Ответ 4

Используйте плагин для гралирования, который будет решать вашу проблему