jsp连接Access

jsp连接Access,第1张

开始接触JDBC时,一直有一个疑虑,为什么执行Class.forName(“com.mysql.jdbc.Driver“)就可以载入MySql的驱动程序?JDBC的驱动程序初始化过程是怎么样的?连接具体的数据库时,JDBC的DriverManager又是如何运作的?带着这么几个疑惑,本人下载了MySql的驱动源代码,结合J2SDK的源代码,分析了一下JDBC的驱动管理机制。

1. 分析JDBC的驱动程序管理部分的实现代码:

在JDBC的层次上,sun主要定义了1个接口Driver和两个类:DirverManager和DriverInfo。每个JDBC驱动程序必须实现Driver接口(在MySql的Connector/J驱动中,这个叫做com.mysql.jdbc.Driver)。而DriverManager则负责管理所有的Driver对象,包含注册Driver;选择合适的Driver来建立到某个数据库的连接;以及进行一些Driver的信息管理等。DriverInfo非常简单,用于保存Driver的信息,只有3个成员变量,Driver,DriverClass和DriverClassName,意义非常明显。

先看一下在DriverManager.java中的关键代码:

private static java.util.Vector drivers = new java.util.Vector()

所有的Driver对象保存在一个Vector数组中。

注册Driver的函数叫registerDriver,将需要注册的Driver对象传入即可:

public static synchronized void registerDriver(java.sql.Driver driver)

throws SQLException {

if (!initialized) {//如果没有初始化,则先初始化

initialize()

}

DriverInfo di = new DriverInfo()//实际保存的不是Driver,而是一个DriverInfo对象,但是DriverInfo的其它成员完全可以由Driver推导出来,所以个人觉得DriverInfo对象可有可无,直接使用Driver应该就可以了。

di.driver = driver

di.driverClass = driver.getClass()

di.driverClassName = di.driverClass.getName()

drivers.addElement(di) //将DriverInfo对象添加到数组中

println("registerDriver: " + di)

}

这样就完成了驱动程序的注册过程。然后重点看一下建立数据库连接的代码,在getConnection函数中,省略了一些非关键代码:

private static synchronized Connection getConnection(

String url, java.util.Properties info, ClassLoader callerCL) throws SQLException {

SQLException reason = null

//轮询所有的DriverInfo对象。

for (int i = 0i <drivers.size()i++) {

DriverInfo di = (DriverInfo)drivers.elementAt(i)

try {

//使用DriverInfo中的Driver对象去做实际的连接数据库的工作

Connection result = di.driver.connect(url, info)

if (result != null) {

// Success!

println("getConnection returning " + di)

return (result) //一旦成功连接,直接返回Connection对象,然后推出

}

} catch (SQLException ex) {

...

}

}

//这就是经常看到的出错信息--找不到合适的驱动程序。

println("getConnection: no suitable driver")

throw new SQLException("No suitable driver", "08001")

}

由上面的getConnection函数可以看到,真正实现数据库连接的是Driver对象的connect函数。而且可以看到,由于DriverManager.getConnection使用的是一种轮询的方式,注册的驱动程序越多,连接速度会越慢。JDBC连接数据库的速度很慢,是不是和这种实现方式有关联呢?怀着这个问题,本人下载了MySql的Connector/J驱动包,开始分析其connect函数的实现。

2.分析MySql的注册和建立连接部分的代码:

打开MySql的源码包,首先分析其Driver类的实现。发现Driver类的实现非常简单,

public class Driver extends NonRegisteringDriver implements java.sql.Driver {

static {

try {

java.sql.DriverManager.registerDriver(new Driver())

} catch (SQLException E) {

throw new RuntimeException("Can't register driver!")

}

}

public Driver() throws SQLException {

// Required for Class.forName().newInstance()

}

可以看到,有一段static代码,调用了DriverManager的registerDriver方法。这其实就解释了Class.forName(“com.mysql.jdbc.Driver”)能够完成MySql驱动注册的问题。因为forName会导致这段static代码被调用,从而间接调用了registerDriver,完成注册过程。

com.mysql.jdbc.Driver从com.mysql.jdbc.NonRegisteringDriver继承而来,实际上是NonReisteringDriver完成了java.sql.Driver接口的实现工作。转移目标,分析NonRegisteringDriver的connect函数。

NonRegisteringDriver.connect的实现也比较简单,正合我意:

public java.sql.Connection connect(String url, Properties info)

throws SQLException {

//1.分析传入的连接字符串.

if ((props = parseURL(url, info)) == null) {

return null

}

try {

//2. 建立一个Connection对象完成实际的数据库连接工作

Connection newConn = new com.mysql.jdbc.Connection(host(props),

port(props), props, database(props), url, this)

return newConn

非常简单,先parseURL,然后使用Connection去建立连接。parseURL只是简单的字符串分析,主要是分析传入的连接字符串是否满足“jdbc:mysql://host:port/database“的格式,如果不满足,直接返回null,然后由DriverManager去试验下一个Driver。如果满足,则建立一个Connection对象建立实际的数据库连接,这不是本人关注的问题,源码分析就此打住。

这也就解释了第二个问题,DriverManager的轮询查询注册的Driver对象的工作方式所带来的性能代价并不是很大,主工作量只是parseURL函数。

Connection con=null

Statement stmt=null

ResultSet rs=null

try

{

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver")

}

catch(ClassNotFoundException e)

{

//

}

try

{

String url=getServletContext().getRealPath("/work6/mystu.mdb")//相对于webapps的数据库所在目录

con=DriverManager.getConnection("jdbc:odbc:driver={Microsoft Access Driver (*.mdb)}DBQ="+url+"")

stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY)

String condition="//你的sql语句"

stmt.executeUpdate(condition)

con.close()

}

catch(SQLException e)

{

//

}

import java.sql.Connection

import java.sql.DriverManager

import java.sql.ResultSet

import java.sql.SQLException

import java.sql.Statement

public class ConnToAccess {

 public static void main(String[] args) throws SQLException, InstantiationException, IllegalAccessException {

  String url="jdbc:odbc:driver={Microsoft Access Driver(*.mdb)}DBQ=db.mdb"

  //           driver:连接类型        DBQ是access的地址

//  String url="jdbc:odbc:test" //此为dsn

  try {

   Class.forName("sun.jdbc.odbc.JdbcOdbcDriver")

   Connection conn=DriverManager.getConnection(url)

   Statement stm=conn.createStatement()

   ResultSet rs=stm.executeQuery("select * from sell")

   while(rs.next())

   {

    System.out.println(rs.getString(3))

   }

   rs.close()

   stm.close()

   conn.close()

  } catch (ClassNotFoundException e) {

   System.out.println(e.getMessage())

  }

 }

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9976650.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-03
下一篇 2023-05-03

发表评论

登录后才能评论

评论列表(0条)

保存