如何在Grails 3中的普通groovy类中访问数据源?

时间:2018-08-23 11:03:55

标签: grails grails-3.3

我正在尝试从普通Groovy类内部运行sql代码(无服务)。 在Grails 2中,我可以通过执行以下操作访问数据源:

 public GroovyClass() {
    def ctx = ServletContextHolder.servletContext.getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT)
    def dataSource = ctx.getBean('dataSource')
    sql = new Sql(dataSource)
 }

迁移到Grails 3.3.8后,该代码不再起作用。 Grails 3.3.8中正确的方法是什么?

2 个答案:

答案 0 :(得分:2)

“好莱坞原则”说:“不要打电话给我们,我们会打电话给您”,这就是依赖注入的含义。就您而言,不要去拿dataSource,不要给dataSource

有很多方法可以做到这一点。参见位于https://github.com/jeffbrown/asdudemo的项目。

https://github.com/jeffbrown/asdudemo/blob/master/src/main/groovy/ascudemo/helpers/FirstGroovyClass.groovy

// src/main/groovy/ascudemo/FirstGroovyClass.groovy
package ascudemo.helpers

import groovy.sql.Sql
import groovy.util.logging.Slf4j
import org.springframework.beans.factory.InitializingBean

import javax.sql.DataSource

@Slf4j
class FirstGroovyClass implements InitializingBean {
    DataSource dataSource
    Sql sql

    void logSomeInfo() {
        // both have been initialized
        log.debug "dataSource: ${dataSource}"
        log.debug "sql: ${sql}"
    }

    @Override
    void afterPropertiesSet() throws Exception {
        sql = new Sql(dataSource)
    }
}

https://github.com/jeffbrown/asdudemo/blob/master/src/main/groovy/ascudemo/helpers/SecondGroovyClass.groovy

// src/main/groovy/ascudemo/SecondGroovyClass.groovy
package ascudemo.helpers

import groovy.sql.Sql
import groovy.util.logging.Slf4j

import javax.annotation.PostConstruct
import javax.sql.DataSource

@Slf4j
class SecondGroovyClass {
    DataSource dataSource
    Sql sql

    void logSomeInfo() {
        // both have been initialized
        log.debug "dataSource: ${dataSource}"
        log.debug "sql: ${sql}"
    }

    @PostConstruct
    void initSql() throws Exception {
        sql = new Sql(dataSource)
    }
}

https://github.com/jeffbrown/asdudemo/blob/master/src/main/groovy/ascudemo/helpers/ThirdGroovyClass.groovy

// src/main/groovy/ascudemo/SecondGroovyClass.groovy
package ascudemo.helpers

import groovy.sql.Sql
import groovy.util.logging.Slf4j
import org.springframework.beans.BeansException
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware

import javax.sql.DataSource

@Slf4j
class ThirdGroovyClass implements ApplicationContextAware {
    Sql sql

    void logSomeInfo() {
        // sql been initialized
        log.debug "sql: ${sql}"
    }

    @Override
    void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        DataSource dataSource = applicationContext.getBean('dataSource', DataSource)
        sql = new Sql(dataSource)
    }
}

https://github.com/jeffbrown/asdudemo/blob/master/grails-app/controllers/ascudemo/DemoController.groovy

// grails-app/controllers/ascudemo/DemoController.groovy
package ascudemo

class DemoController {

    SomeService someService

    def index() {
        someService.logSomeInfo()
        render 'Success'
    }
}

https://github.com/jeffbrown/asdudemo/blob/master/grails-app/services/ascudemo/SomeService.groovy

// grails-app/services/ascudemo/SomeService.groovy
package ascudemo

import ascudemo.helpers.FirstGroovyClass
import ascudemo.helpers.SecondGroovyClass
import ascudemo.helpers.ThirdGroovyClass

class SomeService {

    FirstGroovyClass firstGroovyBean
    SecondGroovyClass secondGroovyBean
    ThirdGroovyClass thirdGroovyBean

    def logSomeInfo() {
        firstGroovyBean.logSomeInfo()
        secondGroovyBean.logSomeInfo()
        thirdGroovyBean.logSomeInfo()
    }
}

https://github.com/jeffbrown/asdudemo/blob/master/grails-app/conf/spring/resources.groovy

// grails-app/conf/spring/resources.groovy
import ascudemo.helpers.FirstGroovyClass
import ascudemo.helpers.SecondGroovyClass
import ascudemo.helpers.ThirdGroovyClass

beans = {
    // demonstrates one approach
    firstGroovyBean(FirstGroovyClass) { bean ->
        bean.autowire = 'byName'
    }

    // demonstrates another approach
    secondGroovyBean(SecondGroovyClass) { bean ->
        bean.autowire = 'byName'
    }

    // demonstrates a third approach
    thirdGroovyBean ThirdGroovyClass
}

运行该应用程序,然后向http://localhost:8080/demo/发送请求,这将验证所有3种方法是否都有效。

还有其他方法可以做到这一点,但我希望以上所述对您有所帮助。

祝你好运!

答案 1 :(得分:0)

我刚刚对此进行了测试,它似乎可以提供数据源

def ds = Holders.grailsApplication.mainContext.getBean('dataSource')
println "DataSource: ${ds}"  ---> DataSource: org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy@5e91ade8

没有尝试对其进行任何操作,但是看起来不错。