2.3 JDBC

本文全面介绍了JDBC(Java数据库连接)的基础知识,包括JDBC的体系结构、核心组件、使用步骤及执行SQL语句的方法。详细讲解了Statement、ResultSet、PreparedStatement的用法,并通过实例演示了如何使用JDBC进行数据库的CRUD操作。

本文是课上资料的总结非原创没有转载地址

用的是MySQL数据库

JDBC

一、JDBC简介

1.1 简介

  • JDBC(Java DataBase Connectivity,Java数据库连接)是一种用于执行SQL语句的JavaAPI,可以为多种关系数据库提过统一访问,它由一组用Java语言编写的类和接口组成。
  • JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。

1.2 JDBC体系结构

JDBC原理

Java提供访问数据库规范称为JDBC,而生产厂商提供规范的实现类称为驱动。没有驱动将无法完成数据库连接,也不能操作数据库,每个数据库厂商都需要提供自己的驱动,用来连接自己公司的数据库,也就是说驱动一般都由数据库生成厂商提供。

JDBC体系
JDBC体系结构由两层组成:

  • JDBC:提供了应用程序到数据库连接规范。
  • JDBC驱动程序:连接数据库的驱动程序的实现。

JDBC API使用驱动程序管理器来管理不同数据库的驱动程序
JDBC API体系

1.3 JDBC核心组件

  • DriverManager:此类管理数据库驱动程序列表。使用通信协议将来自java应用程序的连接请求与适当的数据库驱动程序匹配。
  • Driver:此接口处理与数据库服务器的通信,我们很少会直接与Driver对象进行交互。而是使用DriverManager对象来管理这种类型的对象。
  • Connection:该接口具有用于连接数据库的所有方法。连接对象表示通信上下文,数据库的所有通信仅通过连接对象。
  • Statement:使用从此接口创建的对象将SQL语句提交到数据库。除了执行存储过程之外,一些派生接口还接受参数。
  • ResultSet:在使用Statement对象执行SQL查询后,这些对象保存从数据库检索的数据。它作为一个迭代器,允许我们移动其数据。
  • SQLException:此类处理数据库应用程序中发生的任何异常。

二、JDBC入门

2.1 使用步骤

构建JDBC应用程序涉及以下六个步骤:

  • **导入JDBC驱动包:**需要下载包含数据库编程所需的JDBC的jar包。

注意:下载jar包地址有:jar包名称mysql-connector-javaOR[MySQL] Connector/J(J代表Java)
MySQL官网下载地址(官网可下载其他语言jar包)
maven远程仓库

  • **注册JDBC驱动程序:**要求您初始化驱动程序,以便您可以打开与数据库的通信通道。
  • **创建连接:**需要使用*DriverManager.getConnection()*方法创建一个Connection对象,该对象表示与数据库的物理连接。
  • **执行查询:**需要使用类型为Statement的对象来构建和提交SQL语句到数据库。
  • **从结果集中提取数据:**需要使用相应的*ResultSet.getXXX()*方法从结果集中检索数据。
  • **释放资源:**需要明确地关闭所有数据库资源,而不依赖于JVM的垃圾收集。

(1)导入jar包,在项目下创建lib目录,把mysql的jdbc包放入此目录,并添加到build path中(idea不同)。

(2)注册驱动(jdk1.7后可以省略,建议写上)

  • 第一种方式(推荐写法):Class.forName()
    注册驱动程序最常见的方法是使用Java的**Class.forName()**方法,将驱动程序的类文件动态加载到内存中,并将其自动注册
try {
   Class.forName("com.mysql.jdbc.Driver");
}
catch(ClassNotFoundException ex) {
   System.out.println("Error: unable to load driver class!");
}
  • 第二种方式:是使用静态**DriverManager.registerDriver()**方法。
  1. 驱动程序注册两次
  2. java程序依赖mysql驱动包
try {
   Driver myDriver = new com.mysql.jdbc.Driver();
   DriverManager.registerDriver(myDriver);
}
catch(ClassNotFoundException ex) {
   System.out.println("Error: unable to load driver class!");
}
// 1>驱动程序注册两次
// 2>java程序依赖mysql驱动包

(3)获取连接

  1. 数据库URL配置
    加载驱动程序后,可以使用**DriverManager.getConnection()**方法建立连接。
  • getConnection(String url)
  • getConnection(String url, Properties prop)
  • getConnection(String url, String user, String password)
RDBMSJDBC驱动程序名称连接字符串格式
MySQL的com.mysql.jdbc.Driverjdbc:mysql://hostname:3306/databaseName
ORACLEoracle.jdbc.driver.OracleDriverjdbc:oracle:thin:@hostname:port:databaseName
DB2com.ibm.db2.jdbc.net.DB2Driverjdbc:db2:hostname:port/databaseName
SYBASEcom.sybase.jdbc.SybDriverjdbc:sybase:Tds:hostname:port/databaseName
  1. 创建数据库连接对象
String URL = "jdbc:mysql://localhost:3306/emp";
String USER = "root";
String PASS = "root"
Connection conn = DriverManager.getConnection(URL, USER, PASS);

(4)执行查询(下面内容)
(5)处理结果(下面内容)
(6)关闭数据库连接

  • 为确保连接关闭,您可以在代码中提供一个“finally”块。finally块总是执行,不管是否发生异常。
    要关闭上面打开的连接,你应该调用close()方法如下 -
conn.close();

提示警告:

WARN: Establishing SSL connection without server’s identity verification is not recommended.
警告

  • 连接字符串 characterEncoding=utf8采用编码格式 useSSL=false不适用SSL安全连接
  • 在url后添加?...&...
    • characterEncoding=utf8 表示使用的编码utf8
    • useSSL=false 不使用SSL安全,安全连接需要证书
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/emp?characterEncoding=utf8&useSSL=false", "root", "");

三、JDBC执行SQL语句

3.1 Statement

用法分析介绍

创建命令对象

在使用Statement对象执行SQL语句之前,需要使用Connection对象的createStatement()方法创建一个,如下例所示:

Statement stmt = null;
try {
   stmt = conn.createStatement( );
   // ...
}
catch (SQLException e) {
   // ...
}
finally {
   // ...
}

创建Statement对象后,您可以使用它来执行一个SQL语句,其中有三个执行方法之一。

  • boolean execute(String SQL):如果可以检索到ResultSet对象,则返回一个布尔值true;否则返回false。使用此方法执行SQL DDL语句或需要使用真正的动态SQL时。
  • int executeUpdate(String SQL):返回受SQL语句执行影响的行数。使用此方法执行预期会影响多个行的SQL语句,例如INSERT,UPDATE或DELETE语句。
  • ResultSet executeQuery(String SQL):返回一个ResultSet对象。当您希望获得结果集时,请使用此方法,就像使用SELECT语句一样。

注意:上方只能一次执行一条SQL语句,如若参数SQL中有多个语句需要在url后添加参数allowMultiQueries=true;但其返回的是第一条语句影响的行数。不推荐使用

关闭Statement对象

命令执行完毕后需要调用close()方法显式关闭Statement对象,以确保正确清理。

Statement stmt = null;
try {
   stmt = conn.createStatement( );
   // ...
}
catch (SQLException e) {
   // ...
}
finally {
   stmt.close();
}
案例
  1. 案例操作1: 添加数据
public class JdbcDemo1 {
	public static void main(String[] args) {
		Connection connection=null;
		Statement stat=null;
		//2 注册驱动
		try {
			Class.forName("com.mysql.jdbc.Driver");
			//3打开连接
			connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
			//4创建命令并执行
			stat=connection.createStatement();
			int result=stat.executeUpdate("insert into dept(deptno,dname,loc) values(80,'市场部','天津')");
			if(result>0){
				System.out.println("添加成功");
			}else{
				System.out.println("添加失败");
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if(stat!=null){
				try {
					stat.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(connection!=null){
				try {
					connection.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}
  1. 演示案例2:更新数据
public class JdbcDemo2 {
	public static void main(String[] args) {
		Connection connection=null;
		Statement stat=null;
		//2 注册驱动
		try {
			Class.forName("com.mysql.jdbc.Driver");
			//3打开连接
			connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
			//4创建命令并执行
			stat=connection.createStatement();
			int result=stat.executeUpdate("update dept set loc='内蒙' where deptno=80");
			if(result>0){
				System.out.println("更新成功");
			}else{
				System.out.println("更新失败");
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if(stat!=null){
				try {
					stat.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(connection!=null){
				try {
					connection.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}
  1. 演示案例3:删除数据
public class JdbcDemo3 {
	public static void main(String[] args) {
		Connection connection=null;
		Statement stat=null;
		//2 注册驱动
		try {
			Class.forName("com.mysql.jdbc.Driver");
			//3打开连接
			connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
			//4创建命令并执行
			stat=connection.createStatement();
			int result=stat.executeUpdate("delete from dept where deptno=80");
			if(result>0){
				System.out.println("删除成功");
			}else{
				System.out.println("删除失败");
			}
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if(stat!=null){
				try {
					stat.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(connection!=null){
				try {
					connection.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

3.2 ResultSet

用法分析介绍
  • ResultSet接口表示查询结果集,ResultSet对象维护指向结果集中当前行的游标。结果集是指包含在ResultSet对象中的行和列数据。
案例
  1. 演示案例4:查询数据
public class JdbcDemo2 {
	public static void main(String[] args) {
		Connection connection=null;
		Statement stat=null;
		ResultSet rs=null;
		//2注册驱动
		try {
			Class.forName("com.mysql.jdbc.Driver");
			//3获取连接
			connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
			//4创建命令(语句)对象
			stat=connection.createStatement();
			//执行命令查询
			rs=stat.executeQuery("select ename,empno from emp");
			//5处理结果
			while(rs.next()){
//				 int empno=rs.getInt(1);
//				 String empname=rs.getString(2);
				 int empno=rs.getInt("empno");
				 String empname=rs.getString("ename");
				 System.out.println(empno+"...."+empname);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if(rs!=null){
				try {
					rs.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(stat!=null){
				try {
					stat.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(connection!=null){
				try {
					connection.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}
  1. 演示案例5:实现用户登录

数据库myschool

表 :user

create table user(		
​	id int primary key auto_increment,
​	username varchar(18) not null,
​	password varchar(16) not null,  # 密文 123456
​	phone varchar(11)
);

insert into user (username,password,phone) values('zhangsan','123456','13898765678');
insert into user (username,password,phone) values('lisi','6666','17898879988');

程序代码

/*
 * 实现用户登录
 */
public class JdbcDemo5 {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		System.out.println("请输入用户名");
		String username=input.nextLine();
		System.out.println("请输入密码");
		String pass=input.nextLine();
		
		//连接对象
		Connection connection=null;
		//命令对象
		Statement stat=null;
		//结果集
		ResultSet rs=null;
		//1 注册驱动
		try {
			Class.forName("com.mysql.jdbc.Driver");
			//2获取连接
			connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");
			//3创建命令
			stat=connection.createStatement();
			//4执行命命令  select * from user where username='zhangsan' and password='123456';
			 rs=stat.executeQuery("select * from user where username='"+username+"' and password='"+pass+"'");
			if(rs.next()){ //有数据
				System.out.println("登录成功");
			}else{
				System.out.println("账号或密码错误");
			}
		
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if(rs!=null){
				try {
					rs.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(stat!=null){
				try {
					stat.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(connection!=null){
				try {
					connection.close();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

3.3 PreparedStatement

用法分析介绍
  • SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
  • PreparedStatement接口扩展了Statement接口,提供了比Statement对象更强大的功能。
  • 作用
    1. 预编译,效率高
    2. 安全,避免SQL注入
PreparedStatement pstmt = null;
try {
   String SQL = "Update Employees SET age = ? WHERE id = ?";
   pstmt = conn.prepareStatement(SQL);
   // ...
}
catch (SQLException e) {
   // ...
}
finally {
   // ...
}
  • JDBC中的所有参数都由 ? 符号,这被称为参数标记。在执行SQL语句之前,必须为每个参数提供值。

  • 把输入的特殊的符号转移成普通字符,避免sql注入。

  • 所述的setXXX()方法将值绑定到所述参数,其中XXX代表要绑定到输入参数的值的Java数据类型。如果忘记提供值,将收到一个SQLException。

  • 每个参数标记由其顺序位置引用。第一个标记表示位置1,下一个位置2等等。该方法与Java数组索引不同,从0开始。

关闭PreparedStatement对象

  • 就像关闭Statement对象一样,由于同样的原因,还应该关闭PreparedStatement对象。

  • 一个简单的调用close()方法将执行该作业。如果先关闭Connection对象,它也会关闭PreparedStatement对象。但是,应始终显式关闭PreparedStatement对象,以确保正确清理。

PreparedStatement pstmt = null;
try {
   String SQL = "Update Employees SET age = ? WHERE id = ?";
   pstmt = conn.prepareStatement(SQL);
   // ...
}
catch (SQLException e) {
   // ...
}
finally {
   pstmt.close();
}
案例
  1. 上机练习:使用PreparedStatement实现emp表的数据添加
/**
 * 使用PreparedStatement实现emp表的数据添加
 * @author ldt
 *
 */
public class Demo6 {
	public static void main(String[] args) throws Exception{
		Scanner input=new Scanner(System.in);
		System.out.println("请输入员工编号");
		int empno=input.nextInt();
		System.out.println("请输入员工姓名");
		String ename=input.next();
		System.out.println("请输入工作");
		String job=input.next();
		System.out.println("请输入经理的编号");
		int mgr=input.nextInt();
		System.out.println("请输入入职日期");
		
		String date=input.next();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		Date hiredate=sdf.parse(date);
		System.out.println("请输入工资");
		double salary=input.nextDouble();
		System.out.println("请输入奖金");
		double comm=input.nextDouble();
		System.out.println("请输入部门");
		int deptno=input.nextInt();
		
		//1注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2获取连接
		String url="jdbc:mysql:///school";
		Connection conn=DriverManager.getConnection(url, "root", "root");
		//3创建命令
		PreparedStatement pstat=conn.prepareStatement("insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(?,?,?,?,?,?,?,?);");
		//4参数赋值
		pstat.setObject(1, empno);
		pstat.setObject(2, ename);
		pstat.setObject(3, job);
		pstat.setObject(4, mgr);
		pstat.setObject(5, hiredate);
		pstat.setObject(6, salary);
		pstat.setObject(7, comm);
		pstat.setObject(8, deptno);
		//5执行
		int count=pstat.executeUpdate();
		if(count>0) {
			System.out.println("添加成功");
		}else {
			System.out.println("添加失败");
		}
		//6释放资源
		pstat.close();
		conn.close();	
	}
}

总结

  1. JDBC介绍 :
    ​ Java Database Connectity java数据库连接技术
    ​ 定义一套连接数据的规范和标准。

  2. JDBC包含两个部分
    ​ JDBC API
    ​ JDBC 驱动程序

  3. JDBC的使用步骤

    1. 导入jar包
    2. 注册驱动 Class.forName(“com.mysql.jdbc.Driver”);
    3. 获取连接
    4. 创建命令
    5. 执行命令,处理结果
    6. 释放资源
  4. JDBC的api

类名功能
​Driver驱动
​DriverManager驱动管理类
Connection负责连接数据库
​Statement负责执行命令
ResultSet封装结果集
PreparedStatment预编译命令
  1. 实现CRUD

作业题

1.登录
	创建user表
		id int 主键 自增
		username varchar(18)
		password varchar(18)
		name   varchar(20)
		age    int
		sex    char(1)
	控制台输入用户名 密码
	连接数据库 判断和数据库里的是否一致
	一致显示 登录成功并显示用户信息
    不一致 显示登陆失败
2.根据id查询指定的学生记录
	创建学生信息表	创建方法 传入学生id 获取学生信息
	student 表 
	sid(int 主键 自增) 
	sname(varchar(20) 非空) 
	sage(int 默认值为10) 
	ssex(varchar(1)) 
	birthday(date) 
	score(double(5,2) 保留小数点后2位)

面试题

 1. Statement对象的execute,executeQuery,executeUpdate方法的区别?
execute:可以执行任何SQL语句,返回一个boolean值,表明执行该SQL语句是否返回了ResultSet。如果执行后第一个结果是ResultSet,则返回true,否则返回false。但它执行SQL语句时比较麻烦,通常没有必要使用execute方法执行SQL语句,而是使用executeQuery或executeUpdate更适合,但如果在不清楚SQL语句的类型时则只能使用execute方法来执行该SQL语句了。
executeQuery:用于产生单个结果集(ResultSet)的语句,例如 SELECT 语句。 被使用最多的执行 SQL 语句的方法。这个方法被用来执行 SELECT 语句,它几乎是使用最多的 SQL 语句。但也只能执行查询语句,执行后返回代表查询结果的ResultSet对象。
executeUpdate:用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQL DDL(数据定义语言)语句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或 DELETE 语句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一个整数(int),指示受影响的行数(即更新计数)。对于 CREATE TABLE 或 DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。

 2. PreparedStatement接口和Statement的区别?
(1)PreparedStatement比Statement效率高,安全可靠
(2)PreparedStatement只能执行一种sql语句,Statement可以执行多个
(3)PreparedStatement使用占位符赋值,Statement只能字符串拼接
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值