最近写了个监控系统,需要从各个数据库中获取数据,为了可配行,各个数据库的信息(数据库类型,用户名,密码等)都存放在我们自己的数据库中,
暂时想到的方法就是直接用JDBC代码访问数据库,取数据,然后将数据库连接进行池化。
唉,以前都是J2EE开发,用spring配置使用,这次直接使用JDBC还不太习惯了,OK,不废话了
JDBC步骤:
1.加载数据驱动
Class.forName("com.mysql.jdbc.Driver");
2. 得到数据库连接
DriverManager.getConnection(url, user, password);
当时到这步就产生两个疑问:
1. 为什么加载了数据库驱动,就能得到数据库连接,看上面的两行代码,是看出来两者之间联系
2. 除了Class.forName()加载数据库驱动,貌似没有看到过其他加载数据库驱动方式,是否有其他方式?为什么不用其他方式?
OK,问题出来了,就看看问题
问题1:
后来结合数据库驱动源代码和JDBC规范了解到,每个数据库驱动,都必须在加载的时候,自己实现数据库驱动注册(注册?貌似前面观察者模式就有注册行为,但是数据库驱动却没有update行为,所以不存在通知)
mysql驱动源代码:
public class Driver extends NonRegisteringDriver
implements java.sql.Driver
{
public Driver()
throws SQLException
{
}
static
{
try
{
DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
}
DriverManager.registerDriver()代码如下:
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);
/* 由于可以注册多个数据库驱动类型,这里更新下数据库驱动 */
readDrivers = (java.util.Vector) writeDrivers.clone();
}
这样在DriverManager.getConnection()的时候,就可以用到数据库驱动,得到连接了,代码如下
public static Connection getConnection(String url,
String user, String password) throws SQLException {
java.util.Properties info = new java.util.Properties();
// Gets the classloader of the code that called this method, may
// be null.
ClassLoader callerCL = DriverManager.getCallerClassLoader();
if (user != null) {
info.put("user", user);
}
if (password != null) {
info.put("password", password);
}
return (getConnection(url, info, callerCL));
}
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();
}
synchronized (DriverManager.class){
// 得到注册的驱动
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 ( 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");
}
OK,到此问题的答案算是明白了
下面,问题2:
加载类的方式几种,目前我想到的就下面几种,不够以后在补充,呵呵:
1. Class.forName()
2. Class.forName().newInstance();
3. new
4.Class.class
5.Class.class.newInstance();
6.Thread.currentThread().getContextClassLoader().loadClass()
可以知道方法2和5都是有点多余,加载的类,还实例化了一个对象出来,可以Pass掉。而3跟前面一个问题一样,实例化了一个对象出来,多此一举,此对象还占据内存。
OK,还剩下三种方法1.4.6,先来分析1和6的区别
Class.forName()的源代码如下:
public static Class<?> forName(String className)
throws ClassNotFoundException {
return forName0(className, true, ClassLoader.getCallerClassLoader());
}
调用此方法等效于:
Class.forName(className, true, currentLoader)
第二次参数表示装载类的时候是否初始化该类, 即调用类的静态块的语句及初始化静态成员变量。
Thread.currentThread().getContextClassLoader().loadClass()的代码如下:
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
调用此方法等效于调用 loadClass(name,false)
。
protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// First, check if the class has already been loaded
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
此方法使用指定的二进制名称来加载类。此方法的默认实现将按以下顺序搜索类:
-
调用 findLoadedClass(String)
来检查是否已经加载类。
-
在父类加载器上调用 loadClass
方法。如果父类加载器为 null,则使用虚拟机的内置类加载器。
-
调用 findClass(String)
方法查找类。
如果使用上述步骤找到类,并且 resolve 标志为真,则此方法将在得到的 Class 对象上调用 resolveClass(Class)
方法。
参数:
resolve
- 如果该参数为 true,则分析这个类
所以此方法没有初始化类,即没有加载类的静态代码,所以此方法不行
OK,下面只剩下方法1和4了,方法4加载类会获得编译检查,可以保证此类一定存在,所以无法做到运行时动态加载未知数据库驱动,并且Class.class前面还必须给一个变量赋值才行: Class cc = Class.class
所以加载数据库,大家看到的都是方法1。
好了,到这,收工,呵呵。。。。
分享到:
相关推荐
根据所提供的文件信息,我们可以详细探讨在Java中如何加载并使用各种数据库驱动来建立与数据库的连接。 ### Java连接数据库:驱动加载与连接建立 #### 1. **MySQL数据库** 对于MySQL数据库,其驱动类名为`...
下面我们将深入探讨`Class.forName()`的用途、工作原理以及与`new`关键字的区别。 一、`Class.forName()`的用途 1. **动态加载类**:当需要在程序运行时根据某些条件或用户输入来决定加载哪个类时,`Class.forName...
- **Class.forName()**:用于加载特定的JDBC驱动类。 - **DriverManager.getConnection()**:用于建立到数据库的连接。 - **URL**:指定数据库的位置以及连接参数。 - **Connection**:表示与数据库之间的连接。 ##...
在Java编程中,JDBC(Java Database Connectivity)是用于与各种数据库进行交互的一组接口和类。当我们使用JDBC操作MySQL...然而,对于较旧的项目或较低版本的JDBC,仍然需要使用`Class.forName()`的方式来加载驱动。
加载JDBC驱动程序是Java应用程序访问数据库的第一步,这个过程涉及到Java的反射机制和Class.forName()方法。下面我们将深入探讨这一主题。 1. **JDBC驱动类型** JDBC驱动分为四种类型: - Type 1: JDBC-ODBC ...
### Java数据库驱动加载问题 #### SQLServer2000与SQLServer2005加载驱动的相同点与不同点 在Java开发环境中,通过JDBC(Java Database Connectivity)技术可以实现对各种数据库的操作。其中,SQL Server是常用的...
Class.forName("com.informix.jdbc.IfxDriver"); Connection conn = DriverManager.getConnection(url, username, password); // ... 执行数据库操作 } catch (Exception e) { e.printStackTrace(); } } } ``...
2. **建立连接**:通过JDBC的`Class.forName()`方法加载数据库驱动,例如: ```java Class.forName("com.nudt.jdbc.Driver"); ``` 这里的字符串应替换为实际的驱动类名,确保与jar包中的类名匹配。 3. **获取...
1. 加载驱动:使用`Class.forName()`方法加载特定数据库的JDBC驱动,例如: ```java Class.forName("com.mysql.jdbc.Driver"); ``` 2. 创建连接:使用`DriverManager.getConnection()`方法创建数据库连接,参数...
首先需要在系统中配置ODBC数据源,然后在Java代码中通过`Class.forName()`加载对应的驱动,最后使用`DriverManager.getConnection()`创建连接。 - 示例代码: ```java Class.forName("sun.jdbc.odbc....
本文将深入探讨如何使用Java连接这些数据库,并介绍所需的驱动包。 首先,我们来了解一下JDBC。JDBC是Java中的一组接口和类,由Java SE的标准版(Java SE Standard Edition)提供,允许Java应用程序与各种关系型...
在Java中,加载数据库驱动通常通过`Class.forName()`方法,然后使用`DriverManager.getConnection()`创建数据库连接。此外,Java 6及以上版本引入了Automatic JDBC Driver Registration,可以省略`Class.forName()`...
2. **加载驱动**:使用`Class.forName()`方法加载JDBC驱动。 3. **创建连接**:通过`DriverManager.getConnection()`方法建立与Sybase数据库的连接,需要提供数据库URL、用户名和密码。 4. **创建Statement或...
这里,`Class.forName`用于加载特定的数据库驱动,`DriverManager.getConnection`则负责根据提供的URL、用户名和密码创建数据库连接。`jdbc:oracle:thin:@`协议指示使用Oracle Thin驱动进行连接。 #### 2. Java连接...
本篇文章将深入探讨"sqlserver2000数据库驱动"这一主题,特别是关于jtds和SQL Server的jar包驱动。 首先,让我们关注一下`jtds`。Jtds(Java JDBC Driver for MS SQL Server and Sybase)是一个开源的Java数据库...
这一过程通常通过`Class.forName()`方法完成,该方法会加载指定类到JVM中,并实例化驱动对象。以下是针对三种不同数据库的驱动加载示例: 1. **Microsoft SQL Server** (MSSQL): ```java Class.forName(...
在上述代码中,`Class.forName()`方法用于加载相应的数据库驱动,`DriverManager.getConnection()`则用于建立实际的数据库连接。每个数据库的URL格式略有不同,包含了主机地址、端口、数据库名称和服务名等信息。 ...
在Java应用中,使用Oracle JDBC驱动通常涉及Class.forName()加载驱动,DataSource获取连接,并通过CallableStatement或PreparedStatement进行操作。 3. SQL Server驱动: Microsoft SQL Server是另一款广泛使用的...
本文将深入探讨标题中提到的几个数据库及其对应的JDBC驱动包,包括MySQL、Microsoft SQL Server 2000/2005以及Oracle。 首先,MySQL是一款开源、免费的关系型数据库管理系统,广泛应用于Web应用开发。其JDBC驱动包...