I would like to iterate over all the available dataSources for the current environment, trying to see if any of them contain a particular domain instance. Each environment has different dataSources.
The best I've hacked up so far is grailsApplication.config.findAll { it.key.contains('dataSource_') }. Is there a better or more legitimate way to do this?
You can also query against the bean names in the application context.
Something like
ctx.beanDefinitionNames.findAll{ it.contains( 'dataSource' ) }
At least that is what the DatasourcesUtils in the Datasources plugin does -
http://plugins.grails.org/grails-datasources/trunk/src/groovy/com/burtbeckwith/grails/plugin/datasources/DatasourcesUtils.groovy
Related
I have a read-only MySql DB replica and want to use it for all select-based GORM requests and criteria all over the project (Grails 3.1.16)
Is there any beautiful way to override the default DataSource only for the part of GORM methods (e.g. get, find)?
According to the documentation, we can use a particular dataSource for domain/service or use namespace with each method call. But I am looking for a more generic mechanism.
You can use dbresolver.
For example:
db.Use(dbresolver.Register(dbresolver.Config{
Replicas: []gorm.Dialector{mysql.Open("read_only_replica")},
}))
Is there any beautiful way to override the default DataSource only for
the part of GORM methods (e.g. get, find)?
There is not.
You can configure as many datasources as you like but you can't declaratively express that one is used for reads and others are used for writes or anything like that. You could easily let one be the default and then be explicit when you want to do others. For example, SomeDomainClass.nameOfDatasourceUsedForReads.list() etc.
Ok, this is definitely my last question about Linq2DB! Maybe...
I've gotten through some of the learning curve with Linq2DB for a project that will work against DB2/iSeries data. One problem though is that while my code works against my test database just fine, in production it will need to point at different schemas for the same objects. For instance, a particular user class in one environment would have a table mapping like:
[Table(Schema="ABC", Name="USERS")]
in another environment it might look like:
[Table(Schema="XYZ", Name="USERS")]
I haven't quite figured out how I will approach this in production. Has anyone dealt with this before? Is there a way to do this with a DataContext? Or possibly by digging into the internals of the mapping? Any thoughts or ideas are appreciated!
I would recommend to use fluent mapping or configurations for your case.
For fluent mapping pass schema name to fluent mapping builder function:
void ConfigureMappings(MappingSchema ms, string schema)
{
ms.GetFluentMappingBuilder()
.Entity<Users>()
.HasSchemaName(schema)
// configure columns and other entities
}
Configuration-based solution: use different configurations for test and production environments and pass configuration name to data connection constructor:
[Table(Schema="ABC", Name="USERS", Configuration="test")]
[Table(Schema="XYZ", Name="USERS", Configuration="production")]
public class User
{...}
// or make test configuration default and override it for production where it differ from default
[Table(Schema="ABC", Name="USERS")]
[Table(Schema="XYZ", Name="USERS", Configuration="production")]
public class User
{...}
This approach (with configurations) also could be used for fluent mapper.
I have created a POC with SDN 3.3.1 in which I have deployed a plugin inside the Neo4j server. The plugin contains domain objects, repositories and controllers.
From my application, I'm making rest calls to the controllers to execute repositories methods and return the response.
The issue is that in my queries, I'm returning multiple nodes and relationships. So, to map the response, I created wrapper classes using #QueryResult, #ResultColumn containing references to domain objects for each query. This is because each query has a different result set.
Since, my application has around 150 such queries I will have to create similar number of intermediate wrapper classes.
This is quite tedious and number of wrapper classes will only increase in future as more and more queries are added.
Is there any smarter way to do this?
I tried to have all of my domain objects as references in a single wrapper class. So that I can use it for any of my queries. But it gives exception if any of the fields in the wrapper class is not present in the query result.
Another issue is that, some of my queries are written to return all different nodes connected to a particular node, e.g,
Match (a)-[rel]->(b)-[tempRel]->(tempNodes) Return b,tempRel,tempNodes
I'm not sure how to map this result set to a wrapper class.
Is there any way to achieve it without refactoring the queries to match indvidual paths?
Regards,
Rahul
Good idea to have it ignore unknown classes and fields in both directions perhaps as an additional annotation on the class can you raise a Spring JIRA issue?
something like this e.g.
#QueryResult(requireFields=false, require=false)
class MyResult {
String name;
int age;
}
but you still have them focused on one area or use-case and not 1 for all 150 use-cases but perhaps 15-30 different ones.
I tried to serialize grails domains classes to Maps or similar in order to be able to store it in memcached.
I want to be able to read the objects only, I don't need gorm crud. Only to read them without breaking the kind of interfaces they have.
For instance: I could convert domains to maps, becouse it wouldn't break the interface for access like .<property> or .findall or similar
First I tried to do a manual serialization but it was very error prone. So I needed something more general.
Then I tried to serialize as a map with a grails codec.
Here is the testing repo.
Here is the snippet.
But I get StackOverFlowException.
I also tried to mark all the domains as Serializable but I need to reattach every domain when I bring them back from memcached to avoid hibernate errors like org.hibernate.LazyInitializationException: could not initialize proxy - no Session
Do you know a way to achieve this?
Is very frustrating to google search for something like this "storing domain classes in memcached" and find out is not a common problem.
I haven't see an out-of-the-box solution for doing this, but if you wanted to keep it generic you could do it manually (and consistently) like this:
def yourDomainInst = DefaultGrailsDomainClass(YourDomainClazz)
List listOfOnlyPersistantProperties = yourDomainInst.persistantProperties
def yourNewMap
yourObjects.each { obj ->
listOfOnlyPersistantProperties.each { prop ->
def propName = prop.name
yourNewMap.put(propName, obj."$propName")
}
}
Something like that should work. Note there's probably a hundred errors because I can't try it out right now, but that is the general idea.
Have a look at: Retrieving a list of GORM persistent properties for a domain
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'
}