【JavaWeb】-JDBC详解、数据库连接池的认识
作者:学Java的冬瓜
博客主页:☀冬瓜的博客🌙
专栏:【Java Web】
分享:我沐浴过神河文明的光芒,它指引我成为一名战士,如有战死沙场之日,我愿化作银河里的星辰,为你们照亮前路。——《雄兵连》
主要内容:认识JDBC、用JDBC连接数据库并执行SQL语句、常用API的学习、数据库连接池
文章目录
- 一、认识JDBC
- 1、JDBC概念
- 2、JDBC本质
- 3、图片解析
- 4、JDBC优点
- 二、JDBC连接数据库并执行SQL语句
- 1、代码
- 2、步骤
- 第O 步
- 第一步
- 第二步
- 拓展:DriverManager API
- 第三步
- 第四步
- 拓展I:Connection API
- 拓展II:PreparedStatement API
- 第五步
- 第六步
- 拓展:Statement API
- 拓展:ResultSet API(结果集)
- 第七步
- 3、结果
- 三、数据库连接池
- 1、认识数据库连接池
- 2、连接池Druid的使用
一、认识JDBC
1、JDBC概念
- JDBC是使用Java语言操作关系型数据库的一套API
- 全称:(Java Database Connectivity) Java数据库连接
2、JDBC本质
- 官方(sun公司)定义的一套操作所有关系型数据库的接口。
- 数据库厂商要提供数据库驱动 jar 包(去相应的数据库厂商官网下载),自己去做实现这套接口的类。
- 我们利用这套接口进行编程,真正执行代码的是jar包中的实现这套接口的类。
3、图片解析
4、JDBC优点
- 各数据库厂商使用相同的接口,Java代码不需要根据不同数据库单独开发
- 可随时替换底层数据库,访问数据库的Java代码基本不变。
二、JDBC连接数据库并执行SQL语句
1、代码
public class JDBC {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1、注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2、获取连接
String url = "jdbc:mysql://127.0.0.1:3306/itcase";
String userName = "root";
String passWord = "202111a.";
Connection conn = DriverManager.getConnection(url,userName,passWord);
//3、定义SQL语句
String sql = "update user set age = 19 where id = 1";
//4、获取执行SQL对象
Statement stmt = conn.createStatement();
//5、执行SQL,并返回结果(影响行数)
int count = stmt.executeUpdate(sql);
//6、处理返回结果
System.out.println(count);
//7、释放资源
conn.close();
stmt.close();
}
}
2、步骤
- 创建工程,导入jar包
- 注册驱动
- 获取连接
- 定义SQL语句
- 获取要执行的SQL对象
- 执行SQL
- 处理返回结果
- 释放资源
第O 步
创建工程,导入jar包
- 创建一个Java工程,在工程里建一个包如 lib,用来存放jar包。
- 复制jar包,然后粘贴到lib包下
- jar包去相应数据库官网下载(我这里下的是数据库的8.0.28版本,注意要和MySQL版本对应)。
- 我这里是下载jar包并解压后单独保存在了D盘,JDBC文件夹下Mysql驱动包里
第一步
注册驱动
- 关键语句:Class.forName(“com.mysql.jdbc.Driver”);,其中com.mysql.jdbc.Driver就是各数据库厂商实现JDBC接口的驱动类。
- 使用这个语句后,jvm会加载这个类,然后进入com.mysql.jdbc.Driver,会立即注册
- 进入java.sql.DriverManager,DriverManager管理器会调用注册方法,并把Driver放入registeredDrivers列表中:
// Register ourselves with the DriverManager
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
- MySQL 5 之后,可以忽略注册的步骤。
- 导入jar包后程序会自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类。
第二步
获取连接
-
关键语句
String url = “jdbc:mysql://127.0.0.1:3306/itcas”; //127.0.0.1是IP地址(域名),3306是端口号,itcase是要连接的数据库
String userName = “root”; //用户名
String passWord = “202111a.”; //密码 -
关键语句
Connection conn = DriverManager.getConnection(url,userName,passWord);
利用DriverManager API连接数据库,使用Cnonection接收,因为DriverManager的getConnection方法返回值是Cnonection类型。
- 如果连接本机的MySQL且端口是默认端口3306,可以省略域名和端口名,简化成:“jdbc:mysql:///itcase”
- 数据库名之后,可以跟参数键值对,键值对之间用&连接
拓展:DriverManager API
1>、注册驱动
2>、获取连接
第三步
定义SQL语句
- 关键语句
String sql = “update user set age = 19 where id = 1”; //我这里用了一个更新操作,把在itcase数据库user表里,id为1的年龄改为19。
itcase里放着的user表:
第四步
获取要执行SQL对象
- 关键语句
Statement stmt = conn.createStatement();
拓展I:Connection API
1>、获取执行SQL对象
2>、管理事务
拓展II:PreparedStatement API
预编译接近SQL注入问题:
1>、SQL注入:
概念:通过操作输入来修改事先定义好的SQL语句,用以执行代码对服务器进行攻击的方法。
@ 准备:在itcase数据库中创建stu表,存放用户名和姓名,并插入数据:
//进入itcase数据库
use itcase;
//建表stu
create table stu(
username char(20),
password char(20)
);
//插入
insert stu values('zhangsan','123'),('lisi','1234');
//查询
select * from stu;
@ SQL注入核心代码:
注意:SQL注入,输入用户名任意,输入特殊的密码就会可以登录成功 如:
String pwd = "' or '1' = '1";
//接收用户输入用户名和密码
String name = "abc";
String pwd = "' or '1' = '1";
String sql = "select * from stu where username = '"+name+"' and password = '"+pwd+"'";
//获取对象
Statement stmt = conn.createStatement();
//执行SQL
ResultSet rs = stmt.executeQuery(sql);
//判断登录是否成功
if(rs.next()){
System.out.println("登录成功");
}else {
System.out.println("登陆失败");
}
@ 分析
2>、PreparedStatement解决SQL注入
@ 核心代码
思想:
1、利用占位符?先把坑占好
2、再调用Connection下的preparedStatement方法进行预编译
3、然后再设置参数
4、最后执行SQL语句。
String sql = "select * from stu where username = ? and password = ?"; //?表示占位符
//获取pstmt对象
PreparedStatement pstmt = conn.prepareStatement(sql); //预编译
pstmt.setString(1,name);
pstmt.setString(2,password); //设置参数
ResultSet rs = pstmt.executeQuery();//执行SQL,这里不再传参
if(rs.next()){ //判断登录是否成功
System.out.println("登录成功");
}else {
System.out.println("登陆失败");
}
3>、PreparedStatement防止SQL注入的原理
@ 对无法SQL注入的解释:
使用SQL注入的特殊密码时:String pwd = "' or '1' = '1";
在预编译完,设置参数时,会将单引号转义为'' \ ' ''。
所以,不会再出现凑字符串去登录的情况。
第五步
执行SQL,并返回结果(影响行数)
关键语句:
int count = stmt.executeUpdate(sql); //count是SQL语句执行数据库后,返回的影响行数
第六步
处理返回结果
拓展:Statement API
1>、处理第五步中,Statement的executeUpdate(sql)方法返回值:
这个处理方法符合DML语句,但DDL语句不行。比如删除数据库,或一个表。对于DDL语句只要没有报错,就相当于执行成功了。
if(count > 0){
System.out.println("修改成功!");
}else {
System.out.println("修改失败!");
}
2>、第五步中,Statement的executeQuery(sql)方法,处理返回值ResultSet:结果集
认识ResultSet结果集:
处理方法:
代码:
//连接
String url = "jdbc:mysql://127.0.0.1:3306/itcase? ";
String userName = "root";
String passWord = "202111a.";
Connection conn = DriverManager.getConnection(url,userName,passWord);
//定义SQL,获取执行对象,接收查询结果
String sql = "select * from user";
Statement stmt = conn.createStatement();
ResultSet resultSet = stmt.executeQuery(sql);
//6、处理返回结果
while (resultSet.next()){
String id = resultSet.getString(1);//1可以用"id"代替,其它也一样
String name = resultSet.getString(2);
int age = resultSet.getInt(3);
System.out.println("id:"+id+" name:"+name+" age:"+age);
System.out.println("************************");
}
结果:
id:1 name:zhang age:19
************************
id:2 name:li age:20
************************
拓展:ResultSet API(结果集)
需求:查询user表的id、name、age数据,封装到User对象中,并存储到ArrayList中
步骤:
1》创建一个pojo包,包里创建User类,User类有id、name、age三个字段,设置set方法和toString方法。
User类:
2》查询数据,封装到User对象中
3》将User对象存到ArrayList集合中,并输出
List<User> list = new ArrayList<>();
//6、处理返回结果
while (resultSet.next()){
User user = new User();
String id = resultSet.getString(1);
String name = resultSet.getString(2);
int age = resultSet.getInt(3);
//给对象赋值
user.setId(id);
user.setName(name);
user.setAge(age);
//把对象存储到list集合
list.add(user);
}
System.out.println(list);
结果:
[User{id='1', name='zhang', age=19}, User{id='2', name='li', age=20}]
第七步
释放资源
关键语句:
conn.close();
stmt.close(); //这两行都是回收资源
3、结果
修改前:
修改后:
注:执行 “update user set age = 19 where id = 1”
SQL语句后,把id为1的age=17改为了age=19。
三、数据库连接池
1、认识数据库连接池
2、连接池Druid的使用
@ 实现步骤
说明:具体操作找黑马JavaWeb视频