Java Web程序设计—— JDBC(一)
什么是JDBC
- Java DateBase Connectivity,java连接数据库,其实就是通过java语言连接数据库。
- JDBC就是通过向数据库发送sql语句操作数据库。
- 应用程序使用JDBC访问数据库的方式:
- JDBC的具体实现细节:
- JDBC驱动管理器:负责注册特定的JDBC驱动器,主要通java.sql.DriverManager类实现
- JDBC驱动器API:由SUN公司负责制定,其中最主要的接口是java.sql.Driver接口。
- JDBC驱动器:由数据库厂商创建,也称为JDBC驱动程序。JDBC驱动器实现了JDBC驱动器API,负责与特定的数据库连接,以及处理通信细节。
JDBC常用的API
Driver接口
- Driver接口是所有JDBC驱动程序必须实现的接口,该接口专门提供给数据库厂商使用。需要注意的是,在编写JDBC程序时,必须要把所使用的数据库驱动程序或类库加载到项目的中(这里指MySQL驱动JAR包)
DriverManager类
- DriverManager类用于加载JDBC驱动并且创建与数据库的连接。
- 在DriverManager类中,定义了两个比较重要的静态方法,如下所示:
Connection接口
- Connection接口代表Java程序和数据库的连接,只有获得该连接对象后,才能访问数据库,并操作数据表。
- Connection接口中,定义了一系列方法,其常用方法如下所示:
Statement接口
- Statement接口用于执行静态的SQL语句,并返回一个结果对象。Statement接口对象可以通过Connection实例的createStatement()方法获得,该对象会把静态的SQL语句发送到数据库中编译执行,然后返回数据库的处理结果。
- 在Statement接口中,提供了3个常用的执行SQL语句的方法,具体如下所示:
PreparedStatement接口
- PreparedStatement是Statement的子接口,用于执行预编译的SQL语句。该接口扩展了带有参数SQL语句的执行操作,应用该接口中的SQL语句可以使用占位符“?”来代替其参数,然后通过setXxx()方法为SQL语句的参数赋值。
- PreparedStatement接口中,提供了一些常用方法,具体如下所示:
注:需要注意的是,表中的setDate()方法可以设置日期内容,但参数Date的类型是java.sql.Date,而不是java.util.Date。
ResultSet接口
- ResultSet接口用于保存JDBC执行查询时返回的结果集,该结果集封装在一个逻辑表格中。
- 在ResultSet接口内部有一个指向表格数据行的游标(或指针),ResultSet对象初始化时,游标在表格的第一行之前,调用next()方法可将游标移动到下一行。如果下一行没有数据,则返回false。
- 在应用程序中经常使用next()方法作为while循环的条件来迭代ResultSet结果集。
- ResultSet接口中的常用方法如下所示:
实现第一个JDBC程序
-
JDBC的使用可以按照以下几个步骤进行:
(1)加载并注册数据库驱动。DriverManager.registerDriver(Driver driver)
或者Class.forName("driverName")
(2)获取Connection连接对象。Connection con = DriverManager.getConnection(url,username,password);
(3)获取操作数据库的对象Statement(或者PreparedStatement)。Statement stmt = con.createStatement();
(4)向数据库发送SQL语句,执行操作。比如执行查询操作:String sql="select * from users";
调用executeQuery(sql);
(5)操作ResultSet结果集,结果集里面封装的是查询的结果。遍历ResultSet,获取我们查询的数据。
(6)关闭连接,释放资源(倒关原则,先出现的,后关闭)。 -
准备工作:
(1)创建数据库:JDBC,在这个数据库里面创建表,插入几条数据:
mysql> create table users(
-> id int primary key auto_increment,
-> name varchar(40),
-> password varchar(40),
-> email varchar(60),
-> birthday date);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into users(name,password,email,birthday) values('zs','123','zs@qq.com','1990-08-02');
Query OK, 1 row affected (0.01 sec)
mysql> insert into users(name,password,email,birthday) values('ls','456','ls@qq.com','1978-04-05');
Query OK, 1 row affected (0.00 sec)
mysql> insert into users(name,password,email,birthday) values('wmz','789','wmz@qq.com','1998-07-18');
Query OK, 1 row affected (0.00 sec)
(2)导入jar包
package jdbc.example;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Date;
import com.mysql.jdbc.Driver;
public class Example01 {
// 执行查询操作
public static void main(String[] args) throws Exception {
// 1.注册并加载驱动
Driver driver = new Driver();
DriverManager.registerDriver(driver);
// 2.获取连接对象
String url = "jdbc:mysql://localhost:3306/jdbc";
String user = "root";
String password = "";
Connection con = DriverManager.getConnection(url, user, password);
// 3.获取操作数据的对象
Statement stmt = con.createStatement();
// 4.向数据库发送查询语句
String sql = "select * from users";
ResultSet rs = stmt.executeQuery(sql);
// 5.遍历结果集,获取查询的数据
while (rs.next()) {// 跳转搭配下一行,在某一行的值遍历完毕后,才会跳转到下一行去遍历
int id = rs.getInt(1);
String name = rs.getString("name");
String psw = rs.getString(3);
String email = rs.getString("email");
Date birthday = rs.getDate("birthday");
System.out.println(id + " " + name + " " + psw + " " + email + " " + birthday);
}
// 6.关闭连接,释放资源
rs.close();
stmt.close();
con.close();
}
}
比较规范的代码:
package jdbc.example;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
public class Example01 {
// 执行查询操作
public static void main(String[] args) {
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 1.注册并加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.获取连接对象
String url = "jdbc:mysql://localhost:3306/jdbc";
String user = "root";
String password = "";
con = DriverManager.getConnection(url, user, password);
// 3.获取操作数据的对象
stmt = con.createStatement();
// 4.向数据库发送查询语句
String sql = "select * from users";
rs = stmt.executeQuery(sql);
// 5.遍历结果集,获取查询的数据
while (rs.next()) {// 跳转搭配下一行,在某一行的值遍历完毕后,才会跳转到下一行去遍历
int id = rs.getInt(1);
String name = rs.getString("name");
String psw = rs.getString(3);
String email = rs.getString("email");
Date birthday = rs.getDate("birthday");
System.out.println(id + " " + name + " " + psw + " " + email + " " + birthday);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// 6.关闭连接,释放资源
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
}
注意:1.在开发中,通常使用Class.forName(“com.mysql.jdbc.Driver”)注册驱动,不用DriverManger注册驱动方法,因为这个方法注册了2次驱动。
2.关闭资源时,关闭资源的代码一定要放在finally块里,因为前面的代码无论是否发生异常,这个块里的关闭资源代码总会被执行,因为数据库连接资源很宝贵,数据库连接资源时是有限的,所以一定要关。