求教一个jdbc问题
在学JDBC时搞不明白内部是怎么连接的。(1)
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String connectionUrl = "jdbc:sqlserver://localhost;database=AdventureWorks;integratedSecurity=true;"
Connection con = DriverManager.getConnection(connectionUrl);
(2)
等价于
Driver d = (Driver) Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
String connectionUrl = "jdbc:sqlserver://localhost;database=AdventureWorks;integratedSecurity=true;"
Connection con = d.connect(connectionUrl, new Properties());
第2段很容易理解。
迷惑的事第一段:
在执行Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");这句话后SQLServerDriver这个类的.class文件被加载到JVM中生成一个Class对象,这个Class对象包含SQLServerDriver这个类运行时的信息,这个Class对象应该是为之后创建连接时调用吧。
Connection con = DriverManager.getConnection(connectionUrl);这个方法在执行时肯定是调用了上述的Class对象吧,我在疑惑是怎么找到上述的Class对象的进行调用的。难道是通过本地方法找到上述那个Class对象的?
--------------------编程问答-------------------- Class.forName(xxx.xx.xx) 返回的是一个类,不是一个对象
--------------------编程问答-------------------- public inte易做图ce Driver
The inte易做图ce that every driver class must implement.
The Java SQL framework allows for multiple database drivers.
Each driver should supply a class that implements the Driver inte易做图ce.
The DriverManager will try to load as many drivers as it can find and then for any given connection request, it will ask each driver in turn to try to connect to the target URL.
It is strongly recommended that each Driver class should be small and standalone so that the Driver class can be loaded and queried without bringing in vast quantities of supporting code.
When a Driver class is loaded, it should create an instance of itself and register it with the DriverManager. This means that a user can load and register a driver by calling
Class.forName("foo.bah.Driver")
看最后一句,驱动类实现了Driver接口,并且推荐在载入时使用DriverManager注册自身,这样不管你是直接new一个Driver实现类,或者通过Class.forName载入一个Driver实现类,都通过DriverManager创建了自身并执行了注册,这样DriverManager.getConnection和Driver.connect会有相同的执行效果。 --------------------编程问答-------------------- --------------------编程问答-------------------- 有空去学习学习java的反射吧 --------------------编程问答-------------------- Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
虚拟机会装载SQLServerDriver这个类,但不仅仅只是装载这个类,还会执行这个类里的方法,那就是static块
你反编译下SQLServerDriver这个了,找找里面的static块,一般都有DriverManager.register。。。。之类的代码在里头,Class.forName这个类的主要目的就是执行这段代码 --------------------编程问答-------------------- 你确信返回的事一个类?应该返回的是一个Class对象。 --------------------编程问答-------------------- 现在知道了!JDBC是一个服务者框架,DriverManager类有一个静态成员,这个成员是一个集合用于装载连接,当JVM加载这个类的时候(也就是调用Class.forName()时候)静态成员会被初始化,会调用一个方法,这个方法向这个集合里面注册一个连接,然后调用DriverManager.getConnection()时返回这个连接。 --------------------编程问答-------------------- just do it ,and do not care about it. --------------------编程问答--------------------
这是详细的过程,请你参考,我这用oracle.jdbc.driver.OracleDriver而不是MYSQL的
//这是OracleDriver里面的static块
static
{
defaultDriver = null;
Timestamp timestamp = Timestamp.valueOf("2000-01-01 00:00:00.0");
try
{
if(defaultDriver == null)
{
defaultDriver = new OracleDriver();
//看registerDriver方法做了什么
DriverManager.registerDriver(defaultDriver);
}
}
catch(RuntimeException runtimeexception) { }
catch(SQLException sqlexception) { }
}
//DriverManager的部分源码
//这里是往Vector(writeDrivers)中加入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();
// Not Required -- drivers.addElement(di);
writeDrivers.addElement(di);
println("registerDriver: " + di);
/* update the read copy of drivers vector */
readDrivers = (java.util.Vector) writeDrivers.clone();
}
//注意,你调用的DriverManager.getConnection(connectionUrl)方易做图调用重载的方法
private static Connection getConnection(
String url, java.util.Properties info, ClassLoader callerCL) throws SQLException {
java.util.Vector drivers = null;
/*
* When callerCl is null, we should check the application's
* (which is invoking this class indirectly)
* classloader, so that the JDBC driver class outside rt.jar
* can be loaded from here.
*/
synchronized(DriverManager.class) {
// synchronize loading of the correct classloader.
if(callerCL == null) {
callerCL = Thread.currentThread().getContextClassLoader();
}
}
if(url == null) {
throw new SQLException("The url cannot be null", "08001");
}
println("DriverManager.getConnection(\"" + url + "\")");
if (!initialized) {
initialize();
}
//这里drivers = readDrivers; 而readDrivers是从之前的writeDrivers所clone的,这里就不细讲了
synchronized (DriverManager.class){
// use the readcopy of drivers
drivers = readDrivers;
}
// Walk through the loaded drivers attempting to make a connection.
// Remember the first exception that gets raised so we can reraise it.
SQLException reason = null;
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;
}
}
}
// if we got here nobody could connect.
if (reason != null) {
println("getConnection failed: " + reason);
throw reason;
}
println("getConnection: no suitable driver found for "+ url);
throw new SQLException("No suitable driver found for "+ url, "08001");
}
所以总的来说,调Class.forName("")后,网DriverManager的Vector加入了那个Driver,然后就可以用来创建连接了 --------------------编程问答-------------------- jdbc是java连接数据库的基础啊,楼主多学学啊 --------------------编程问答-------------------- --------------------编程问答-------------------- 不用想的有多复杂
说白了,就是jdbc类里都有一段static段
不管你是new了jdbc实现类或者用class.forname载入
static段都被执行了,仅此而已...
补充:Java , Java EE