Статьи

Использование отдельных схем Postgres для одной и той же базы данных в приложении Grails

Недавно я захотел использовать ту же базу данных Postgres, но разделил свой уровень персистентности на отдельные компоненты, которые использовали разные схемы. Мотивация состояла в том, чтобы продвинуть модульный дизайн, разделить проблемы и прекратить перепутывать разработчиков. Вертикальные доменные модели могут быть труднодостижимыми, но не невозможными.

В моем приложении для покупок у меня был пользовательский компонент, торговый компонент и компонент продукта. Теперь это довольно легко, если вы используете отдельные базы данных, но иногда приятно просто разделить задачи, используя отдельные схемы в одной и той же базе данных, поскольку использование одной и той же базы данных может упростить такие вещи, как DR, доставка журналов, репликация и т. Д.

В то время как я мог найти документ для отдельных баз данных, мне было трудно найти документ Grails для совета по моей конкретной проблеме — как использовать отдельные схемы при использовании той же базы данных при использовании Postgres . Вот как я это сделал.
Вот мой источник данных.гроовый.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
String db_url = "jdbc:postgresql://localhost:5432/testdb"
String usernameVar = "db_user"
String passwordVar = "db_secret"
String dbCreateVar = "update"
String dialect = "net.kaleidos.hibernate.PostgresqlExtensionsDialect"
 
dataSource_user {
    pooled = true
    jmxExport = true
    dialect = dialect
    driverClassName = "org.postgresql.Driver"
    username = usernameVar
    password = passwordVar
    url = platform_url
    dbCreate= "validate"
}
 
hibernate_user {
    cache.use_second_level_cache = false
    cache.use_query_cache = false
    cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory' // Hibernate 3
    singleSession = true // configure OSIV singleSession mode
    default_schema = "user"
}
 
dataSource_shopping {
    pooled = true
    jmxExport = true
    dialect = dialect
    driverClassName = "org.postgresql.Driver"
    username = usernameVar
    password = passwordVar
    url = platform_url
    dbCreate = "validate"
}
 
hibernate_shopping {
    cache.use_second_level_cache = false
    cache.use_query_cache = false
    cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory' // Hibernate 3
    singleSession = true // configure OSIV singleSession mode
    default_schema = "shopping"
}
 
dataSource_product {
    pooled = true
    jmxExport = true
    dialect = dialect
    driverClassName = "org.postgresql.Driver"
    username = usernameVar
    password = passwordVar
    url = platform_url
    dbCreate= "validate"
}
 
hibernate_product {
    cache.use_second_level_cache = false
    cache.use_query_cache = false
    cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory' // Hibernate 3
    singleSession = true // configure OSIV singleSession mode
    default_schema = "product"
}

Примечание: в конфиге есть несколько очевидных оптимизаций, но приведенное выше просто упрощает объяснение.

Затем я сопоставил каждый объект GORM с соответствующей схемой.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Cart {
    // ...
    // ...
    static mapping = {
        datasource 'shopping'
        // ...
    }
}
 
class Address {
    // ...
    // ...
 
    static mapping = {
        datasource 'user'
    }
}
 
class Stock {
    // ...
    // ...
 
    static mapping = {
        datasource 'product'
    }
}

Затем я запустил свое приложение и сказал: «Да, это работает», немного перекусил и перешел к следующей проблеме. Как видно, хитрость заключается в том, чтобы использовать отдельное закрытие гибернации, указать там схему и назвать закрытие, используя тот же формат именования для отдельной базы данных, но сделать так, чтобы закрытия базы данных указывали на одну и ту же базу данных.