How to get data from another data base in runtime - grails

I need an optimal way to change Database in run-time, whether from hibernate or from JNDI or another. I need to change the database when a user clicks on a specific button (Change dependencies on events).

If you are running Grails 1.3.x you can to use the Burt Beckwith's Datasources plugin, in Grails 2.x that feature has been added to core.
Then you can to use a parameter to pass database connection name
def database = params.database
if(!database) database = "default"
and to use Groovy dynamic method invocation to call it
def zipCode = ZipCode.'${database}'.get(42)
…
zipCode.'${database}'.save()

Related

Way to get db field data generic type without adding it to my grails domain class?

I'm working with a grails project which uses a large 3rd party database with numerous tables and numerous fields in each table. We have taken the approach of adding these fields to our domain classes manually on an as-needed basis.
I'm at a point where I'd like systematic access to all of the fields and I'm wondering if there's a way to do this without adding them to my domain class. For example, if I know the column name, I'd like to know the datatype in the database (i.e., whether it's a string, double, int, bool, date).
I don't need programmatic access to the fields because I can interact with these tables using a REST api provided by the 3rd party vendor. I'd just like to know if I can determine what datatype they're expecting.
I found that grails has a reverse engineering plugin, but I'm not sure that's what I want because I don't want to create a domain class, I just want something like:
// this is what I work for fields I've added to the domain class
Type works = MyDomainClass.getDeclaredField("declaredFieldName").genericType
// is there a way to do this without adding it to the domain class?
Type needed = someAPI(MyDomainClass,"unDeclaredFieldName")
Check out the hibernate tools that the reverse engineering plugin is using. Specifically, it creates a DatabaseCollector:
DatabaseCollector readDatabaseSchema(String catalog, String schema) {
catalog = catalog ?: settings.defaultCatalogName
schema = schema ?: settings.defaultSchemaName
JDBCReader reader = JDBCReaderFactory.newJDBCReader(cfg.properties, settings,revengStrategy, cfg.serviceRegistry)
DatabaseCollector dbs = new MappingsDatabaseCollector(mappings, reader.metaDataDialect)
reader.readDatabaseSchema dbs, catalog, schema, new ReverseEngineerProgressListener()
dbs
}
I think you can just use straight SQL for instance
SELECT DATA_TYPE FROM all_tab_columns WHERE table_name = 'TABLE NAME' AND column_name = 'COLUMN NAME'
And you can call SQL directly from Groovy sql http://docs.groovy-lang.org/latest/html/api/groovy/sql/Sql.html

Auto generated values in Grails domain class

Is there a way to add my own auto generated field to domain like id and version , If yes the please guide me . provide me URL form where i can read and under stand the core concept of Grails and Domain specific language .
use install-template in the app to get all default templates:
grails install-template
after which you would be able to see /src/templates (newly created)
Modify DomainClass.groovy under /src/templates/artifacts as below:
#artifact.package#class #artifact.name# {
//according to your need
Long myId
Integer myVersion
static constraints = {
}
}
Done!!!!
Henceforth, when create-domain-class command is used to create a domain class, those fields will be auto populated.
I am not sure I am understanding your question correctly but here is the link to the web features of Grails documentation. The "Link Generation API" may be something you are asking after.
If you would like to manage ID and version than using Spring Security (plugin or full docs) or SQL features may be the direction you want to read more about.
EDIT: Try this Stackoverflow question and answer on using inheritance. Seems to be very similar to what you are asking.
You would need to write an AST transform to inject the fields you want to add automatically. The one that injects ‘id’ and ‘version’ can be found here as an example:
https://github.com/grails/grails-core/blob/master/grails-core/src/main/groovy/org/codehaus/groovy/grails/compiler/injection/DefaultGrailsDomainClassInjector.java
You would then need to write a GORM event listener to automatically update the values of these properties. See
https://github.com/grails/grails-data-mapping/blob/master/grails-datastore-gorm/src/main/groovy/org/grails/datastore/gorm/events/AutoTimestampEventListener.java
For an example of the one that updates the dateCreated/lastUpdated properties.
These can both be written in a separate Gradle/Maven project which you then reference in the dependencies of your BuildConfig.groovy file.

Grails and hsqldb

I was wondering how to persist data to a hsqldb. For example I am trying to save a simple name to a database but I cant seem to figure out how to persist it.
The recommended approach is to create a domain class with a String name property. Then you can save it, and you're done. First, create the domain class:
$ grails create-domain-class com.foo.Person
Then edit the grails-app/domain/com/foo/Person.groovy:
package com.foo
class Person {
String name
}
In controller actions or service methods you can create, save, and retrieve data:
def heMan = new Person(name: 'He Man')
if ( !heMan.save() ) {
// Handle problems saving (e.g. constraint violations)
}
def h = Person.findByName('He Man')
println h.name
An alternative approach is to work with JDBC directly. You can have dataSource bean automatically injected into your controller, then use the groovy.sql.Sql class to query that dataSource. Check out this stackoverflow.com question.
Two ways:
GORM
raw JDBC (via spring's JdbcTemplate)
I would suggest starting with a good Grails tutorial such as this one at IBM or one of these. Learn to use GORM. It will make your life better.

Grails: Use new Multiple Datasources for sharding?

I want to be able to put an object into one of several shards based on a value of a field. In milestone 2.0 I see examples like
def zipCode = ZipCode.auditing.get(42)
zipCode.auditing.save()
But how would I dynamically choose the data source. I want something more like
ZipCode.datasource(1).get(42) // where 1 is calculated based on some other value.
Is there anyway to do that?
See http://grails.org/plugin/sharding which uses the Datasources plugin. The new multiple-datasources support in Grails is the result of moving the Datasources plugin into core, so it should be straightforward to either update the plugin or borrow its code and adapt it.

Is it possible to use a JNDI dataSource read only in Grails?

I need to add a JNDI datasource from a legacy database to my Grails (1.2.2) application.
So far, the resource is added to my Tomcat (5.5) and DataSource.groovy contains:
development {
dataSource {
jndiName = "jdbc/lrc_legacy_db"
}
}
I also created some domain objects mapping the different tables to comfortably load and handle data from the DB with GORM. But I now want to assure, that every connection to this DB is really read-only. My biggest concern here is the dbCreate- property and the automatic database manipulation through GORM and the GORM classes.
Is it enough to just skip dbCreate?
How do I assure that the database will only be read and never ever manipulated in any way?
You should use the validate option for dbCreate.
EDIT: The documentation is quite a bit different than when I first posted this answer so the link doesn't quite get you to where the validate option is explained. A quick find will get you to the right spot.
According to the Grails documentation:
If your application needs to read but never modify instances of a persistent class, a read-only cache may be used
A read-only cache for a domain class can be configured by
1. Enable Caching
Add something like the following to DataSource.groovy
hibernate {
cache.use_second_level_cache=true
cache.use_query_cache=true
cache.provider_class='org.hibernate.cache.EhCacheProvider'
}
2. Make Cache Read-Only
For each domain class, you will need to add the following to the mapping closure:
static mapping = {
cache usage:'read-only', include:'non-lazy'
}

Resources