文章目录
![image-20230206074352715](https://i-blog.csdnimg.cn/blog_migrate/faf96e759748a17a88d8105a8235a679.png)
JDBC -(02)JDBC的核心
实验环境
Java:17
MySQL:8.0.26
JDBC:8.0.30
IDEA:2022
1. 引入 mysql-jdbc 驱动 jar
驱动下载地址:https://downloads.mysql.com/archives/c-j/
1.1 驱动版本的选择
mysql版本 | 推荐驱动版本 | 备注 |
---|---|---|
mysql 5.5.x | 5.0.x | com.mysql.jdbc.Driver |
mysql 5.7.x | 5.1.x | com.mysql.jdbc.Driver |
mysql 8.x | 8.0.x | com.mysql.cj.jdbc.Driver(建议使用8.0.25+,不用设置时区) |
1.2 Java 工程导入依赖
1.项目创建lib文件夹
2.导入驱动依赖 jar 包
![image-20230314152108814](https://cdn.staticaly.com/gh/chenyouchang/markdown_pic@main/2023/03/202303151910341.png)
3.jar 包右键-添加项目依赖
![image-20230314152203365](https://cdn.staticaly.com/gh/chenyouchang/markdown_pic@main/2023/03/202303151910923.png)
此时导入的驱动依赖
2. JDBC 基本使用步骤分析(6步)
2.1 基本使用步骤
1.注册驱动
2.获取连接
3.创建发送 sql 语句对象
4.发送 sql 语句,并获取返回结果
5.结果集解析
6.资源关闭
2.2 应用举例
案例:获取数据库julissa中t_user表中的用户信息
public class QueryUsers {
public static void main(String[] args) throws SQLException {
//1.注册驱动
DriverManager.deregisterDriver(new Driver());
//2.获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa","root","123456");
//3.创建statement
Statement statement = connection.createStatement();
//4.发送sql语句,并获取返回结果
String sql = "select * from t_user";
ResultSet resultSet = statement.executeQuery(sql);
//5.解析结果集
while (resultSet.next()){ //看有没有下一行数据,有就获取
int id = resultSet.getInt("id");
String account = resultSet.getString("account");
String password = resultSet.getString("password");
String nickname = resultSet.getString("nickname");
System.out.println(id + "--" + account + "--" + password + "--" + nickname);
}
//6.关闭资源
resultSet.close();
statement.close();
connection.close();
}
}
3. 基于statement实现查询
3.1 准备数据库数据
1.创建t_user表
![image-20230314155529424](https://cdn.staticaly.com/gh/chenyouchang/markdown_pic@main/2023/03/202303151911157.png)
2.添加数据
3.2 查询目标
查询全部用户信息进行控制台输出
3.3 基于statement实现查询
代码实现:
package com.julissa.api.statement;
import com.mysql.cj.jdbc.Driver;
import java.sql.*;
/**
*
* TODO:
* DriverManager
* Connection
* Statement
* ResultSet
*/
public class QueryUsers {
public static void main(String[] args) throws SQLException {
//1.注册驱动
/**
* TODO:
* 注册驱动 DriverManager.deregisterDrivercom.mysql.cj.jdbc.Driver)
* 依赖:驱动版本 8+ com.mysql.cj.jdbc.Driver
* 驱动版本 5+ com.mysql.jdbc.Driver
*/
DriverManager.deregisterDriver(new Driver());
//2.获取连接
/**
* TODO:
* Java程序要和数据库创建连接
* Java程序连接数据库,肯定是调用某个方法,方法也需要填入连接数据库的基本信息
* 数据库ip地址:127.0.0.1
* 数据库端口号:3306
* 账号:root
* 密码:123456
* 连接数据库名称:julissa
*/
/**
* 参数:
* 参数1:url jdbc:数据库厂商名://ip地址:port/数据库名
* jdbc:mysql://localhost:3306/julissa
* 参数2:username 数据库软件的账号 root
* 参数3:password 数据库软件的密码 123456
*/
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa","root","123456");
//3.创建statement
Statement statement = connection.createStatement();
//4.发送sql语句,并获取返回结果
String sql = "select * from t_user";
ResultSet resultSet = statement.executeQuery(sql);
//5.解析结果集
//看有没有下一行数据,有就获取
while (resultSet.next()){
int id = resultSet.getInt("id");
String account = resultSet.getString("account");
String password = resultSet.getString("password");
String nickname = resultSet.getString("nickname");
System.out.println(id + "--" + account + "--" + password + "--" + nickname);
}
//6.关闭资源
resultSet.close();
statement.close();
connection.close();
}
}
执行结果:
3.4 总结
3.4.1 注册驱动
DriverManager.deregisterDriver(new Driver)
驱动有两种,根据导入的驱动jar包选择对应的驱动
- 驱动版本 8+ com.mysql.cj.jdbc.Driver
- 驱动版本 5+ com.mysql.jdbc.Driver
3.4.2 获取连接
Java程序要和数据库创建连接,肯定是调用某个方法,方法也需要填入连接数据库的基本信息
- 数据库ip地址
- 数据库端口号
- 账号
- 密码
- 连接数据库名称
Connection connection = DriverManager.getConnection(url,user,password);
DriverManager.getConnection()方法中需要提供三个参数:
-
参数1:url jdbc:数据库厂商名://ip地址:port/数据库名,比如:jdbc:mysql://localhost:3306/julissa
-
参数2:user 数据库软件的账号,比如:root
-
参数3:password 数据库软件的密码 ,比如:123456
4. 基于statement方式的问题
明确jdbc流程和详细使用
发现问题,引出prepareStatement
4.1 准备数据库数据
和第三小节的数据库一样
4.2 查询目标
模拟登陆,控制台输入账号和密码,判断是否登陆成功
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U2XsybwT-1678879201972)(null)]
4.3 基于statement实现查询
package com.julissa.api.statement;
import com.mysql.cj.jdbc.Driver;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;
/**
* TODO:
* 输入账号和密码
* 进行数据库信息查询(t_user)
* 反馈登陆成功还是失败
*
* TODO:
* 1.键盘输入事件,收集账号和密码信息
* 2.注册驱动
* 3.获取连接
* 4.创建statement对象
* 5.发送sql语句,并获取结果集
* 6.解析结果集,进行判断,显示登陆成功还是失败
* 7.关闭资源
*/
public class UserLogin {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
Scanner scanner = new Scanner(System.in);
//1.接收数据
System.out.println("请输入账号:");
String account = scanner.next();
System.out.println("请输入密码:");
String password = scanner.next();
//2.注册驱动
/**
* TODO:
* 注意:
* 注册驱动 DriverManager.deregisterDrivercom.mysql.cj.jdbc.Driver);
* 依赖:驱动版本 8+ com.mysql.cj.jdbc.Driver
* 驱动版本 5+ com.mysql.jdbc.Driver
* 问题:注册两次驱动
* 1.DriverManager.deregisterDriver() 方法本身会注册一次
* 2.Driver static { DriverManager.deregisterDriver() } 静态代码块,也会注册一次
* 解决:只想注册一次
* 只触发静态代码块代码即可
* 触发静态代码块:
* 类加载进制:类加载的时候,会触发静态代码块
* 加载 [class文件 -> JVM虚拟机的class对象]
* 连接 [验证(检查文件类型) -> 准备(静态变量默认值) ->解析(触发静态代码块)]
* 初始化(给静态属性赋真实值)
* 触发类加载:
* 1.new 关键字
* 2.调用静态方法
* 3.调用静态属性
* 4.接口,1.8 defaulut默认实现
* 5.反射
* 6.子类触发父类
* 7.程序入门main
*
*/
//方案1
//DriverManager.deregisterDriver(new Driver());
//方案2 固定写法,mysql新版本驱动 切换数据库,oracle驱动,得改代码
//new Driver();
//方案3 通过反射,触发类加载,触发静态代码块的调用
//字符串 -> 提取到外部配置文件 -> 可以在不改变代码的情况下,完成数据库驱动的切换
Class.forName("com.mysql.cj.jdbc.Driver");
//3.获取数据库连接
/**
*
* getConnection(1,2,3)是一个重载方法
* 允许开发着用不同的形式传入数据库连接的核心参数
*
* 核心属性:
* 1.数据库软件所在的主机ip地址:127.0.0.1 | localhost
* 2.数据库软件所在的主机的端口号: 3306
* 3.连接的具体库: julissa
* 4.连接的账号: root
* 5.连接的密码: 123456
* 6.可选的信息:没有
*
* 三个参数:
* String url 数据库软件所在的具体地址,所在的端口号以及连接的具体库,可选信息
* 语法:jdbc:数据库管理软件名称(mysql | oracle)://数据库软件所在地址ip:port端口号/连接的数据库名?key=value&key=value
* jdbc:mysql://127.0.0.1:3306/julissa
* jdbc:mysql://localhost:3306/julissa
* 本机的省略写法: jdbc:mysql:///julissa 省略了【本机地址】和【默认端口3306】,必须是本机和3306端口才可以省略
* String user 数据库的账号 root
* String password 数据库的密码 123456
* 两个参数:
* String url 和三个参数的url作用一样 jdbc:mysql://127.0.0.1:3306/julissa
* Properties info 存储账号和密码
* Properties 类似与 Map,只不过 key 和 value 都是字符串形式
* key user 账号信息
* key password 密码信息
* 一个参数:
* String url 数据库ip,端口号,具体的数据库,可选信息(账号密码)
* jdbc:数据库管理软件名称://数据库软件所在地址ip:port端口号/连接的数据库名?key=value&key=value
* jdbc:mysql://localhost:3306/julissa?user=root&password=123456
* 携带固定的参数名 user 和 password 传递账号和密码信息
*
*
* url路径可选信息:
* url?key=value&key=value
* url?useUnicode=true&characterEncoding=UTF8&autoReconnect=true&serverTimezone=Asia/Shanghai
* useUnicode 是否使用Unicode字符集
* characterEncoding 当useUnicode设置为true时,指定字符编码。比如可设置为gb2312或gbk 或UTF8
* autoReconnect 当数据库连接异常中断时,是否自动重新连接?
* connectTimeout 和数据库服务器建立socket连接时的超时,单位:毫秒。
* serverTimezone 时区设置功能有UTC,Asia/Shanghai,Asia/Hongkong
*
* 8.0.25 版本以后,自动识别时区 serverTimezone=Asia/Shanghai可省略,之前版本还是需要添加的
* 8版本之后,默认使用utf-8字符集,useUnicode=true&characterEncoding=UTF8可省略
*/
//方案1:三个参数
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa", "root", "123456");
//方案2:两个参数
// Properties info = new Properties();
// info.put("user","root");
// info.put("password","123456");
// Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa", info);
//方案3:一个参数
//Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa?user=root&password=123456");
//4.创建发送sql语句的statement对象
//statement 可以发送sql语句到数据库,并且获取返回结果
Statement statement = connection.createStatement();
//5.发送sql语句,获取返回结果(编写sql语句,发送sql语句)
String sql = "select * from t_user where account = '"+ account +"' and password = '"+ password +"'";
ResultSet resultSet = statement.executeQuery(sql);
//6.结果集解析
/**
*
* Java是一种面向对象的思维,把查询结果封装成ResultSet对象,里面有行有列
* resultSet -> 逐行获取数据,行 -> 行的列的数据**
* 想要进行数据解析,我们需要进行两件事情:**
* 1.移动游标指定获取数据
* 2.获取指定数据行的的列的数据
* 游标移动问题:
* resultSet内部包含一个游标,指定当前行数据
* 默认游标指向第一行数据之前
* 我们可以调用next()方向向下移动一行游标
* 如果我们有很多行数据,可以使用while(resultSet.next){获取每一行的数据}
* boolean = next() ,next方法返回值为布尔类型
* true:有更多行数据,并且向下移动一行
* false:没有更多行数据,不移动
* 获取列数据问题:
* 获取光标指向的行的列的数据
* resultSet.get类型(String columLabel | int columIndex)
* columLabel: 列名,如果有别名,可以写别名
* columIndex: 列的小角标获取(从左到右 从1开始)
*/
// while (resultSet.next()){
// System.out.println("账号:" + resultSet.getString("account"));
// System.out.println("密码:" + resultSet.getString("password"));
// System.out.println("昵称:" + resultSet.getString("nickname"));
//
// }
//移动一次游标,如果有数据,就代表登陆成功
if(resultSet.next()){
System.out.println("登陆成功!");
System.out.println("账号:" + resultSet.getString("account"));
System.out.println("密码:" + resultSet.getString("password"));
System.out.println("昵称:" + resultSet.getString("nickname"));
}else {
System.out.println("登陆失败~~~");
}
//7.关闭资源
resultSet.close();
statement.close();
connection.close();
}
}
4.4 总结
4.4.1 注册驱动
如果我们在程序中写入以下代码,那么会产生什么问题呢?
DriverManager.deregisterDriver(new Driver());
问题:注册两次驱动
- DriverManager.deregisterDriver() 方法本身会注册一次
- Driver static { DriverManager.deregisterDriver() } 静态代码块,也会注册一次
解决:只想注册一次
只触发静态代码块代码即可
触发静态代码块:
类加载进制:类加载的时候,会触发静态代码块
加载 [class文件 -> JVM虚拟机的class对象]
连接 [验证(检查文件类型) -> 准备(静态变量默认值) ->解析(触发静态代码块)]
初始化(给静态属性赋真实值)
触发类加载:
1.new 关键字
2.调用静态方法
3.调用静态属性
4.接口,1.8 defaulut默认实现
5.反射
6.子类触发父类
7.程序入门main
改进后的注册驱动代码:
通过反射,触发类加载,触发静态代码块的调用
//字符串 -> 提取到外部配置文件 -> 可以在不改变代码的情况下,完成数据库驱动的切换
//通过反射注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
4.4.2 获取数据库连接
getConnection(1,2,3)是一个重载方法,允许开发着用不同的形式传入数据库连接的核心参数
核心属性:
1.数据库软件所在的主机ip地址:127.0.0.1 | localhost
2.数据库软件所在的主机的端口号: 3306
3.连接的具体库: julissa
4.连接的账号: root
5.连接的密码: 123456
6.可选的信息:没有
(1)三个参数:
String url 数据库软件所在的具体地址,所在的端口号以及连接的具体库,可选信息
语法:jdbc:数据库管理软件名称(mysql | oracle)😕/数据库软件所在地址ip:port端口号/连接的数据库名?key=value&key=value
jdbc:mysql://127.0.0.1:3306/julissa
jdbc:mysql://localhost:3306/julissa
本机的省略写法: jdbc:mysql:///julissa 省略了【本机地址】和【默认端口3306】,必须是本机和3306端口才可以省略
String user 数据库的账号 root
String password 数据库的密码 123456
//获取数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa", "root", "123456");
(2)两个参数
String url 和三个参数的url作用一样 jdbc:mysql://127.0.0.1:3306/julissa
Properties info 存储账号和密码
Properties 类似与 Map,只不过 key 和 value 都是字符串形式
key user 账号信息
key password 密码信息
//创建用于存储账号密码的properties对象
Properties info = new Properties();
info.put("user","root");
info.put("password","123456");
//获取数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa", info);
(3)一个参数
String url 数据库ip,端口号,具体的数据库,可选信息(账号密码)
jdbc:数据库管理软件名称://数据库软件所在地址ip:port端口号/连接的数据库名?key=value&key=value
jdbc:mysql://localhost:3306/julissa?user=root&password=123456
携带固定的参数名 user 和 password 传递账号和密码信息
//获取数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa?user=root&password=123456");
url路径可选信息:
url?key=value&key=value
useUnicode 是否使用Unicode字符集
characterEncoding 当useUnicode设置为true时,指定字符编码。比如可设置为gb2312或gbk 或UTF8
autoReconnect 当数据库连接异常中断时,是否自动重新连接?
connectTimeout 和数据库服务器建立socket连接时的超时,单位:毫秒。
serverTimezone 时区设置功能有UTC,Asia/Shanghai,Asia/Hongkong
8.0.25 版本以后,自动识别时区 serverTimezone=Asia/Shanghai可省略,之前版本还是需要添加的
8版本之后,默认使用utf-8字符集,useUnicode=true&characterEncoding=UTF8可省略
//获取数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa?useUnicode=true&characterEncoding=UTF8&autoReconnect=true&serverTimezone=Asia/Shanghai", "root", "123456");
4.4.3 创建statement对象
statement 可以发送sql语句到数据库,并且获取返回结果
//创建statement对象
Statement statement = connection.createStatement();
4.4.4 发送sql语句,获取返回结果
编写sql语句,发送sql语句到数据库,获取返回结果
SQL分类:
- DDL 容器创建、修改、删除
- DML 数据插入、修改、删除
- DQL 数据查询
- DCL 权限控制
- TPL 事务控制
executeUpdate() 和 executeQuery() 的选择
方法 | 参数 | 返回值 |
---|---|---|
statement.executeUpdate() | sql(非DQL) | int,情况1:DML 返回影响的行数,例如,删除三条数据 return 3 ,添加两条数据 return 2;情况2:非DML return 0 |
statement.executeQuery() | sql(DQL) | ResultSet,结果集 |
//编写sql语句
String sql = "select * from t_user where account = '"+ account +"' and password = '"+ password +"'";
//发送sql语句并获取返回结果集
ResultSet resultSet = statement.executeQuery(sql);
4.4.5 解析结果集
Java是一种面向对象的思维,把查询结果封装成ResultSet对象,里面有行有列
resultSet -> 逐行获取数据,行 -> 行的列的数据
想要进行数据解析,我们需要进行两件事情:
1.移动游标指定获取数据行
2.获取指定数据行的的列的数据
游标移动问题:
resultSet内部包含一个游标,指定当前行数据
默认游标指向第一行数据之前
我们可以调用next()方向向下移动一行游标
如果我们有很多行数据,可以使用while(resultSet.next){获取每一行的数据}
boolean = next() ,next方法返回值为布尔类型
true:有更多行数据,并且向下移动一行
false:没有更多行数据,不移动
获取列数据问题:
获取光标指向的行的列的数据
resultSet.get类型(String columLabel | int columIndex)
columLabel: 列名,如果有别名,可以写别名
columIndex: 列的小角标获取(从左到右 从1开始)
假设结果集中有如下数据:
id | accunt | password | nickname |
---|---|---|---|
1 | root | 123456 | 经理 |
2 | admin | 666666 | 管理员 |
结果集的数据解析:
//移动一次游标,如果有数据,就代表登陆成功
if(resultSet.next()){
System.out.println("登陆成功!");
System.out.println("账号:" + resultSet.getString("account"));
System.out.println("密码:" + resultSet.getString("password"));
System.out.println("昵称:" + resultSet.getString("nickname"));
}else {
System.out.println("登陆失败~~~");
}
4.5.6 关闭资源
//7.关闭资源
resultSet.close();
statement.close();
connection.close();
4.5 存在的问题
1.sql语句需要字符串拼接,会很麻烦
2.只能拼接字符串类型,其他的数据类型无法处理
3.可能发生注入攻击
动态值充当了sql语句结果,影响了原有的查询结果
假设sql查询语句如下:
String sql = "select * from t_user where account = '"+ account +"' and password = '"+ password +"'";
当用户输入account:root
password:'or ‘1’='1
拼接后的sql语句:
select * from t_user where account = 'root' and password = ''or '1'='1'
就会查询出账号为root的用户
5.基于prepareStatement方式实现查询
利用prepareStatement解决上述注入攻击和sql语句拼接问题
5.1 基于prepareStatement方式实现查询
package com.julissa.api.statement;
import java.sql.*;
import java.util.Scanner;
public class UserLogin_V2 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入账号:");
String account = scanner.next();
System.out.println("请输入密码:");
String password = scanner.next();
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2..获取数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/julissa", "root", "123456");
/**
*
* statement
* 1.创建statement
* 2.编写sql语句
* 3.发送sql语句,获取返回结果
*
* prepareStatement
* 1.编写sql语句,动态值部分使用占位符 ? 替代
* 2.创建prepareStatement,并且传入sql语句
* 3.动态值 占位符 ? 赋值 单独赋值即可
* 4.发生sql语句,获取返回结果
*/
//3.编写sql语句
String sql = "select * from t_user where account = ? and password = ?";
//4.创建预编译statement
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//5.给动态值赋值
/**
* 参数1:index 占位符的位置 从左向右 从1开始
* 参数2:object 可以设置任何类型的数据,避免了我们拼接和类型更加丰富
*/
preparedStatement.setString(1, account);
preparedStatement.setString(2, password);
//6.执行sql语句,并获取返回结果
//statement.executeQuery(sql) | statement.executeUpdate(sql)
//preparedStatement.executeQuery() | preparedStatement.executeUpdate() TODO:不需要再传入sql,因为它已经知道了动态值
ResultSet resultSet = preparedStatement.executeQuery();
//7.判读是否登陆成功
if(resultSet.next()){
System.out.println("登陆成功!");
System.out.println("账号:" + resultSet.getString("account"));
System.out.println("密码:" + resultSet.getString("password"));
System.out.println("昵称:" + resultSet.getString("nickname"));
}else {
System.out.println("登陆失败!");
}
//8.释放资源
resultSet.close();
preparedStatement.close();
connection.close();
}
}
5.2 statement 和 prepareStatement 的区别
statement的流程:
1.创建statement
2.编写sql语句
3.发送sql语句,获取返回结果
//创建发送sql语句的statement对象
Statement statement = connection.createStatement();
//编写sql语句
String sql = "select * from t_user where account = '"+ account +"' and password = '"+ password +"'";
//发送sql语句,获取返回结果(编写sql语句,发送sql语句
ResultSet resultSet = statement.executeQuery(sql);
prepareStatement的流程:
1.编写sql语句,动态值部分使用占位符 ? 替代
2.创建prepareStatement,并且传入sql语句
3.动态值 占位符 ? 赋值 单独赋值即可
4.发生sql语句,获取返回结果
//编写sql语句
String sql = "select * from t_user where account = ? and password = ?";
//创建预编译statement
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//给动态值赋值
/**
* 参数1:index 占位符的位置 从左向右 从1开始
* 参数2:object 可以设置任何类型的数据,避免了我们拼接和类型更加丰富
*/
preparedStatement.setString(1, account);
preparedStatement.setString(2, password);
//执行sql语句,并获取返回结果
ResultSet resultSet = preparedStatement.executeQuery();
6.基于prepareStatement方式实现增删改(DML)
6.1 添加操作
@Test
public void testInsert() throws ClassNotFoundException, SQLException {
/**
* 向t_user表插入一条数据
* account test
* password test123
* nickname 测试人员
*/
String account = "test";
String password = "test123";
String nickname = "测试人员";
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取数据库连接
Connection connection = DriverManager.getConnection
("jdbc:mysql://localhost:3306/julissa","root","123456");
//3.编写sql
String sql = "insert into t_user(account,password,nickname) values(?,?,?)";
//4.创建预编译statement,并传入sql语句
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//5.给动态值设置值
preparedStatement.setString(1,account);
preparedStatement.setString(2,password);
preparedStatement.setString(3,nickname);
//6.执行sql语句,并获取返回结果
int i = preparedStatement.executeUpdate();
//7.判读是否插入成功 1成功
if(i != 1) {
System.out.println("插入数据失败");
}else {
System.out.println("插入数据成功");
}
//8.关闭资源
preparedStatement.close();
connection.close();
}
6.2 修改操作
@Test
public void testUpdate() throws ClassNotFoundException, SQLException {
/**
* 修改t_user表中admin用户的密码
* account admin
* password admin123
**/
String account = "admin";
String password = "admin123";
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取数据库连接
Connection connection = DriverManager.getConnection
("jdbc:mysql://localhost:3306/julissa","root","123456");
//3.编写sql
String sql = "update t_user set password=? where account=?";
//4.创建预编译statement,并传入sql语句
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//5.给动态值设置值
preparedStatement.setString(1,password);
preparedStatement.setString(2,account);
//6.执行sql语句,并获取返回结果
int i = preparedStatement.executeUpdate();
//7.判读是否插入成功 1成功
if(i != 1) {
System.out.println("修改数据失败");
}else {
System.out.println("修改数据成功");
}
//8.关闭资源
preparedStatement.close();
connection.close();
}
6.3 删除操作
@Test
public void testDelete() throws ClassNotFoundException, SQLException {
/**
* 删除t_user表中id为3的用户信息
* id 3
*/
String id = "3";
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取数据库连接
Connection connection = DriverManager.getConnection
("jdbc:mysql://localhost:3306/julissa","root","123456");
//3.编写sql
String sql = "delete from t_user where id=?";
//4.创建预编译statement,并传入sql语句
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//5.给动态值设置值
preparedStatement.setString(1,id);
//6.执行sql语句,并获取返回结果
int i = preparedStatement.executeUpdate();
//7.判读是否插入成功 1
if(i != 1) {
System.out.println("修改数据失败");
}else {
System.out.println("修改数据成功");
}
//8.关闭资源
preparedStatement.close();
connection.close();
}
6.4 查询操作
@Test
public void testSelect() throws ClassNotFoundException, SQLException {
/**
*
* 目标:查询t_user表中所有用户信息,并且封装到一个List<Map> List集合中
*
* 解释:
* 行: id account password nickname
* 行: id account password nickname
* 行: id account password nickname
*
* 数据库 -> resultSet -> java -> map(key=列名,value=列的内容) -> List<Map> -> List
*/
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取数据库连接
Connection connection = DriverManager.getConnection
("jdbc:mysql://localhost:3306/julissa","root","123456");
//3.编写sql
String sql = "select id,account,password,nickname from t_user";
//4.创建预编译statement,并传入sql语句
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//5.执行sql语句,并获取返回结果
ResultSet resultSet = preparedStatement.executeQuery();
//6.解析结果集
List<Map> list = new ArrayList<>();
//获取列的信息对象
//TODO:metaData装的当前结果集列的对象,(可以根据列的下表获取列的名称,获取列的数量)
ResultSetMetaData metaData = resultSet.getMetaData();
//获取列的数量
int columnCount = metaData.getColumnCount();
while (resultSet.next()) {
Map<String,Object> map = new HashMap<>();
//手动取值
//map.put("id",resultSet.getString("id"));
//map.put("account",resultSet.getString("account"));
//map.put("password",resultSet.getString("password"));
//map.put("nickname",resultSet.getString("nickname"));
//自动遍历列,从1开始
for (int i = 1; i <= columnCount; i++) {
//根据指定下标获取值
Object value = resultSet.getObject(i);
//获取指定列的名称
//getColumnLabel:会获取别名,如果没有再获取列名
String key = metaData.getColumnLabel(i);
map.put(key,value);
}
list.add(map);
}
//遍历集合
for (Map map:
list) {
System.out.println(map);
}
//7.关闭资源
resultSet.close();
preparedStatement.close();
connection.close();
}
7.prepareStatement使用方式总结
7.1 使用步骤总结
1.注册驱动
2.获取连接
3.编写SQL语句结构
4.创建prepareStatement对象。传入SQL语句
5.占位符赋值
6.发送SQL语句,获取返回结果
7.解析结果集
8.关闭资源n
7.2 使用API总结
7.2.1 注册驱动
-
方案1:调用静态方法,但是会注册两次驱动
DriverManager.deregisterDriver(new Driver());
-
方案2:反射触发
Class.forName(“com.mysql.cj.jdbc.Driver”);
7.2.2 获取连接
Connection connection = DriverManager.getConnection();
-
三个参数:DriverManager.getConnection(String url,String user,String password)
-
两个参数:DriverManager.getConnection(String url,Properties info)
info 有两个key : user 和 password
-
一个参数:DriverManager.getConnection(String url)
url?user=xxx&password=xxx
7.2.3 编写SQL语句
-
查询
String sql = “select account,password from t_user”;
-
添加
String sql = “insert into t_user(account,password,nickname) values(?,?,?)”;
-
删除
String sql = “delete from t_user where id=?”;
-
修改
String sql = “update t_user set password=? where account=?”;
7.2.4 创建statement
-
静态
Statement statement = connection.createStatement();
-
预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
7.2.5 发送sql语句并获取返回结果
-
executeUpdate
非DQL 返回值类型 int
-
executeQuery
DQL,返回值类型 ResultSet
7.2.6 查询结果集解析
-
移动光标指向行数据
next() while(next) if(next)
-
获取列数据
get类型(列的下表|列的名称)
-
获取列的信息
getMataData() ResultSetMataData对象包含列的信息
getColumnCount() 获取列的数量
getColumnLabel(下标) 获取列的名称
verManager.getConnection();
-
-
三个参数:DriverManager.getConnection(String url,String user,String password)
-
两个参数:DriverManager.getConnection(String url,Properties info)
info 有两个key : user 和 password
-
一个参数:DriverManager.getConnection(String url)
url?user=xxx&password=xxx
7.2.3 编写SQL语句
-
查询
String sql = “select account,password from t_user”;
-
添加
String sql = “insert into t_user(account,password,nickname) values(?,?,?)”;
-
删除
String sql = “delete from t_user where id=?”;
-
修改
String sql = “update t_user set password=? where account=?”;
7.2.4 创建statement
-
静态
Statement statement = connection.createStatement();
-
预编译
PreparedStatement preparedStatement = connection.prepareStatement(sql);
7.2.5 发送sql语句并获取返回结果
-
executeUpdate
非DQL 返回值类型 int
-
executeQuery
DQL,返回值类型 ResultSet
7.2.6 查询结果集解析
-
移动光标指向行数据
next() while(next) if(next)
-
获取列数据
get类型(列的下表|列的名称)
-
获取列的信息
getMataData() ResultSetMataData对象包含列的信息
getColumnCount() 获取列的数量
getColumnLabel(下标) 获取列的名称
-