12.1 JDBC编程

JDBC简介

  1. JDBC:Java Database Connectivity,Java数据库连接
  2. JDBC为开发者使用数据库提供了统一的编程接口,它由一组java类和接口组成,是java程序与数据库系统通信的标准API。JDBC API使得开发人员可以使用纯java的方式来连接数据库,并执行操作。
  3. 不同厂商的数据库程序代码不同,无法使用一套代码来使用所有数据库,所以sun公司提出了一套API,凡是数据库想与java进行连接的,数据库厂商自己必须实现JDBC这套接口。对应的JDBC实现被称为此数据库的数据库驱动。
  4. 使用不同的数据库需要下载不同的数据库驱动包。

访问数据库流程

  1. 加载JDBC驱动程序
  2. 连接数据库
  3. 为数据库传递查询和更新指令
  4. 处理数据库 响应并返回 的结果

JDBC下载

  1. MySQL数据库驱动包下载地址:http://dev.mysql.com/downloads/connector/j/(虽然只有4.5M,但直接下载速度非常慢)
    p1
  2. 解压后得到 jar 文件,然后在对应的项目中导入该文件。
    p2
    p3

环境

  • win10、eclipse、JDK11、Mysql8.0.21、JDBC8.0.21
  • 注意:Mysql8以上版本的数据库连接方式与以下版本有所不同。

编程中的基本使用

建立数据库连接

代码

//加载JDBC驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//建立与数据库的连接(连接对象内部包含了Socket对象,是一个远程连接;比较耗时,)
//真正开发中使用连接池来管理连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/school"
					+ "?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC","root","password");

注意:
(1)加载数据库驱动语句 适用于MySql8以上版本。
(2)MySQL 8.0 以上版本不需要建立 SSL 连接的,需要显示关闭。
(3)allowPublicKeyRetrieval=true 允许客户端从服务器获取公钥。
(4)最后还需要设置 中央标准时间。
(5)最后两个字符串应分别设置为登入数据库的 用户名 和 密码。

执行sql语句
  1. Statement接口
    (1)用于执行静态SQL语句并返回它所生成结果的对象。
    (2)三种Statement类:
            [1] Statement:
            实例对象通过createStatement创建,用于发送简单的SQL语句(不带参数的SQL语句,如果带参数可能会发生SQL注入)。
            [2] PreparedStatement:
            继承自Statement接口,实例对象通过prepareStatement创建,用于发送含有一个或多个输入参数的sql语句。PreparedStatement对象比Statement对象的效率更高,并且可以防止sql注入。一般都是用PrepareStatement。
            [3] CallableStatement:
            继承自PreparedStatement。由方法prePareCall创建,用于调用存储过程。
    (3)常用的Statement方法:
            execute(): 运行语句,返回 是否有结果集。
            executeQuery(): 运行select语句,返回ResultSet结果集。
            executeUpdate(): 运行insert/update/delete操作,返回 更新的行数。
  2. Statement执行对象
    (1)使用场景:普通的不带参数的简单SQL语句。
    (2)特点:每次的执行都需要编译SQL,效率低。
    (3)代码示例:
//2. 使用Statement对象 执行sql语句,可能会发生sql注入
Statement stmt = conn.createStatement();
String sql = "insert into student values (103, \"王五\",2);";	//拼接sql语句
stmt.execute(sql);	//执行
  1. PreparedStatement执行对象
    (1)使用场景:执行具有一个或多个可变参数的SQL。
    (2)特点:PreparedStatement会预编译,会被缓冲,在缓存区中可以发现预编译的命令,虽然会被再次解析,但不会被再次编译,能够有效提高系统性能。
    (3)代码(两种方式)
    示例1:
//2. 使用PrepareStatement执行sql语句,可以避免sql注入
String sql = "insert into student values (?, ?, ?)";	//?号是占位符
PreparedStatement ps = conn.prepareStatement(sql);	//创建PreparedStatement对象
ps.setInt(1, 104);	//第一个参数是占位符的索引(从1开始),第二个参数是占位符对应的实际值
ps.setString(2, "赵六");
ps.setInt(3, 2);
ps.execute();	//执行

        示例2:

//2. 使用PrepareStatement执行sql语句,可以避免sql注入
String sql = "insert into student values (?, ?, ?)";	//?号是占位符
PreparedStatement ps = conn.prepareStatement(sql);	//创建PreparedStatement对象
ps.setObject(1, 105);
ps.setObject(2, "小明");
ps.setObject(3, 3);
ps.execute();	//执行
  1. 关闭连接
    后创建的先关闭;如果使用try…catch…处理异常,则要分开关闭。
  2. 以PreparedStatement执行对象为例整个sql语句执行过程
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * 测试PreparedStatement的基本用法
 * @author dxt
 *
 */
public class Demo03 {
	public static void main(String[] args) {
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			//1、连接数据库
			Class.forName("com.mysql.cj.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/school"
					+ "?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC", "root", "root");
			//2. 使用PrepareStatement执行sql语句,可以避免sql注入
			String sql = "insert into student values (?, ?, ?)";	//?号是占位符
			ps = conn.prepareStatement(sql);	//创建PreparedStatement对象
			ps.setObject(1, 105);	//第一个参数是占位符的索引(从1开始),第二个参数是占位符对应的实际值
			ps.setObject(2, "小明");
			ps.setObject(3, 3);
			ps.execute();	//执行
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(ps != null) {	
					ps.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				if(conn != null) {	
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}	
		}
	}
}
  1. sql注入问题
    示例代码
Statement stmt = conn.createStatement();
//测试SQL注入
String id = "5 or 1=1";	//传入的参数中含有恶意代码
String sql = "delete from student where id="+id;
stmt.execute(sql);

解释:id可能是传入程序中的参数,此参数可能会包含恶意代码,从而改变sql语句的执行逻辑,从而会对数据库造成不好的影响。如上述代码:会删除student表中所有数据,因为sql语句的逻辑变为了delete from student where true

获取处理结果
  1. execute()
    如果sql语句第一个结果是结果集对象则返回true;如果sql语句返回结果是一个 更新操作的计数 或 没有结果集 则返回false。
  2. executeQuery()
    (1)运行select语句,返回 ResultSet 结果集。
    (2)示例代码
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 测试ResultSet的基本使用方法
 * @author dxt
 *
 */
public class Demo04 {
	public static void main(String[] args) {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			//1. 连接数据库
			Class.forName("com.mysql.cj.jdbc.Driver");
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/school"
					+ "?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC","root","root");
			//2.执行sql语句
			String sql = "select id,name,class from student where id>?";
			ps = conn.prepareStatement(sql);
			ps.setInt(1, 102); 	//把id大于102的用户信息取出来
			rs = ps.executeQuery();
			while(rs.next()) {	//向后移动游标,如果此位置的下一位置有内容则为true;游标从1之前开始
				//getInt():参数为列在结果集中对应的序号
				System.out.println(rs.getInt(1)+"--"+rs.getString(2)+"--"+rs.getInt(3));
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if(rs != null) {	
					rs.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				if(ps != null) {	
					ps.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				if(conn != null) {	
					conn.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}	
		}
	}
}
  1. executeUpdate()
    返回insert/update/delete操作处理的数据的 计数。插入1行数据则返回1,删除2行数据则返回2。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值