netbeans中 Class.forName("com.mysql.jdbc.Driver");一直报错 那位高手帮忙解决
发布网友
发布时间:2022-04-07 22:12
我来回答
共4个回答
懂视网
时间:2022-04-08 02:34
传统的使用jdbc来访问数据库的流程为:
Class.forName(“com.mysql.jdbc.Driver”);
String url = “jdbc:mysql://localhost:3306/test?user=root&password=123456″;
Connection con = DriverManager.getConnection(url);
Statement statement = con.createStatement();
最开始使用的时候,不明白为什么首先要加载一个驱动类,之后就可以取得了Connection了,很好奇DriverManager是怎么获得那个驱动类的信息,后来看了下com.mysql.jdbc.Driver这个类的源代码,豁然开朗了。原来在com.mysql.jdbc.Driver类中有这么一段静态初始化代码:
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException(“Can’t register driver!”);
}
}
也就是,在Class.forName加载完驱动类,开始执行静态初始化代码时,会自动新建一个Driver的对象,并调用DriverManager.registerDriver把自己注册到DriverManager中去。
ps1: Class.forName(String) 与ClassLoader.loadClass(String)的区别
Class.forName(String): 加载类,并且执行类初始化;可以通过Class.forName(String, boolean, ClassLoader)第二个参数来仅仅加载类不执行初始化;
ClassLoader.loadClass(String): 仅仅加载类,不执行类初始化;
ps2: 有时会看到这种用法:
Class.forName(“com.mysql.jdbc.Driver”).newInstance();
这是没有必要的,正如前述,静态初始化已经new了一个Driver的对象,注册到DriverManager中去,在此再建立一个Driver对象则是完全没有必要的,浪费空间。
ps3: 结合ps1,Class.forName(“com.mysql.jdbc.Driver”);相当于:
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class cls = loader.loadClass(“com.mysql.jdbc.Driver”);
cls.newInstance();
这种方法的问题同ps2, 浪费了一个Driver对象;
ps4: 在java 6中,引入了service provider的概念,即可以在配置文件中配置service(可能是一个interface或者abstract class)的provider(即service的实现类)。配置路径是:/META-INF/services/下面。详细信息见:http://docs.oracle.com/javase/6/docs/technotes/guides/jar/jar.html#Service%20Provider
而java.sql.DriverManager也添加了对此的支持,因此,在JDK6中,DriverManager的查找Driver的范围为:
1)system property “jdbc.drivers” 中配置的Driver值;
2)用户调用Class.forName()注册的Driver
3)service provider配置文件java.sql.Driver中配置的Driver值。
因此,在jdk6中,其实是可以不用调用Class.forName来加载mysql驱动的,因为mysql的驱动程序jar包中已经包含了java.sql.Driver配置文件,并在文件中添加了com.mysql.jdbc.Driver.但在JDK6之前版本,还是要调用这个方法。
热心网友
时间:2022-04-07 23:42
在使用传统的JDBC连接数据库的时候,总是需要这一句(以MySQL为例):
Class.forName("com.mysql.jdbc.Driver");
以前我也没深究,只是看网上的例子都这么写,实际上也跑通了,于是便懒得去管内部原理。不过大概还是清楚的,知道这句话是向DriverManage注册了一个MySQL的JDBC Driver。
但为什么要用Class.forName这样看上去不是很优雅的方式呢?
网上还流传了一个这样的版本Class.forName("com.mysql.jdbc.Driver").newInstance(),似乎有点儿多此一举。
经过实验,我发现用com.mysql.jdbc.Driver driver = new com.mysql.jdbc.Driver() 也是可以的,但是只声明
com.mysql.jdbc.Driver driver = null ,而不实例化却又是不行的。
那么Driver的注册到底是在类的初始化时进行的,还是在类的对象初始化时进行的呢? 我也不知道,最好的办法还是看源码:
package com.mysql.jdbc;
import java.sql.DriverManager;
import java.sql.SQLException;
// Referenced classes of package com.mysql.jdbc:
// NonRegisteringDriver
public class Driver extends NonRegisteringDriver
{
public Driver()
throws SQLException
{
}
static
{
try
{
DriverManager.registerDriver(new Driver());
}
catch(SQLException E)
{
throw new RuntimeException("Can't register driver!");
}
}
}
源码之前没秘密,com.mysql.jdbc.Driver很简单,就是红色的那句,看来是在类的static block里面做的初始化。
那么我们只要搞清楚在java里面,static block执行的时机就可以清楚来龙去脉了。
还是做一个实验吧:package com.javaye;
class A{
static{
System.out.println("Class A loaded");
}
public A(){
System.out.println("create a instance of A");
}
}
public class Main {
public static void main(String[] args) throws Exception{
Class.forName("com.javaye.A");
}
}
打印结果:“Class A loaded”
这说明Class.forName可以使类的static block中的代码得到执行。
然后,我们在修改成下面这样:
package com.javaye;
class A{
static{
System.out.println("Class A loaded");
}
public A(){
System.out.println("create a instance of A");
}
}
public class Main {
public static void main(String[] args) throws Exception{
com.javaye.A a = null;
}
}
发现没有打印任何东西,这说明只是声明某个类的变量,是不会使static block的到执行的。
再改一下:
package com.javaye;
class A{
static{
System.out.println("Class A loaded");
}
public A(){
System.out.println("create a instance of A");
}
}
public class Main {
public static void main(String[] args) throws Exception{
com.javaye.A a = new com.javaye.A();
com.javaye.A a2 = new com.javaye.A();
}
}
输出结果:
Class A loaded
create a instance of A
create a instance of A
这说明实例化一个类的话,static block 也会被执行,而且只会被执行一遍。
如果仍有兴趣,还可以探索一下Driver的注册机制:
public static synchronized void registerDriver(java.sql.Driver driver)
throws SQLException {
if (!initialized) {
initialize();
}
DriverInfo di = new DriverInfo();
di.driver = driver;
di.driverClass = driver.getClass();
di.driverClassName = di.driverClass.getName();
drivers.addElement(di); //drivers 是一个vector,保存着被注册的driver.
println("registerDriver: " + di);
}
getConnection就是要从drivers里面挑出一个合适的数据库driver:
for (int i = 0; i < drivers.size(); i++) {
DriverInfo di = (DriverInfo)drivers.elementAt(i);
// If the caller does not have permission to load the driver then
// skip it.
if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
println(" skipping: " + di);
continue;
}
try {
println(" trying " + di);
Connection result = di.driver.connect(url, info);
if (result != null) {
// Success!
println("getConnection returning " + di);
return (result);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/go_2004/archive/2008/06/10/2531310.aspx
热心网友
时间:2022-04-08 01:00
估计是找不到Jar包,在应用服务器/Web服务器 的lib内拷入 驱动
热心网友
时间:2022-04-08 02:34
不容易