Grails Service无法创建Sql实例

时间:2017-09-25 20:13:18

标签: grails groovy

如何在不使用dataSource或GORM Hibernate相关的任何内容的情况下在Grails服务中创建类groovy.sql.Sql的实例?在我的Grails应用程序中,当我尝试创建一个Sql实例时,在我的Service类中,我得到一个异常:

Caused by: java.lang.ClassNotFoundException: org.postgresql.Driver
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    at java_lang_ClassLoader$loadClass$1.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
    at com.tav.admin.DbService.copyFileToTable(DbService.groovy:87)

似乎是一个类加载问题。这是服务方法。

long copyFileToTable(String sql, FileReader fileReader) {

    println("System Class Loader: ${ClassLoader.getSystemClassLoader().getClass().getName()}")
    println("Groovy Class Loader: ${Thread.currentThread().getContextClassLoader().getClass().getName()}")
    Thread.currentThread().getContextClassLoader().loadClass(driverClassName)
    ClassLoader.getSystemClassLoader().loadClass(driverClassName) // Note throws exception here!

    props = new Properties()
    props.setProperty('user', username)
    props.setProperty('password', password)
    PgConnection copyOperationConnection = (PgConnection) Sql.newInstance(url, props, driverClassName)
    CopyManager copyManager = new CopyManager(copyOperationConnection)
    return copyManager.copyIn(sql, fileReader)
}

输出:

System Class Loader: sun.misc.Launcher$AppClassLoader
Groovy Class Loader: groovy.lang.GroovyClassLoader

PostgreSQL驱动程序已在DriverManager中注册。我可以在我的服务中使用注入的dataSource但是我需要创建与GORM Hibernate无关的数据库的新连接以使用驱动程序特定的功能(PostgreSQL CopyManager)。

在DriverManager.isDriverAllowed()

Class.forName(driver.getClass().getName(), true, classLoader);

返回null。

版本信息:Grails 2.5.1,Java jdk1.7.0_79,Groovy 2.0.6

我已将问题缩小到下面的代码行:

ClassLoader.getSystemClassLoader().loadClass(driverClassName) // Note throws exception here!

似乎Groovy / Grails使用GroovyClassLoader加载JDBC驱动程序,但是当您尝试从DriverManager.getConnection()获取连接时,驱动程序管理器尝试使用System Class Loader加载JDBC驱动程序。系统类加载器似乎没有意识到Groovy类加载器已经加载了类。就像DriverManager和System Class加载器一样,远离Groovy加载的类。

2 个答案:

答案 0 :(得分:1)

在我的情况下,我有相同的情况(使用没有GORM的Sql)但使用MySQL。

我在 resources.groovy

声明了一个dataSource bean
beans{
   "otherDataSource"(BasicDataSource) {
      driverClassName = 'com.mysql.Driver'
      username = 'xxx'
      password = 'xxxx'
      url = 'jdbc:blablabla'
   }
}

并将其注入服务

class MyService{
    def otherDataSource
    void doIt(){
        def sql = new Sql(otherDataSource)
    }
}

答案 1 :(得分:0)

为了与PostgreSQL接口,您需要在类路径中有一个合适的驱动程序,如堆栈跟踪所示。

你需要包含一个依赖项或一个捆绑在jar中的外部库,它将为你提供一个实现`javax.sql。*'的包。接口