任务目标
1.了解数据库在web应用中的作用。
2.了解什么是JDBC
3.了解JDBC常用的API
4.利用JDBC能独立编写调用数据库记录的案例
数据库在web应用中的作用
- 平时见到的网站:学校网站、网易等。
- 本课程完成项目:web书城网站
JDBC简介
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC为工具/数据库开发人员提供了一个标准的API,据此可以构建更高级的工具和接口,使数据库开发人员能够用纯 Java API 编写数据库应用程序。
不同种类的数据库(如MySQL、Oracle等)在其内部处理数据的方式是不同的。如果直接使用数据库厂商提供的访问接口操作数据库,应用程序的可移植性就会变得很差。例如,用户当前在程序中使用是MySQL提供的接口操作数据库,如果换成Oracle数据库,则需要重新使用Oracle 数据库提供的接口,这样代码的改动量会非常大。有了JDBC后,这种情况就不复存在了,因为它要求各个数据库厂商按照统一的规范来提供数据库驱动联系,所以用户就不必直接与底层的数据库交互,这使得代码的通用性更强。
从图中要以看出,JDBC在应用程序与数据库之间起到了一个桥梁作用。当应用程序使用JDBC访问特定的数据库时,需要通过不同数据库驱动与不同的数据库进行连接,连接后即可对该数据库进行相应的操作
创建JDBC程序的步骤
1.加载并注册驱动
注册数据库驱动的具体方式如下:
DriverManager.registerDriver(Driver driver);
或者
Class.forName(“DriverName”);
在注册数据库驱动时,虽然两种方法可以完成,但第一种会使数据库驱动被注册两次。这是因为Drive类的源码中,已经在静态代码块中完成了数据库驱动的注册。所以,为了避免数据库驱动被重复注册,我们一般都使用第二种方式Class.forName(“DriverName”);
2.通过DriverManager获取数据库连接
具体方式:
Connection conn=DriverManager.getConnection(String url,String user,String pwd)
说明:
(1)DriverManager类用于加载JDBC驱动并且创建与数据库的连接。在DriverManager类中的getConnection方法用于建立和数据库的连接,并且返回连接的Connection对象。
3个参数:
url:表示连接数据库的URL地址。书写格式如下:
jdbc:mysql://hostname:port/databasename
mysql批的是mysql数据库。Hostname指的是主机的名称(如果数据库在本机中,hostname可以为localhost或127.0.0.1; 如果要连接的数据库在其他电脑上hostname为所要连接电脑的IP),Port指的是连接数据库的端口号(mysql默认为3306),databasename指的是mysql中相应的数据库的名称。
User:登录数据库名
Pwd: 登录数据库密码
如果连接本机名为jdbc的数据库,代码如下:
Connection conn=DriverManager.getConnection(“jdbc:mysql://localhost:3306/jdbc”,”sa”,”sa”)
(2)Connection接口代表Java程序和数据库的连接,只有获得该连接对象后才能访问数据库,并操作数据库。
3.通过connection对象创建statement对象
Statement用于执行静态的sql语句,并返回一个结果对象,该接口的对象通过connection实例的createStatement()方法获得。利用该对象把静态的sql语句发送到数据库编译执行,然后返回数据库的处理结果。
Connection创建statement的方式有如下3种:
createStatement():创建基本的Statement对象
prepareStatement():创建PreparedStatement对象
prepareCall():创建CallableStatement 对象
4.使用statement执行sql语句
所有的Statement都有如下3种执行sql语句的方法。
Execute():可以执行任何sql语句
executeQuery():通常执行查询语句,执行后返回代表结果集的ResultSet对象
executeUpdate():主要用于执行DML的DDL语句。执行DML语句,如 insert、update或delete时,返回受sql语句影响的行数,执行ddl语句返回0(ddl:create table ,drop table等)
以executeQuery方法为例,其使用方式如下:
ResultSet rs=stmt.executeQuery(sql)
5.执行ResultSet结果集
如果执行的sql语句是查询语句,执行结果将返回一个ResultSet对象,该对象里保存了sql语句查询的结果。程序可以通过操作该ResultSet对象来取出查询结果
6.关闭连接,释放资源
每次操作数据库结束后都要关闭数据库连接,释放资源,包括关闭ResultSet、Statement和Connection等资源。
至此,JDBC程序大致实现步骤已经讲解完成。接下来,依照上面所讲解的步骤来演示JDBC的使用。
五、第一个JDBC程序实现
1. 数据库环境搭建
数据库驱动jar包
数据库创建代码
/*在MySQL中创建一个名称为chapter01的数据库,
然后在该数据库中创建一个users表,SQL语句如下所示*/
CREATE DATABASE jdbc;
USE jdbc;
CREATE TABLE users(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(40),
password VARCHAR(40),
email VARCHAR(60),
birthday DATE
)CHARACTER SET utf8 COLLATE utf8_general_ci;
/*数据库和表创建成功后,再向users表中插入3条数据,SQL语句如下所示*/
INSERT INTO users(NAME,PASSWORD,email,birthday)
VALUES('zs','123456','zs@sina.com','1980-12-04');
INSERT INTO users(NAME,PASSWORD,email,birthday)
VALUES('lisi','123456','lisi@sina.com','1981-12-04');
INSERT INTO users(NAME,PASSWORD,email,birthday)
VALUES('wangwu','123456','wangwu@sina.com','1979-12-04');
/*为了查看数据是否添加成功,使用SELECT语句查询users表,SQL语句如下所示*/
SELECT * FROM users;
2.创建项目环境,导入数据库驱动
3.编写JDBC程序
public static void main(String[] args) throws SQLException {
Statement stmt = null;
ResultSet rs = null;
Connection conn = null;
try {
// 1. 注册数据库的驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.通过DriverManager获取数据库连接
String url = "jdbc:mysql://localhost:3306/jdbc";
String username = "root";
String password = "root";
conn = DriverManager.getConnection (url, username,
password);
// 3.通过Connection对象获取Statement对象
stmt = conn.createStatement();
// 4.使用Statement执行SQL语句。
String sql = "select * from users";
rs = stmt.executeQuery(sql);
// 5. 操作ResultSet结果集
System.out.println("id | name | password | email | birthday");
while (rs.next()) {
int id = rs.getInt("id"); // 通过列名获取指定字段的值
String name = rs.getString("name");
String psw = rs.getString("password");
String email = rs.getString("email");
Date birthday = rs.getDate("birthday");
System.out.println(id + " | " + name + " | " + psw + " | " + email
+ " | " + birthday);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally{
// 6.回收数据库资源
if(rs!=null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if(stmt!=null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn!=null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
}
ResultSet对象
Statement stmt=conn.createStatement(参数一,参数二)
createStatement返回的Statement对象是执行sql语句用的
第一个参数可以取值为
ResultSet.RTYPE_FORWORD_ONLY,只可向前滚动,也就是只能从第一个一直移动到最后一个。该选项为默认选项。(针对jdbc2.0)
ResultSet.TYPE_SCROLL_INSENSITIVE,双向滚动,但不及时更新,就是如果数据库里的数据修改过,并不在ResultSet中反应出来。
ResultSet.TYPE_SCROLL_SENSITIVE,双向滚动,并及时跟踪数据库的更新,以便更改ResultSet中的数据。
第二个参数可以取值为
ResultSet.CONCUR_READ_ONLY:这是缺省值,指定不可以更新 ResultSet
ResultSet.CONCUR_UPDATABLE:指定可以更新 ResultSet
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/chapter01";
String username = "root";
String password = "root";
conn = DriverManager.getConnection(url, username, password);
String sql = "select * from users";
Statement st =conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
ResultSet rs = st.executeQuery(sql);
System.out.print("第2条数据的name值为:");
rs.absolute(2); //将指针定位到结果集中第2行数据
System.out.println(rs.getString("name"));
System.out.print("第1条数据的name值为:");
rs.beforeFirst(); //将指针定位到结果集中第1行数据之前
rs.next(); //将指针向后滚动
System.out.println(rs.getString("name"));
rs.previous();
System.out.print("pervious name值为:");
System.out.print("第4条数据的name值为:");
rs.afterLast(); //将指针定位到结果集中最后一条数据之后
rs.previous(); //将指针向前滚动
System.out.println(rs.getString("name"));
} catch (Exception e) {
e.printStackTrace();
} finally { // 释放资源
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
附recordset相关方法:
public boolean previous() 将游标向上移动,该方法返回boolean型数据,当移到结果集第一行之前时,返回false。
public void beforeFirst 将游标移动到结果集的初始位置,即在第一行之前。
public void afterLast() 将游标移到结果集最后一行之后。
public void first() 将游标移到结果集的第一行。
public void last() 将游标移到结果集的最后一行。
public boolean isAfterLast() 判断游标是否在最后一行之后。
public boolean isBeforeFirst() 判断游标是否在第一行之前。
public boolean ifFirst() 判断游标是否指向结果集的第一行。
public boolean isLast() 判断游标是否指向结果集的最后一行。
public int getRow() 得到当前游标所指向行的行号,行号从1开始,如果结果集没有行,返回0。
public boolean absolute(int row) 将游标移到参数row指定的行号。如果row取负值,就是倒数的行数,absolute(-1)表示移到最后一行,absolute(-2)表示移到倒数第2行。当移动到第一行前面或最后一行的后面时,该方法返回false