JDBC基础
1. JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API),定义了用来访问数据库的标准Java类库,使用这个类库可以以一种标准的方法、方便地访问数据库资源
2. JDBC为访问不同的数据库提供了一种统一的途径,为开发者屏蔽了一些细节问题。
3. JDBC的目标是使Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,这样就使得程序员无需对特定的数据库系统的特点有过多的了解,从而大大简化和加快了开发过程。
JDBC驱动程序分类:
1. JDBC驱动程序:各个数据库厂商根据JDBC的规范制作的 JDBC 实现类的类库
2. JDBC驱动程序总共有四种类型:
第一类:JDBC-ODBC桥。
第二类:部分本地API部分Java的驱动程序。
第三类:JDBC网络纯Java驱动程序。
第四类:本地协议的纯 Java 驱动程序。
第三、四两类都是纯Java的驱动程序,因此,对于Java开发者来说,它们在性能、可移植性、功能等方面都有优势。
Driver 接口:
Java.sql.Driver 接口是所有 JDBC 驱动程序需要实现的接口。这个接口是提供给数据库厂商使用的,不同数据库厂商提供不用的实现.在程序中不需要直接去访问实现了 Driver 接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现
加载与注册 JDBC 驱动:
1. 加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动的类名
2. DriverManager 类是驱动程序管理器类,负责管理驱动程序
3. 通常不用显式调用 DriverManager 类的 registerDriver() 方法来注册驱动程序类的实例,因为 Driver 接口的驱动程序类都包含了静态代码块,在这个静态代码块中,会调用DriverManager.register Driver() 方法来注册自身的一个实例.
几种常用数据库的JDBC URL:
1. 对于 Oracle 数据库连接,采用如下形式: jdbc:oracle:thin:@localhost:1521:sid
2. 对于 SQLServer 数据库连接,采用如下形式: jdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sid
3. 对于 MYSQL 数据库连接,采用如下形式: jdbc:mysql://localhost:3306/sid
数据库的访问:
数据库连接被用于向数据库服务器发送命令和 SQL 语句,在连接建立后,需要对数据库进行访问,执行 sql 语句.在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:Statement
PrepatedStatement , CallableStatement
API:
1. java.sql.DriverManager用来装载驱动程序,获取数据库连接。
2. java.sql.Connection完成对某一指定数据库的联接
3. java.sql.Statement在一个给定的连接中作为SQL执行声明的容器,他包含了两个重要的子类型。
4. Java.sql.PreparedSatement 用于执行预编译的sql声明
5. Java.sql.CallableStatement用于执行数据库中存储过程的调用
6. java.sql.ResultSet对于给定声明取得结果的途径
下面通过一些实例来巩固下以上的概念性知识点:第一个例子呢是关于数据库连接的最基本的而且最常操作的一段程序。下面的程序呢,佟刚老师都做了详细的注释,很容易让人理解的!
package cn.itcast.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class TestConnection {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//得到数据库连接的基本原理:
//1. 注册驱动程序 DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//2. 由 DriverManager 负责连接数据库:用户名, 密码, 连接数据库的 url(该 url 包含 a. 连接哪个数据库 b. 数据库的主机 ip c. 数据库端口)
//1. 准备连接数据库所必须的 4 个字符串 : user, password, url, driver
String user = "root";
String password = "1230";
String url = "jdbc:mysql://localhost:3309/itcast";
//协议: 子协议://数据库主机 ip: 端口/数据库名称
String driver = "com.mysql.jdbc.Driver";
//2. 加载驱动
Class.forName(driver);
//DriverManager.registerDriver(new com.mysql.jdbc.Driver());
//DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
//3. 获取连接
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println("Connection: " + conn);
}
}
对于这个程序在下面的小应用里面将会封装在一个类里面.看看下面的一个小WEB应用吧 !
首先,下面是在mysql里面建立的表
DROP TABLE IF EXISTS `customer`;
CREATE TABLE `customer` (
`id` varchar(20) default NULL,
`name` varchar(30) default NULL,
`age` int(11) default NULL,
`email` varchar(20) default NULL,
`birthday` date default NULL,
`salary` double default NULL
) ENGINE=InnoDB DEFAULT CHARSET=gb2312;
INSERT INTO `customer` (`id`,`name`,`age`,`email`,`birthday`,`salary`) VALUES ('10002','Jerry',22,'jerry@sohu.com','1988-03-05',2000);
INSERT INTO `customer` (`id`,`name`,`age`,`email`,`birthday`,`salary`) VALUES ('10001','Tom',21,'tom@sohu.com','1998-02-12',1000);
INSERT INTO `customer` (`id`,`name`,`age`,`email`,`birthday`,`salary`) VALUES ('10003','Bob',25,NULL,NULL,2500);
INSERT INTO `customer` (`id`,`name`,`age`,`email`,`birthday`,`salary`) VALUES ('10004','Mike',28,'mike@163.com',NULL,2900);
INSERT INTO `customer` (`id`,`name`,`age`,`email`,`birthday`,`salary`) VALUES ('10005','Jack',31,NULL,'1987-09-18',3100);
先建一个customer类:
package cn.itcast.webapp.domain;
public class Customer {
private int id;
private String name;
private String address;
private String phone;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "name: ^^" + this.name + "^^, address: ^^" + this.address + "^^, phone: ^^" + this.phone + "^^";
}
}
再写个数据库连接的类:
package cn.itcast.webapp.db;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DBManager {
public static Connection getConnection(){
Connection conn = null;
String user = "root";
String password = "1230";
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3309/test";
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, user, password);
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new RuntimeException("加载数据库驱动异常");
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("连接数据库驱动异常: 请校验数据库的用户名, 密码及端口信息");
}
return conn;
}
public static void releaseDBSource(ResultSet rs, Statement st, Connection conn){
new FileNotFoundException();
try {
if(rs != null)
rs.close();
if(st != null)
st.close();
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("关闭数据库连接异常");
}
}
}
第三步要写servlet类:这个步骤是在今后开发中很重要的一步几乎所有的WEB 应用程序都是通过写servlet,作为中间的部分,对前面和后面部分起的交互,所以,很重要. 而且web.xml的配置都要经过这里,所以好好掌握. 现在就举出增删改查的例子:
AddCustomerServlet :
package cn.itcast.webapp.servlet;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.itcast.webapp.dao.CustomerDAO;
import cn.itcast.webapp.domain.Customer;
public class AddCustomerServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1. 获取表单信息
String name = null;
String phone = null;
String address = null;
name = request.getParameter("name");
phone = request.getParameter("phone");
address = request.getParameter("address");
//2. 把获取到的参数值封装成一个对象
Customer cust = null;
cust = new Customer();
cust.setAddress(address);
cust.setName(name);
cust.setPhone(phone);
String forwardPage = null;
try {
//3. 调用 CustomerDAO 的 saveCustomer 方法
//4. 根据方法是否出现异常, 决定要派发的页面
CustomerDAO.saveCustomer(cust);
forwardPage = "success.jsp";
} catch (Exception e) {
e.printStackTrace();
forwardPage = "addCustomer.jsp";
request.setAttribute("errorInfo", e.getMessage());
}
//5. 派发页面
RequestDispatcher dispatcher = null;
dispatcher = request.getRequestDispatcher(forwardPage);
dispatcher.forward(request, response);
}
}
UpdateCustomerServlet:
package cn.itcast.webapp.servlet;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.itcast.webapp.dao.CustomerDAO;
import cn.itcast.webapp.domain.Customer;
public class UpdateCustomerServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1. 获取客户端提交的表单信息: id, name, address, phone
String name = null;
String address = null;
String phone = null;
String id = null;
name = request.getParameter("updatename");
address = request.getParameter("updateaddress");
phone = request.getParameter("updatephone");
id = request.getParameter("updateid");
String forwardPage = null;
//4. 根据上述方法是否出现异常决定派发页面
try {
//2. 封装表单信息到一个 Customer 对象中
Customer cust = null;
cust = new Customer();
cust.setAddress(address);
cust.setId(Integer.parseInt(id));
cust.setName(name);
cust.setPhone(phone);
//3. 调用 CustomerDAO.updateCustomer(Customer cust) 方法进行 customer 信息的更新
CustomerDAO.updateCustomer(cust);
//a. 若不出现异常, 则派发到 searchCustomers.jsp 页面, 显示更改后的信息
forwardPage = "searchCustomerServlet";
} catch (NumberFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
request.setAttribute("errorInfo", "id 格式错误!");
//b. 若出现异常, 则返回到 updateCustomer.jsp 页面, 显示异常信息, 并在表单域中回显填入的值
forwardPage = "updateCustomer.jsp";
} catch(Exception ex){
ex.printStackTrace();
request.setAttribute("errorInfo", ex.getMessage());
//b. 若出现异常, 则返回到 updateCustomer.jsp 页面, 显示异常信息, 并在表单域中回显填入的值
forwardPage = "updateCustomer.jsp";
}
//5. 页面的派发
RequestDispatcher dispatcher = null;
dispatcher = request.getRequestDispatcher(forwardPage);
dispatcher.forward(request, response);
}
}
SearchCustomersServlet:
package cn.itcast.webapp.servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.itcast.webapp.dao.CustomerDAO;
import cn.itcast.webapp.domain.Customer;
public class SearchCustomersServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1. 解析客户端表单的请求信息
String name = null;
String address = null;
String phone = null;
name = request.getParameter("name");
address = request.getParameter("address");
phone = request.getParameter("phone");
System.out.println("SearchCustomersServlet: name: ^^" + name + "^^, address: ^^" +address + "^^, phone: ^^" + phone + "^^");
//2. 将请求信息封装到一个 JavaBean(Customer) 中
Customer cust = new Customer();
cust.setAddress(address);
cust.setName(name);
cust.setPhone(phone);
//3. 调用 CustomerDAO 的 searchCustomers(Customer customer) 方法
//4. 根据方法是否出现异常, 决定派发的页面
String forwardPage = null;
try {
List custs = null;
custs = CustomerDAO.searchCustomers(cust);
forwardPage = "searchCustomers.jsp";
request.setAttribute("customers", custs);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("errorInfo", e.getMessage());
forwardPage = "searchCustomers.jsp";
}
//5. 页面的派发
RequestDispatcher dispatcher = null;
dispatcher = request.getRequestDispatcher(forwardPage);
dispatcher.forward(request, response);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.doPost(req, resp);
}
}
DeleteCustomerServlet:
package cn.itcast.webapp.servlet;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.itcast.webapp.dao.CustomerDAO;
public class DeleteCustomerServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1. 解析客户端请求信息: id
String id = null;
id = request.getParameter("id");
//2.调用 CustomerDAO 的 deleteCustomerById(int id) 方法
//3. 根据上述方法是否出现异常, 决定要派发的页面
String forwardPage = null;
try {
//a. 不出现异常: 回到 searchCustomers.jsp 显示所有客户的信息
CustomerDAO.deleteCustomerById(Integer.parseInt(id));
forwardPage = "searchCustomerServlet";
} catch (NumberFormatException e) {
e.printStackTrace();
//b. 出现异常: 回到 searchCustomers.jsp 显示错误信息
forwardPage = "searchCustomer.jsp";
request.setAttribute("errorInfo", "id 号格式错误!");
}catch(Exception ex){
forwardPage = "searchCustomer.jsp";
request.setAttribute("errorInfo", ex.getMessage());
}
//4. 页面的派发
RequestDispatcher dispatcher = null;
dispatcher = request.getRequestDispatcher(forwardPage);
dispatcher.forward(request, response);
}
}
}
}