Dana Leaman
Dana Leaman

Reputation: 125

In Grails, how can I get a reference to the datasource used by a particular class?

In the project I'm working on (in Grails 2.5.4/Hibernate 4.3) I have a bunch of different classes, using a few different dataSources. I need to determine whether two given Class objects use the same dataSource. What I would like to do is something like:

Boolean doDataSourcesMatch(Class a, Class b)
{
  return a.mapping.datasource == b.mapping.datasource
}

But of course that doesn't work since a.mapping is a closure. Does anyone know how to access the dataSource used by a class? I don't need to know any of the properties of the connection, just whether queries on the two classes will use the same connection.

Many thanks!

Upvotes: 1

Views: 1040

Answers (1)

V H
V H

Reputation: 8587

Although none of these spell anything concrete out, they may help:

  1. http://grails.1312388.n4.nabble.com/How-can-I-get-the-column-name-that-a-property-maps-to-for-a-domain-class-td4633766.html

  2. How to get the name of the table GORM object is mapped to?

I haven't found anything specific, but this is all rather strange. I mean you already know and I presume this is some dynamic query otherwise you coding it would know what to query together etc.

Anyhow as a workaround, unsure if it can be since it depends on how many domainClasses we are talking about, and if this is something you have already put in place or thinking of writing up i.e nothing written in either case if you could add your own getter to all the domain classes in question

//
static String getDataSrc() {
  return 'data_source_a'
}

//or
static boolean canQuery() {
  return true/false
}

You could just check from anywhere something like this:

boolean canQuery = UserAttributes.canQuery()
String currentDataSource = UserAttributes.dataSrc

Since they are static methods, no instantiation is required. This means if you have

userObject(1) you don't need to do:

User user = User.get(1)
if (user.canQuery()) {
 // this is ok
} 

You can just call out the method directly from anywhere By referencing the upperCase class name and its method.

String currentDataSource = UserAttributes.dataSrc
//Where this is exactly the same as above
String currentDataSource = UserAttributes.getDataSrc()

E2A: The answer is:

import org.grails.orm.hibernate.cfg.GrailsDomainBinder

class TestController {
 //either this method
def binder = new org.grails.orm.hibernate.cfg.GrailsDomainBinder().getMapping(Photos.class)
        println "binder : ${binder.table.name}"
        println "b: ${binder.datasources}"

//Or this
        def dc=GrailsDomainBinder.getMapping(Photos.class)

        println "-dc is ${dc}"
        println "${dc.datasources}"
}

dc.datasources

is a list so you need to compare lists.

Of course silly me, if you are querying something like in HQL where you are giving dynamic table names ${tableA} ${tableB}

You will need to access actual domain class to be able to call GrailsDomainBinder

So something like: def domainClass = grailsApplication.getDomainClass(domain).clazz

would give you your actual domainClass for a given tableName. But your domain would have to be a fully qualified packaged name so that will cause you issues again. If you querying com.domain.users.tableA and com.domain.info.tableB

So You could instead use If outside of service/controller):

def domainClass=Holders.grailsApplication?.domainClasses?.find { it.clazz.simpleName == tableName }?.clazz

or without Holders if you are declaring grailsApplication in controller service:

def domainClass=grailsApplication?.domainClasses?.find { it.clazz.simpleName == tableName }?.clazz

Upvotes: 2

Related Questions