本博客要记录的是如何去使用JDBC去操作数据库的一般过程。
JDBC操作步骤如下:
1.注册驱动
2.建立连接
3.创建语句对象
4.执行语句
5.处理结果集
6.关闭资源
看如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
package
Base;
import
java.sql.DriverManager;
import
java.sql.ResultSet;
import
java.sql.SQLException;
import
com.mysql.jdbc.Connection;
import
com.mysql.jdbc.Statement;
public
class
BaseDriver {
public
static
void
Test()
throws
SQLException{
//注册驱动
DriverManager.registerDriver(
new
com.mysql.jdbc.Driver());
//建立连接
Connection conn = (Connection) DriverManager.getConnection(
""
,
"root"
,
"password01!"
);
//创建语句
Statement stm = (Statement) conn.createStatement();
//执行语句,获取结果
ResultSet resultSet = stm.executeQuery(
"select * from t_user"
);
//遍历结果集
while
(resultSet.next()){
System.out.println(resultSet.getObject(
0
)+
"\t"
+resultSet.getObject(
1
)+
"\t"
+resultSet.getObject(
2
)+
"\t"
+resultSet.getObject(
3
));
}
//释放资源
resultSet.close();
stm.close();
conn.close();
}
}
|
1.注册驱动
注册驱动的方式有两种:
a.DriverManager进行注册
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
b.使用Class进行注册
Class.forName("com.mysql.jdbc.Driver");
注册驱动过程到底做了什么事情呢?听我慢慢道来:
a方式注册驱动主要做了如下工作:
首先我们先来看一下DriverManager的源代码:
1
2
3
4
5
6
7
8
9
10
11
12
|
public
class
DriverManager {
// List of registered JDBC drivers
private
final
static
CopyOnWriteArrayList<DriverInfo> registeredDrivers =
new
CopyOnWriteArrayList<>();
private
static
volatile
int
loginTimeout =
0
;
private
static
volatile
java.io.PrintWriter logWriter =
null
;
private
static
volatile
java.io.PrintStream logStream =
null
;
// Used in println() to synchronize logWriter
private
final
static
Object logSync =
new
Object();
}
|
上面是通过反编译出来的DriverManager类的部分代码
private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>();把驱动注册在一个列表里面。有了数据库的驱动包后,在调用getConnection后,就会在这个驱动注册列表里面去一个一个的找,看是否能够建立连接,如果最后没有找到,那么就会抛出异常。
b.方式注册驱动做了哪些工作:
同样我们也来看一下源代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
/**
* Returns the {@code Class} object associated with the class or
* interface with the given string name. Invoking this method is
* equivalent to:
*
* <blockquote>
* {@code Class.forName(className, true, currentLoader)}
* </blockquote>
*
* where {@code currentLoader} denotes the defining class loader of
* the current class.
*
* <p> For example, the following code fragment returns the
* runtime {@code Class} descriptor for the class named
* {@code java.lang.Thread}:
*
* <blockquote>
* {@code Class t = Class.forName("java.lang.Thread")}
* </blockquote>
* <p>
* A call to {@code forName("X")} causes the class named
* {@code X} to be initialized.
*
* @param className the fully qualified name of the desired class.
* @return the {@code Class} object for the class with the
* specified name.
* @exception LinkageError if the linkage fails
* @exception ExceptionInInitializerError if the initialization provoked
* by this method fails
* @exception ClassNotFoundException if the class cannot be located
*/
@CallerSensitive
public
static
Class<?> forName(String className)
throws
ClassNotFoundException {
return
forName0(className,
true
,
ClassLoader.getClassLoader(Reflection.getCallerClass()));
}
|
根据上面的反编译出来的Class源代码重的ForName的源代码,也是加载在一个驱动列表中,通过遍历驱动列表进行检测是否有符合目标的驱动注册,如果没有则抛出异常。
区别:
DriverManager.registerDriver(new com.mysql.jdbc.Driver());会在JVM装载类时调用静态代码初始化块,new com.mysql.jdbc.Driver()同时会实例化一个驱动实例,所以这种方式会在驱动注册列表中出现两个相同的MySql的驱动注册项。
Class.forName("com.mysql.jdbc.Driver");因为forName的参数是字符串类型,在加载类时只会调用静态代码块创建一个实例,驱动注册表中只有一个MySql的驱动注册项。