web项目中不适用于java.sql.DriverManager描述的JDBC 4.0 Drivers及以后版本连接数据库是不需要用forName()?

来源:互联网 发布:淘宝客服介入会成功吗 编辑:程序博客网 时间:2024/05/18 15:26

在jdk1.6中java.sql.DriverManager明确指出,在JDBC 4.0 Drivers 版本及以后版本不再需要使用Class.forName() 显式地加载 JDBC 驱动程序。

mysql JDBC Driver源文件

public class Driver extends NonRegisteringDriver implementsjava.sql.Driver {
     //
     // Register ourselves with theDriverManager
     //JDBC4.0Drivers以前,使用Class.forName("com.mysql.jdbc.driver")显示加载驱动程序时就会调用这个静态代码块。
     static {
         try {
            java.sql.DriverManager.registerDriver(new Driver());
         } catch(SQLException E) {
            throw new RuntimeException("Can't register driver!");
         }
     }
     /**
      * Construct a new driverand register it with DriverManager
      * 
      * @throws SQLException
      *            if a database error occurs.
      */
     public Driver() throwsSQLException {
         // Required forClass.forName().newInstance()
     }
 }


 

javaSE项目(支持不用forName())

不用forName()显示调用的代码,也能正确连接**************************(支持不用forName())

//连接数据库的URL
 String url ="jdbc:mysql://localhost:3306/test";

//设置用户名和密码
 Properties props = new Properties();
 props.setProperty("user","user");
 props.setProperty("password","password");
 
//应用程序不再需要使用 Class.forName()显式地加载 JDBC驱动程序。
 //在调用getConnection方法时,DriverManager会试着从初始化时加载的那些驱动程序以及使用与当前 applet

// 或应用程序相同的类加载器显式加载的那些驱动程序中查找合适的驱动程序。


//连接到具体的数据库(根据url中的连接规范判断连接驱动程序)
 Connection connection =DriverManager.getConnection(url, props);
 

*************************************


 

那不用显示调用forName(Driver)连接数据库是什么时候加载java.sql.jdbc.Driver的呢?

让我们看一下

java.sql.DriverManager的源代码。
 

在java.sql.DriverManager类中有一静态码块,里面有 loadInitialDrivers()方法。 

 /**
      * Load the initial JDBCdrivers by checking the System property
      * jdbc.properties and thenuse the {@code ServiceLoader} mechanism
      */
     static {
        loadInitialDrivers();                                           //用来初始化相关的Drivers
         println("JDBCDriverManager initialized");
     }
  

 loadInitialDrivers();源代码
 

 private static void loadInitialDrivers() {
         Stringdrivers;       

省略从META-INF/services/java.sql.Driver文件中或从读取Driver驱动等代码
         。。。


       String[] driversList = drivers.split(":");
        println("number of Drivers:" + driversList.length);
         for (StringaDriver : driversList) {
             try{
                println("DriverManager.Initialize: loading " +aDriver);
                Class.forName(aDriver, true, //这里有forName()语句,也就是说,再调用DriverManage静态方法时必定会调用这里的语句。
                        ClassLoader.getSystemClassLoader());            //所以JDBC 4.0 Drivers及以后版本是不需要显示调用forName语句的。
             }catch (Exception ex) {
                println("DriverManager.Initialize: load failed: " +ex);
             }
         }
     }
 


 上面在java 项目中完全像JDK中介绍的一样,运行没问题。


java web项目(不支持不用forName())

今天在java web项目中用tomcat服务器试了一下,出现

java.lang.RuntimeException: java.sql.SQLException:No suitable driver found错误

也就是com.mysql.jdbc.Driver类没有找到,我已经把mysql-connector-java-5.1.41-bin.jar放到了WebRoot/WEB-INF/lib/目录下,确提示没有找到匹配的Driver驱动。

加上Class.forName(com.mysql.jdbc.Driver),问题解决,说明mysqlJDBC连接.jar是生效的。


 

为什么WEB项目中DriverManager静态代码块中的loadInitialDrivers()不能找到自己的com.mysql.jdbc.Driver呢? 

这其中的原理还有待研究,菜鸟水平有限,希望高手指导一下。微笑


 


 

引用jdk 1.6中文版java.sql.DriverManager
 


 

public class DriverManager extends Object

管理一组JDBC驱动程序的基本服务。
 
注:DataSource接口是 JDBC 2.0 API 中的新增内容,它提供了连接到数据源的另一种方法。使用 DataSource对象是连接到数据源的首选方法。(这里看了com.mysql.jdbc.jdbc2.optional.MysqlDataSource源码,也就是利用反射创建com.mysql.jdbc.Driver类,只是不用注册DriverManager了;而且创建驱动获得的连接跟是此方法获得的连接是一样的java.sql.Connection 
 

作为初始化的一部分,DriverManager类会尝试加载在 "jdbc.drivers"系统属性中引用的驱动程序类。这允许用户定制由他们的应用程序使用的 JDBC Driver。例如,在 ~/.hotjava/properties 文件中,用户可以指定: 
 

 jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.taste.ourDriver
  DriverManager 类的方法 getConnection getDrivers已经得到提高以支持 Java Standard Edition ServiceProvider机制。 JDBC 4.0 Drivers必须包括 META-INF/services/java.sql.Driver 文件。此文件包含 java.sql.Driver JDBC驱动程序实现的名称。例如,要加载 my.sql.Driver类,META-INF/services/java.sql.Driver文件需要包含下面的条目: 
 

 my.sql.Driver
  应用程序不再需要使用 Class.forName()显式地加载 JDBC驱动程序。当前使用 Class.forName()加载 JDBC驱动程序的现有程序将在不作修改的情况下继续工作。 
 

在调用 getConnection方法时,DriverManager会试着从初始化时加载的那些驱动程序以及使用与当前 applet或应用程序相同的类加载器显式加载的那些驱动程序中查找合适的驱动程序。 
 

Java 2 SDK标准版本 1.3版开始,只有当已授予适当权限时设置日志流。通常这将使用工具 PolicyTool完成,该工具可用于授予 permissionjava.sql.SQLPermission "setLog"权限。 

1 0
原创粉丝点击