Java-JDBC连接数据库步骤

abstract

加载JDBC驱动类(以mysql驱动为例)

JDBC定义了一套接口,数据库产品的提供商会实现这些接口来提供自己的数据库驱动程序,这是个很好的面向接口编程的实例,想要替换数据库的时候只需要替换驱动程序就可以了(这里暂不考虑不同数据库之间的数据类型和SQL语法的差异)

1
2
3
4
5
6
7
try {    
// 加载MySql的驱动类
Class.forName("com.mysql.jdbc.Driver");
} catch(ClassNotFoundException e) {
System.out.println("找不到驱动程序类 ,加载驱动失败!");
e.printStackTrace();
}

加载驱动类的时候具体执行了哪些操作呢?

Class.froName()方法源码

1
2
3
4
5
6
@CallerSensitive
public static Class<?> forName(String className)
throws ClassNotFoundException {
Class<?> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

Class.forName0()方法源码

1
2
3
4
5
/** Called after security check for system loader access checks have been made. */
private static native Class<?> forName0(String name, boolean initialize,
ClassLoader loader,
Class<?> caller)
throws ClassNotFoundException;

java7官方文档中对该方法的描述

Returns the Class object associated with the class or interface with the given string name, using the given class loader. Given the fully qualified name for a class or interface (in the same format returned by getName) this method attempts to locate, load, and link the class or interface. The specified class loader is used to load the class or interface. If the parameter loader is null, the class is loaded through the bootstrap class loader. The class is initialized only if the initialize parameter is true and if it has not been initialized earlier.

返回一个给定类或者接口的一个 Class 对象,如果没有给定类加载器, 那么会使用根类加载器。如果 initalize 这个参数传了 true,那么给定的类如果之前没有被初始化过,那么会被初始化。

再回过头来看看com.mysql.jdbc.Driver

1
2
3
4
5
6
7
8
9
10
11
12
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}

static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}

刚才说到类会被初始化,类初始化的时候静态方法会被执行。即DriverManager.registerDriver(new Driver());,也就是说一开始我们加载驱动的时候执行DriverManager.registerDriver(new Driver());也是一样的。

JDBC4.0以后就不用再手动加载数据库驱动了,在DriverManager.loadInitialFrivers()方法中有这么一段代码

1
2
3
4
5
6
7
8
9
10
String drivers;
try {
drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty("jdbc.drivers");
}
});
} catch (Exception ex) {
drivers = null;
}

他会检查系统配置中名为jdbc.drivers的配置参数,并找到对应的数据库驱动。

拼接JDBC连接URL

连接URL格式如下

1
jdbc:mysql://[host:port],[host:port].../[database][?参数名1][=参数值1][&参数名2][=参数值2]...

例如:

1
2
3
4
5
jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=gbk;
# useUnicode=true:表示使用Unicode字符集。
# 如果characterEncoding设置为gb2312或GBK,本参数必须设置为true。

# characterEncoding=gbk:字符编码方式。

创建数据库连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
要连接数据库,需要向java.sql.DriverManager请求并获得Connection对象
该对象就代表着一个数据库的连接
使用DriverManager的getConnectin(String url, String username, String password)方法
传入指定的连接的数据库的路径、数据库的用户名和密码来获得。
// 连接MySql数据库,用户名和密码都是root
String url = "jdbc:mysql://localhost:3306/test";
String username = "root";
String password = "root";
try {
Connection con = DriverManager.getConnection(url , username , password);
} catch(SQLException se) {
System.out.println("数据库连接失败!");
se.printStackTrace();
}

创建Statement实例

1
2
3
4
5
6
7
8
要执行SQL语句,必须获得java.sql.Statement实例,Statement实例分为以下3种类型:    
1、执行静态SQL语句。通常通过Statement实例实现。
2、执行动态SQL语句。通常通过PreparedStatement实例实现。
3、执行数据库存储过程。通常通过CallableStatement实例实现。
具体的实现方式:
Statement stmt = con.createStatement();
PreparedStatement pstmt = con.prepareStatement(sql);
CallableStatement cstmt = con.prepareCall("{CALL demoSp(? , ?)}");

执行SQL语句

……

操作完数据库后关闭连接

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
操作完成以后要把所有使用的JDBC对象全都关闭,以释放JDBC资源,连接操作如果是入栈顺序的话,关闭连接的顺序那就是出栈顺序:    
1、关闭记录集
2、关闭声明
3、关闭连接对象
if (rs != null) { // 关闭记录集
try {
rs.close();
} catch(SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) { // 关闭声明
try {
stmt.close();
} catch(SQLException e) {
e.printStackTrace();
}
}
if (conn != null) { // 关闭连接对象
try {
conn.close();
} catch(SQLException e) {
e.printStackTrace();
}
}