【问题标题】:Loading and connecting to mysql jdbc driver runtime加载并连接到 mysql jdbc 驱动程序运行时
【发布时间】:2012-05-29 06:27:01
【问题描述】:

我目前正在处理需要加载 mysql 驱动程序运行时并使用 java 连接到数据库的需求。

我正在使用URLClassLoader来加载jar文件

File f = new File("D:/Pallavi/workspace/WarInstallation/mysql-connector-java-5.0.4-bin.jar"); //Jar path

URLClassLoader urlCl = new URLClassLoader(new URL[] { f.toURL()},System.class.getClassLoader()); 
Class sqldriver = urlCl.loadClass("com.mysql.jdbc.Driver"); // Runtime loading

Driver ds = (Driver) sqldriver.newInstance(); //Compilation failing as "sqldriver" class of type Driver is not found

//I am using now java.sql.Driver to remove the compilation error

sqldriver = Class.forName("com.mysql.jdbc.Driver", true, sqldriver.getClassLoader()).newInstance(); //Runtime fail.. "Driver" Class not Found Exception.

尽管类加载良好,但无论我尝试哪种驱动程序,我都无法建立数据库连接(找不到适合的驱动程序...)。

请建议一种加载 jdbc "com.mysql.jdbc.Driver" 类运行时的方法。 如果您需要任何进一步的信息,请告诉我,因为这很紧急。

提前致谢。

【问题讨论】:

  • 类路径中有mysql jar吗?
  • 你好,我在环境变量中设置了mysql jar的classpath,需要通过系统属性设置吗?

标签: java mysql runtime


【解决方案1】:

在回答您的问题之前,我有三个问题:

  1. 声明 1

    ya, I have set the classpath of mysql jar in the environment variables, do we need to set it through system properties?

    Q1:当系统类加载器可以从类路径中轻松获得一个类时,为什么要依赖自定义类加载器?
    您不需要明确的类路径到 mysql***.jar 来使用自定义类加载器。

  2. 声明 2

    Class sqldriver = urlCl.loadClass("com.mysql.jdbc.Driver"); // Runtime loading
    //Compilation failing as "sqldriver" class of type Driver is not found
    Driver ds = (Driver) sqldriver.newInstance();

    Q2:声称 Compilation failing ... 非常矛盾。您的编译器是否正在寻找这样的类来生成您的类!?
    我确定不是。可能是错误在运行时使用java.lang.ClassNotFoundException: com.mysql.jdbc.Driver。而且我还怀疑评论应该与您的 Statement 3 放在下面。
    如果是CNFE,则您指向mysql***.jar 的文件路径错误。先修好了。

  3. 声明 3

    //I am using now java.sql.Driver to remove the compilation error
    //Runtime fail.. "Driver" Class not Found Exception. sqldriver = Class.forName("com.mysql.jdbc.Driver", true, sqldriver.getClassLoader()).newInstance();

    Q3:声称 ... "Driver" Class not Found Exception 是可疑的。因为,这个语句不会被编译。那么它怎么可能是一个运行时失败。 ..!?
    我还怀疑评论应该与您上面的 Statement 2 一起使用。
    在这里,您需要调用newInstance(),然后转换为java.sql.Driver,然后再分配给sqlDriver 变量。因为Class.forName( ... 只返回一个Class object associated with the class or interface with the given string name
    如果上述声明 2 中的问题得到修复,您可以应用此修复来进一步测试。

希望您能澄清这些陈述。


我在下面有一个工作示例代码,并为您显示了经过测试的输出。

import java.io.File; // and others as required

public class MySQLDriveClassLoader {
  public static void main( String [] args ) throws Exception {
    //File f = new File( "/home/ravinder/soft-dump/mysql-connector-java-5.1.18-bin.jar" );
    File f = new File( "E:\\Soft_Dump\\mysql-connector-java-5.0.4\\mysql-connector-java-5.0.4-bin.jar" );
    URLClassLoader urlCl = new URLClassLoader( new URL[] { f.toURI().toURL() }, System.class.getClassLoader() );

    Class mySqlDriver = urlCl.loadClass( "com.mysql.jdbc.Driver" );

    //*** Start: DEBUG *************************
    //mySqlDriver.con // On pressing CTRL+SPACEBAR, after .con, IDE shows "No default proposals"
    // meaning it still is not an instance of Driver, and hence can't call a method from Driver class.

    //Incompatible conditional operand types Class and Driver
    //System.out.println( mySqlDriver instanceof java.sql.Driver ) );

    System.out.println( "mySqlDriver: " + mySqlDriver );
    System.out.println( "Is this interface? = " + mySqlDriver.isInterface() );

    Class interfaces[] = mySqlDriver.getInterfaces();
    int i = 1;
    for( Class _interface : interfaces ) {
      System.out.println( "Implemented Interface Name " + ( i++ ) + " = " + _interface.getName() );
    } // for(...)

    Constructor constructors[] = mySqlDriver.getConstructors();
    for( Constructor constructor : constructors ) {
      System.out.println( "Constructor Name = " + constructor.getName() );
      System.out.println( "Is Constructor Accessible? = " + constructor.isAccessible() );
    } // for(...)
    //*** End  : DEBUG *************************

    Driver sqlDriverInstance = ( Driver ) mySqlDriver.newInstance();
    System.out.println( "sqlDriverInstance: " + sqlDriverInstance );

    Connection con = null;
    try {
      /******************************************************************
      // You may fail to register the above driver
      // hence don't depend on DriverManager to get Connected
      //DriverManager.registerDriver( sqlDriverInstance );
      //Driver driver = DriverManager.getDriver( "com.mysql.jdbc.Driver" ); // ( "jdbc:mysql" );
      Enumeration<Driver> enumDrivers = DriverManager.getDrivers();
      while ( enumDrivers.hasMoreElements() ) {
        Driver driver = enumDrivers.nextElement();
        System.out.println( "driver: " + driver );
      } // while drivers
      //******************************************************************/

      String dbUrl = "jdbc:mysql://:3306/test";
      Properties userDbCredentials = new Properties();
      userDbCredentials.put( "user", "root" );
      userDbCredentials.put( "password", "password" );

      // No suitable driver found for ...
      //con = DriverManager.getConnection( dbUrl, "root", "password" );

      // safely use driver to connect
      con = sqlDriverInstance.connect( dbUrl, userDbCredentials );
      System.out.println( "con: " + con );

      Statement stmt = con.createStatement();
      String sql = "select now()";
      ResultSet rs = stmt.executeQuery( sql );
      if ( rs.next() ) {
        System.out.println( rs.getString( 1 ) );
      } // if rs
    } catch( Exception e ) {
      e.printStackTrace(); // only for quick debug
    } finally {
      try { if ( con != null ) con.close(); } catch ( Exception ignoreThis ) {}
    }
  } // psvm(...)
} // class MySQLDriveClassLoader

编译运行成功,输出如下:

mySqlDriver: class com.mysql.jdbc.Driver
Is this interface? = false
Implemented Interface Name 1 = java.sql.Driver
Constructor Name = com.mysql.jdbc.Driver
Is Constructor Accessible? = false
sqlDriverInstance: com.mysql.jdbc.Driver@1270b73
con: com.mysql.jdbc.Connection@32fb4f
2012-05-29 03:52:12.0

【讨论】:

  • 非常感谢您的澄清。我的很多疑虑都被清除了。在获得驱动程序实例之后,我实际上是在尝试获取 DriverManager 类本身的实例以获取连接。此外,我还试图将驱动程序类转换为“com.mysql.jdbc.Driver”接口“java.sql.Driver”。它为我工作..我正在做进一步的研发,再次感谢您提供的信息。
【解决方案2】:

DriverManager 忽略在运行时加载的类,它只对系统类加载器加载的类起作用。

您可以创建一个 Dummy 驱动程序类来封装您的实际数据库驱动程序。源码可以在here找到。

题外话:

File.toURL 已弃用,而是使用 toURL 上的 URIFile 获取 URL

URLClassLoader urlCl = new URLClassLoader(new URL[] { f.toURI().toURL()},System.class.getClassLoader()); 

【讨论】:

    猜你喜欢
    • 2011-08-06
    • 1970-01-01
    • 2014-03-30
    • 2012-02-28
    • 2017-01-15
    • 1970-01-01
    • 2016-09-07
    • 1970-01-01
    • 2013-08-06
    相关资源
    最近更新 更多