JDBC API
JDBC API可做三件事:与数据库建立连接、发送SQL语句,处理结果
4个重要环节:
- DriverManager类:依据不同数据库,管理JDBC驱动
- Connection接口:连接数据库并担任传送数据的业务
- Statement接口:由Connection产生,负责执行SQL语句
- ResultSet接口:负责保存Statement执行后所产生的查询结果
JDBC代码模板
- 把JDBC驱动类载入到Java虚拟机中。
Class.forName("JDBC驱动类的名称");
如果系统中不存在给定的类,则会引发异常,异常类型为ClassNotFoundException。
- 加载驱动,并与数据库建立连接。DriverManager类跟踪已注册的驱动程序,当调用getConnection()方法时,它会搜索整个驱动程序列表,直到找到一个能够连接至数据连接字符串中指定的数据库的驱动程序。加载此驱动程序之后,将使用DriverManager类的getConnection()方法建立与数据库的连接。此方法接收三个参数,分别表示URL、用户名和密码。
Connection con=DriverManager.getConnection(数据库连接字符串,数据库用户名,密码);
- 发送SQL语句,并得到结果集。一旦连接建立,就是用该连接创建Statement接口的实例,并将SQL语句传递给它所连接的数据库,并返回类型为ResultSet的对象,它包含执行SQL查询的结果。
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery("select a,b,c from table1");
- 处理结果。使用ResultSet对象的next()方法将光标指向下一行。最初光标位于第一行之前,因此第一次调用next()方法将把光标置于第一行上。如果到达结果集的末尾,则ResultSet的next()方法会返回false。方法getXXX提供了获取当前行中某列值的途径,列名或列号可用于标识要从中获取数据的列。例如,如果数据表中第一列的列名为a,存储类型为整型,则可以使用两种方法获取存储在该列中的值,如:int x=rs.getInt("a");或者:int x=rs.getInt(1);
while(rs.next()){
int x=rs.getInt("s");
String s=rs.getString("b");
float f=rs.getFloat("c");
}
JDBC应用
案例需求:对学生信息表进行管理,要求如下:
学生信息表存储在MySQL中,通过JDBC对学生信息进行增、删、改、查操作。
数据库test,表students,表结构如下:
字段名称 | 字段说明 | 数据类型 | 大小 |
---|---|---|---|
studentId | 学号 | varchar | 12 |
studentName | 姓名 | varchar | 30 |
studentPwd | 密码 | varchar | 12 |
sex | 性别 | varchar | 2 |
classId | 班级Id | int | 8 |
步骤如下
- 新建项目,导入MySQL驱动,并添加到类路径中。
- 连接数据库的类ConnectionManager。专门负责建立数据库的连接以及执行关闭操作。
import java.sql.*;
public class ConnectionManager {
private static final String DRIVER_CLASS ="com.mysql.jdbc.Driver";
private static final String DATABASE_URL = "jdbc:mysql://localhost:3306/DatabaseName?characterEncoding=UTF-8";
private static final String DATABASE_USRE = "root";
private static final String DATABASE_PASSWORD = "123456";
/** 返回连接 */
public static Connection getConnection() {
Connection dbConnection = null;
try {
Class.forName(DRIVER_CLASS);
dbConnection = DriverManager.getConnection(DATABASE_URL,DATABASE_USRE, DATABASE_PASSWORD);
} catch (Exception e) { e.printStackTrace(); }
return dbConnection;
}
/** 关闭连接*/
public static void closeConnection(Connection dbConnection) {
try {
if (dbConnection != null && (!dbConnection.isClosed())) {
dbConnection.close();
}
} catch (SQLException sqlEx) { sqlEx.printStackTrace(); }
}
/**关闭结果集*/
public static void closeResultSet(ResultSet res) {
try {
if (res != null) {
res.close();
}
} catch (SQLException e) { e.printStackTrace(); }
}
/** 关闭语句*/
public static void closeStatement(PreparedStatement pStatement) {
try {
if (pStatement != null) {
pStatement.close();
}
} catch (SQLException e) { e.printStackTrace(); }
}
public static void closeStatement(Statement statement) {
try {
if (statement != null) {
statement.close();
}
} catch (SQLException e) { e.printStackTrace(); }
}
}
注:如果不关闭Statement对象和数据库连接,它们会一直占用服务器资源,直到Java垃圾收集程序来回收它,有潜在的内存问题。
学生类
public class Students {
private String studentId;
private String studentName;
private String studentPwd;
private String sex;
private int classId;
public Students(String studentId, String studentName, String studentPwd,String sex, int classId) {
this.studentId = studentId;
this.studentName = studentName;
this.studentPwd = studentPwd;
this.sex = sex;
this.classId = classId;
}
//各属性的setter方法和getter方法
}
Statement语句
使用Connection对象可以生成Statement实例。Statement接口中包含很多基本的数据库操作方法,下面列出了执行SQL命令的三个方法。
(1)ResultSet executeQuery(String sql):可以执行SQL查询并获取到ResultSet对象。
(2)int executeUpdate(String sql):可以执行插入、删除、更新等操作,返回值是执行该操作所影响的行数。
(3)boolean execute(String sql):这是一个最为一般的执行方法,可以执行任意SQL语句,然后获得一个布尔值,表示是否返回ResultSet。
例:使用Statement插入数据
import java.sql.*;
public class StudentsDB {
public static void main(String[] args) {
Connection con=null;
Statement statement=null;
try {
con = ConnectionManager.getConnection();//1.创建连接
String strSql = "insert into Students values('2013880123','康熙','1234','男',10201541)";
statement = con.createStatement();//2.创建语句总管
statement.execute(strSql);//3.语句总管执行SQL语句
} catch (SQLException e) {
e.printStackTrace();
}finally{
ConnectionManager.closeStatement(statement);//4.关闭语句总管、连接
ConnectionManager.closeConnection(con);
}
}
}
PreparedStatement语句
PreparedStatement接口继承自Statement接口,PreparedStatement比普通的Statement对象使用起来更加灵活,更有效率。
PreparedStatement实例包含已编译的SQL语句,SQL语句可具有一个或多个输入参数,这些输入的值在SQL语句创建时未被指定,而是为每个输入参数保留一个问号("?")作为占位符。
PreparedStatement pstmt=con.preparedStatement("update Table1 set a=? where b=?")
在执行PreparedStatement对象之前,必须设置每个输入参数的值。可通过调用setXXX方法来完成,其中XXX是与该参数相应的类型。例如,如果参数具有Java类型的long,则使用的方法就是setLong。setXXX方法的第一个参数是要设置的参数的序数位置,第二个参数是设置给该参数的值。
pstmt.setLong(1,123456789);
pstmt.setInt(2,10);
由于PreparedStatement对象已编译过,所以其执行速度要快于Statement对象。因此,多次执行的SQL语句应被创建为Preparedment对象,以提高效率。
例:使用PreparedStatement插入数据
import java.sql.*;
public class StudentsDB {
public static void main(String[] args) {
Connection con = null;
PreparedStatement pStatement = null;
try {
con = ConnectionManager.getConnection(); //1.创建连接
String strSql = "insert into students values(?,?,?,?,?)";
pStatement = con.prepareStatement(strSql); //2.创建预处理语句总管
pStatement.setString(1, "2008110106");
pStatement.setString(2, "乾隆");
pStatement.setString(3, "2008");
pStatement.setString(4, "男");
pStatement.setInt(5, 10201541);
pStatement.executeUpdate(); //3.语句总管执行SQL语句
} catch (SQLException sqlE) {
sqlE.printStackTrace();
} finally {
ConnectionManager.closeStatement(pStatement);//4.关闭语句总管、连接
ConnectionManager.closeConnection(con);
}
}
}
例:使用PreparedStatement删除数据
import java.sql.*;
public class StudentsDB {
public static void main(String[] args) {
Connection con = null;
PreparedStatement pStatement = null;
try {
con = ConnectionManager.getConnection(); //1.创建连接
String strSql = "delete from students where studentName=?";
pStatement = con.prepareStatement(strSql); //2.创建预处理语句总管
pStatement.setString(1, "乾隆");
int row=pStatement.executeUpdate(); //3.语句总管执行SQL语句
System.out.println("成功删除"+row+"条数据!");
} catch (SQLException sqlE) {
sqlE.printStackTrace();
} finally {
ConnectionManager.closeStatement(pStatement);//4.关闭语句总管、连接
ConnectionManager.closeConnection(con);
}
}
}
例:使用PreparedStatement更新数据
import java.sql.*;
public class StudentsDB {
public static void main(String[] args) {
Connection con = null;
PreparedStatement pStatement = null;
try {
con = ConnectionManager.getConnection();//1.创建连接
String strSql = "update students set studentName = ? where studentId = ?";
pStatement = con.prepareStatement(strSql);//2.创建预处理语句总管
pStatement.setString(1, "玄烨");
pStatement.setString(2,"2013880123" );
int row = pStatement.executeUpdate();//3.语句总管执行SQL语句
System.out.println("成功更新了"+row+"行数据!");
} catch (SQLException sqlE) {
sqlE.printStackTrace();
} finally {
ConnectionManager.closeStatement(pStatement);//4.关闭语句总管、连接
ConnectionManager.closeConnection(con);
}
}
}
例:使用PreparedStatement查询数据
import java.sql.*;
public class StudentsDB {
public static void main(String[] args) {
Connection con = null;
PreparedStatement pStatement = null;
ResultSet resSet=null;
try {
con = ConnectionManager.getConnection(); //1.创建连接
String strSql = "select * from students where studentName=?";
pStatement = con.prepareStatement(strSql); //2.创建预处理语句总管
pStatement.setString(1, "谢亚飞");
resSet=pStatement.executeQuery(); //3.语句总管执行SQL语句
if(resSet.next()){
System.out.println("学号为:"+resSet.getString(1));
System.out.println("姓名为:"+resSet.getString(2));
System.out.println("密码为:"+resSet.getString(3));
System.out.println("性别为:"+resSet.getString(4));
System.out.println("班级号为:"+resSet.getInt(5));
}
} catch (SQLException sqlE) {
sqlE.printStackTrace();
} finally {
ConnectionManager.closeStatement(pStatement);//4.关闭语句总管、连接
ConnectionManager.closeConnection(con);
}
}
}
例:使用PreparedStatement查询所有学生信息
import java.util.*;
import java.sql.*;
import com.vo.Students;
public class StudentsDB {
public List<Students> getAllStudents(){
List<Students> allStudents=new ArrayList<Students>();
Connection con=null;
PreparedStatement pStatement=null;
ResultSet res=null;
try {
con = ConnectionManager.getConnection();//1.创建连接
String sql = "select * from Students";
pStatement = con.prepareStatement(sql);//2.创建预处理语句总管
res = pStatement.executeQuery();//3.语句总管执行查询
while (res.next()) {
String studentId = res.getString(1);
String studentName = res.getString("studentName");
String studentPwd = res.getString(3);
String sex = res.getString("sex");
int classId = res.getInt(5);
//构造方法组装成一个Students对象stu
Students stu = new Students(studentId, studentName, studentPwd, sex, classId);
allStudents.add(stu);
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
ConnectionManager.closeResultSet(res);//5.关闭结果集 对象、语句总管、连接
ConnectionManager.closeStatement(pStatement);
ConnectionManager.closeConnection(con);
}
return allStudents;
}
public static void main(String[] args) {
StudentsDB db=new StudentsDB();
List<Students> all=db.getAllStudents();
for(int i=0;i<all.size();i++){
Students stu=(Students)all.get(i);
System.out.println(stu);
}
}
}
案例:学生信息系统,要求在系统的前台页面上显示所有的从数据库中取出的 学生信息。
步骤分解:
(1)设计数据库表结构,表名为students。
(2)确定存储对象,存储类型为学生类(Students.java),属性的设置与students表的各字段保持一致。
(3)通过JDBC访问数据库,创建类StudentsDB.java,用来查询数据库,并返回allstudents对象的集合。
(4)编写JSP文件showStudents.jsp,用来在页面中逐条逐行输出 学生的信息。
<%@ page language="java" pageEncoding="gbk"%>
<%@ page import="java.util.*,com.vo.Students,com.db.StudentsDB6" %>
<!DOCTYPE HTML>
<html>
<head><title>显示所有学生信息</title></head>
<body>
<table border="2">
<tr><th>学号</th><th>姓名</th><th>密码</th><th>性别</th><th>班级号</th></tr>
<%
List<Students> all=new ArrayList<Students>();
StudentsDB db=new StudentsDB();
all=db.getAllStudents();
if(all.size()!=0){
for(int i=0;i<all.size();i++){
Students stu=(Students)all.get(i);
%>
<tr>
<td><%=stu.getStudentId() %></td>
<td><%=stu.getStudentName() %></td>
<td><%=stu.getStudentPwd() %></td>
<td><%=stu.getSex() %></td>
<td><%=stu.getClassId() %></td>
</tr>
<%
} //end for
}//end if
%>
</table>
</body>
</html>